Перейти к содержанию

CoAP

Датчик на батарейке не может держать соединение TCP и разбирать заголовки HTTP. CoAP даёт тот же запрос-ответ с методами и кодами, но в одной UDP-датаграмме с заголовком в 4 байта и собственным механизмом повтора.

Обновлено Редакция GAW

CoAP (Constrained Application Protocol) — протокол запрос-ответ для устройств с малой памятью и сетей с потерями, определённый в RFC 7252. Модель та же, что у HTTP: клиент отправляет запрос с методом на ресурс, заданный URI, сервер отвечает кодом и, возможно, представлением ресурса. Но весь обмен идёт поверх UDP — каждое сообщение CoAP занимает одну датаграмму, а надёжность, если она нужна, обеспечивает сам протокол повторной отправкой (RFC 7252, разд. 2).

Четыре типа сообщений

ТипКод TПодтверждениеДля чего
CON (Confirmable)0обязательно ACK или RSTкоманды, настройки, всё, что нельзя потерять
NON (Non-confirmable)1нетрегулярные показания датчика, где важен лишь итог
ACK (Acknowledgement)2—подтверждение CON с тем же Message ID, часто несёт ответ
RST (Reset)3—получатель не может обработать сообщение

Запросы и ответы передаются в CON и NON, ответы — ещё и внутри ACK: если сервер успел подготовить ответ, он кладёт его в само подтверждение (piggybacked, разд. 2.2 и табл. 1 в разд. 4.3). Сообщения связывает 16-битный Message ID; запрос с ответом сопоставляют по Token длиной 0–8 байт (разд. 3). Заголовок фиксированный, 4 байта: версия (всегда 1), тип, длина Token, код и Message ID; за ним Token, опции в формате TLV и, после маркера 0xFF, полезная нагрузка.

Повтор и таймауты

Сообщение CON отправитель повторяет, пока не получит ACK или RST. Первый таймаут выбирается случайно между ACK_TIMEOUT и ACK_TIMEOUT × ACK_RANDOM_FACTOR, затем удваивается; попыток — MAX_RETRANSMIT (разд. 4.2). Значения по умолчанию из табл. 2 и 3 RFC 7252:

ПараметрЗначениеСмысл
ACK_TIMEOUT2 снижняя граница первого таймаута
ACK_RANDOM_FACTOR1,5верхняя граница — 3 с
MAX_RETRANSMIT4число повторов
NSTART1одновременных неподтверждённых обменов с одним адресатом
MAX_TRANSMIT_SPAN45 сот первой отправки до последнего повтора
MAX_TRANSMIT_WAIT93 скогда отправитель прекращает ждать ACK
EXCHANGE_LIFETIME247 ссколько хранить состояние обмена

Снижать ACK_TIMEOUT ниже 1 с стандарт запрещает без собственного контроля перегрузки (разд. 4.8.1). Для сети с потерями это означает: команда реле может дойти через десятки секунд, и прошивка должна это учитывать.

Методы, коды и URI

Методов четыре (разд. 5.8): GET возвращает представление ресурса (2.05 Content), POST обрабатывает присланные данные и может создать ресурс (2.01 Created) или изменить его (2.04 Changed), PUT заменяет или создаёт ресурс по заданному URI, DELETE удаляет (2.02 Deleted). GET, PUT и DELETE идемпотентны, POST — нет. Коды ответов записываются как «класс.деталь»: 2.xx — успех, 4.xx — ошибка клиента (4.04 Not Found, 4.13 Request Entity Too Large), 5.xx — ошибка сервера (5.03 Service Unavailable).

Адрес ресурса — coap://host[:port]/path?query, порт по умолчанию UDP 5683; coaps:// означает CoAP поверх DTLS, порт 5684 (разд. 6.1, 6.2). Список ресурсов сервер отдаёт по /.well-known/core в формате CoRE Link Format (разд. 7.2), а для поиска серверов в сети выделены групповые адреса 224.0.1.187 и FF0X::FD (разд. 12.8).

Размеры и расширения

Если MTU пути неизвестен, RFC 7252 (разд. 4.6) советует считать его равным 1280 байт и не превышать 1152 байта на сообщение и 1024 байта на полезную нагрузку; в 6LoWPAN кадр канального уровня — 127 байт, поэтому большие данные передают блоками. Подписку на изменения ресурса без опроса добавляет опция Observe, компактную полезную нагрузку обычно кодируют в CBOR. Шифрование — четыре режима: NoSec, PreSharedKey, RawPublicKey, Certificate (разд. 9); DTLS добавляет около 13 байт на датаграмму.

В прошивке

В Zephyr библиотека CoAP включается опцией CONFIG_COAP и работает с обычными буферами: сокет UDP создаёт приложение, а библиотека разбирает и собирает пакеты (coap_packet_init с COAP_TYPE_CON и COAP_METHOD_GET); поддержаны RFC 7252, 6690, 7959, 7641 и OSCORE, а поверх CoAP реализован LwM2M. Как устроить разбор такого бинарного протокола на микроконтроллере, разобрано в статье о реализации протоколов. Если же нужен обмен через брокер, а не адресный запрос к устройству, смотрите MQTT.

Частые вопросы

Чем CoAP отличается от MQTT?

Моделью обмена и транспортом. CoAP — запрос-ответ с методами GET, POST, PUT, DELETE и кодами вроде 2.05 или 4.04, как у HTTP, но поверх UDP, без брокера: клиент обращается к ресурсу на устройстве по URI coap://host/path. MQTT — «издатель — подписчик» через брокер поверх TCP. CoAP удобен, когда датчик нужно опрашивать и настраивать адресно, а MQTT — когда многим получателям нужны одни и те же данные.

Сколько раз и с каким интервалом CoAP повторяет сообщение?

По RFC 7252 (разд. 4.2, 4.8) подтверждаемое сообщение CON повторяют до MAX_RETRANSMIT = 4 раз. Первый таймаут случайный, от ACK_TIMEOUT = 2 с до 2 × 1,5 = 3 с, и удваивается после каждого повтора. Вся серия укладывается в MAX_TRANSMIT_SPAN = 45 с, а отправитель окончательно сдаётся через MAX_TRANSMIT_WAIT = 93 с. Сообщения NON не повторяются вовсе.

Какой порт у CoAP и нужен ли TCP?

CoAP по RFC 7252 работает поверх UDP: порт 5683 для схемы coap:// и 5684 для coaps://, то есть CoAP поверх DTLS. Сервер, отдающий список ресурсов /.well-known/core, обязан слушать 5683. TCP для CoAP в RFC 7252 не определён, надёжность обеспечивает сам протокол повтором сообщений CON.

Источники

  1. Z. Shelby, K. Hartke, C. Bormann. The Constrained Application Protocol (CoAP). RFC 7252, June 2014 — разд. 2: модель клиент — сервер как у HTTP, обмен асинхронный поверх UDP, четыре типа сообщений Confirmable, Non-confirmable, Acknowledgement, Reset; разд. 2.1: фиксированный заголовок 4 байта, 16-битный Message ID даёт около 250 сообщений в секунду при параметрах по умолчанию, CON повторяется с экспоненциальной задержкой до ACK, RST — если получатель не может обработать сообщение, NON не подтверждается; разд. 2.2: ответ на CON-запрос может ехать в самом ACK (piggybacked); разд. 3: Ver = 1, тип 0 CON, 1 NON, 2 ACK, 3 RST, Token 0–8 байт, Code — класс 0 запрос, 2 успех, 4 ошибка клиента, 5 ошибка сервера, 0.00 — пустое сообщение, маркер полезной нагрузки 0xFF; разд. 4.2: первый таймаут случайный между ACK_TIMEOUT и ACK_TIMEOUT × ACK_RANDOM_FACTOR, удваивается, попыток MAX_RETRANSMIT; разд. 4.3: NON для регулярных показаний датчика, таблица 1 — запросы и ответы в CON и NON, ответы и в ACK; разд. 4.6: при неизвестном Path MTU считать IP MTU 1280 байт, верхние границы 1152 байта на сообщение и 1024 байта на полезную нагрузку, кадр 6LoWPAN 127 байт; разд. 4.8, табл. 2: ACK_TIMEOUT 2 с, ACK_RANDOM_FACTOR 1,5, MAX_RETRANSMIT 4, NSTART 1, DEFAULT_LEISURE 5 с, PROBING_RATE 1 байт/с; разд. 4.8.1: ACK_TIMEOUT ниже 1 с нарушает RFC 5405; разд. 4.8.2, табл. 3: MAX_TRANSMIT_SPAN 45 с, MAX_TRANSMIT_WAIT 93 с, MAX_LATENCY 100 с, PROCESSING_DELAY 2 с, MAX_RTT 202 с, EXCHANGE_LIFETIME 247 с, NON_LIFETIME 145 с; разд. 5.8: GET безопасен и идемпотентен (2.05 Content, 2.03 Valid), POST ни то ни другое (2.01 Created, 2.04 Changed, 2.02 Deleted), PUT и DELETE идемпотентны (2.04 или 2.01; 2.02), неизвестный метод — 4.05; разд. 5.9: 4.04 Not Found, 4.13 Request Entity Too Large, 5.03 Service Unavailable; разд. 6.1: схема coap, порт UDP 5683 по умолчанию, префикс /.well-known/; разд. 6.2: схема coaps, порт 5684, обязателен DTLS; разд. 7.1: порт 5683 обязателен для сервера, отдающего список ресурсов; разд. 7.2: описание ресурсов в CoRE Link Format RFC 6690 по /.well-known/core; разд. 9: режимы NoSec, PreSharedKey, RawPublicKey, Certificate, обязательны NoSec и RawPublicKey; разд. 9.1: DTLS добавляет около 13 байт на датаграмму без учёта nonce и имитовставки; разд. 9.1.3.1: обязательный набор TLS_PSK_WITH_AES_128_CCM_8; разд. 12.8: групповые адреса «All CoAP Nodes» 224.0.1.187 и FF0X::FD
  2. Zephyr Project. Zephyr Project Documentation, latest: Networking APIs — CoAP — библиотека включается опцией CONFIG_COAP, роли клиента и сервера, работает с обычными буферами — сокеты создаёт приложение; поддерживаются RFC 7252, 6690, 7959, 7641, 8613 (не целиком); поверх CoAP реализован LwM2M; в примере запрос собирают coap_packet_init с типом COAP_TYPE_CON и методом COAP_METHOD_GET, ресурс /.well-known/core добавляют первым
Страница помогла?

Нашли ошибку? ·