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_TIMEOUT | 2 с | нижняя граница первого таймаута |
| ACK_RANDOM_FACTOR | 1,5 | верхняя граница — 3 с |
| MAX_RETRANSMIT | 4 | число повторов |
| NSTART | 1 | одновременных неподтверждённых обменов с одним адресатом |
| MAX_TRANSMIT_SPAN | 45 с | от первой отправки до последнего повтора |
| MAX_TRANSMIT_WAIT | 93 с | когда отправитель прекращает ждать ACK |
| EXCHANGE_LIFETIME | 247 с | сколько хранить состояние обмена |
Снижать 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.
Источники
- 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
- 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 добавляют первым
Нашли ошибку? ·
Смотрите также
- UDPДатаграммы без соединения: заголовок 8 байт, порты, нет гарантий доставки
- DTLSВариант TLS для UDP: явные номера записей, фрагментация и повтор рукопожатия, cookie; используется с CoAP (coaps, порт 5684)
- CoAP ObserveРасширение CoAP: GET с опцией Observe регистрирует наблюдателя, сервер присылает уведомления при изменении ресурса
- Блочная передача CoAP (Block1/Block2)Передача больших тел CoAP блоками 16–1024 байт через опции Block1 (запрос) и Block2 (ответ)
- CBORДвоичный формат сериализации с моделью данных JSON плюс байтовые строки и теги; штатная полезная нагрузка CoAP
- MQTTПротокол издатель — подписчик через брокер: топики, QoS, retain, Last Will
- 6LoWPANIPv6 поверх IEEE 802.15.4: сжатие заголовков IPHC, фрагментация под кадр 127 байт, MTU 1280
- Реализация протокола обменаКадры по паузе, длине и разделителю, COBS, CRC-16, таймауты, разбор потока