CoAP Observe
Опрашивать датчик раз в секунду — тратить радио и батарейку впустую. Observe позволяет один раз отправить GET и дальше получать новое представление ресурса только тогда, когда оно изменилось.
Обновлено Редакция GAW
CoAP Observe — расширение CoAP, определённое в RFC 7641: клиент один раз отправляет GET с опцией Observe, а сервер затем присылает ему новое представление ресурса при каждом изменении состояния. Это реализация шаблона «наблюдатель — субъект»: субъект — ресурс на сервере CoAP, наблюдатель — клиент, регистрация — расширенный GET, уведомление — дополнительный ответ на тот же самый запрос (RFC 7641, разд. 1.2). Так датчик температуры сообщает о новом значении, не заставляя клиента опрашивать его по таймеру.
Как проходит обмен
| Шаг | Сообщение | Содержимое |
|---|---|---|
| регистрация | GET /temperature, Token 0x4a, Observe: 0 | клиент просит добавить себя в список наблюдателей |
| первое уведомление | 2.05 Content, Token 0x4a, Observe: 12 | текущее состояние ресурса |
| следующие | 2.05 Content, Token 0x4a, Observe: 44, 60, … | состояние после каждого изменения |
Пример из разд. 1.2 RFC 7641. Все уведомления несут Token клиента, по нему клиент и сопоставляет их с запросом (разд. 4.2). Опция Observe имеет номер 6, формат uint длиной 0–3 байта (разд. 2, табл. 1). В запросе значение 0 — регистрация, 1 — отписка. Опция не критическая: сервер, который не умеет или не хочет наблюдать ресурс, отвечает на GET как на обычный, без опции Observe, и клиенту остаётся опрос.
Порядок и свежесть
Датаграммы UDP могут приходить не по порядку, а клиент должен считать свежим то уведомление, которое отправлено последним. Поэтому в уведомлении опция Observe содержит 24 младших бита строго растущего номера (разд. 3.4). Пришедшее уведомление новее предыдущего, если выполнено одно из условий:
V1 < V2 и V2 − V1 < 223, V1 > V2 и V1 − V2 > 223, T2 > T1 + 128 с
где V — значения опции, T — локальное время получения. Третье условие позволяет не сравнивать номера после паузы дольше 128 с — число выбрано как «круглое» и большее MAX_LATENCY из RFC 7252.
Обязанности сервера
- Уведомление может быть CON или NON независимо от типа запроса (разд. 3.5, 4.5); для редких изменений разумнее CON, для частых — NON, а после серии изменений сервер должен довести до клиента последнее состояние, например повторив его в CON.
- Сервер держит не более NSTART (1 по умолчанию) неподтверждённых уведомлений на клиента и без оценки RTT отправляет не чаще одного NON-уведомления в 3 с (разд. 4.5.1).
- Если уведомления идут в основном в NON, хотя бы раз в 24 часа сервер обязан отправить CON — иначе исчезнувший клиент останется в списке навсегда (разд. 4.5).
- Content-Format уведомлений не меняется; если формат больше недоступен — 4.06 Not Acceptable и удаление наблюдателя. Если ресурс удалён, приходит уведомление 4.04 без опции Observe, и запись тоже удаляется (разд. 3.2, 4.2).
Отписка и практика
Клиент может просто «забыть» наблюдение: на следующее уведомление с незнакомым Token он ответит RST, и сервер уберёт запись (разд. 3.6). Явная отписка — GET с тем же Token и Observe = 1. Для устройства в спящем режиме Observe удобнее опроса: радио включается только тогда, когда есть новое значение, а CON-уведомления сервер повторит по правилам CoAP, если приёмник ещё спал. Большое представление ресурса сервер может доставлять блоками — RFC 7959 описывает сочетание Observe и Block2. В ссылках /.well-known/core ресурс помечают атрибутом obs — это подсказка клиенту, а не обещание (разд. 6).
С чем не путать: Observe — не публикация через брокер, как в MQTT. Здесь нет посредника, каждый наблюдатель регистрируется на самом устройстве, и устройство хранит список наблюдателей в своей памяти — для микроконтроллера это ограничение на число клиентов, которое стоит заложить при реализации протокола. Библиотека CoAP в Zephyr (CONFIG_COAP) заявляет поддержку RFC 7641 с оговоркой, что реализованы не все части стандарта; сокеты UDP при этом открывает само приложение, а библиотека только разбирает и собирает пакеты в его буферах.
Частые вопросы
Как клиент CoAP подписывается на изменения ресурса?
Отправляет обычный GET с опцией Observe = 0. Если сервер поддерживает наблюдение, он отвечает 2.05 Content с опцией Observe и добавляет клиента (адрес плюс Token) в список наблюдателей. Дальше каждое изменение ресурса приходит как ещё один ответ на тот же запрос с тем же Token. Если сервер наблюдение не поддерживает, он просто ответит на GET без опции Observe — клиенту придётся опрашивать ресурс самому.
Как отписаться от уведомлений CoAP?
Два способа по RFC 7641 (разд. 3.6). Простой — забыть про подписку: следующее уведомление придёт с незнакомым Token, клиент ответит RST, и сервер удалит запись. Явный — отправить GET с тем же Token и Observe = 1; сервер удалит запись и обработает GET как обычный запрос. Сервер и сам удаляет наблюдателя, если CON-уведомление не подтверждено после всех повторов.
Что делать, если уведомления приходят не по порядку?
Сравнивать значения опции Observe: сервер пишет в неё 24 младших бита растущего номера. Уведомление новее, если его номер V2 больше V1 с учётом переполнения (V2 − V1 < 2^23), либо если с момента предыдущего прошло больше 128 с — тогда номер можно не проверять. Самое свежее — то, что отправлено последним, а не то, что пришло последним.
Источники
- K. Hartke. Observing Resources in the Constrained Application Protocol (CoAP). RFC 7641, September 2015 — разд. 1.2: шаблон «наблюдатель — субъект», регистрация расширенным GET, каждое уведомление — дополнительный ответ на тот же запрос с полным представлением ресурса и тем же Token, пример с Observe: 0 в запросе и Observe: 12, 44, 60 в уведомлениях с температурой; клиент остаётся в списке, пока сервер уверен в его интересе, удаление при отписке, отклонении уведомления или истечении повторов; разд. 2, табл. 1: опция номер 6, Unsafe, не входит в Cache-Key, формат uint 0–3 байта, в запросе 0 — регистрация, 1 — отписка, если сервер не может добавить наблюдателя, запрос работает как обычный GET без опции в ответе; разд. 3.1: клиент не регистрируется дважды на один ресурс; разд. 3.2: уведомления обычно 2.05 Content (2.03 Valid при ETag без полезной нагрузки), при ошибке ресурса уведомление с кодом вроде 4.04 без опции Observe и удаление из списка; разд. 3.4: значение опции — 24 младших бита строго растущего номера, условия свежести V1 < V2 и V2 − V1 < 2^23, либо V1 > V2 и V1 − V2 > 2^23, либо прошло более 128 с (128 с выбрано как больше MAX_LATENCY); разд. 3.5: уведомление может быть CON или NON независимо от типа запроса, незнакомый Token в CON-уведомлении — RST; разд. 3.6: отписка — «забыть» наблюдение и ответить RST на следующее уведомление либо явный GET с Observe = 1 и тем же Token; разд. 4.2: уведомления обязаны повторять Token клиента, Content-Format не меняется, иначе 4.06 и удаление; разд. 4.5: сервер может пропускать уведомления в серии изменений, но обязан довести до клиента последнее состояние, при преимущественно NON-уведомлениях хотя бы раз в 24 часа отправлять CON; разд. 4.5.1: не более NSTART (1) неподтверждённых уведомлений на клиента, без оценки RTT — не чаще одного NON-уведомления в 3 с; разд. 6: атрибут obs в ссылках CoRE Link Format как подсказка; разд. 8: номер опции 6 в реестре IANA
- Zephyr Project. Zephyr Project Documentation, latest: Networking APIs — CoAP — библиотека CoAP (CONFIG_COAP) заявляет поддержку RFC 7641 наряду с RFC 7252, 6690, 7959 и 8613 с оговоркой, что поддержаны не все части этих RFC; библиотека работает с обычными буферами и сокетов не создаёт — их открывает приложение
Нашли ошибку? ·
Смотрите также
- CoAPПротокол запрос-ответ поверх UDP для ограниченных устройств: типы сообщений, методы, таймауты, порт 5683
- Блочная передача CoAP (Block1/Block2)Передача больших тел CoAP блоками 16–1024 байт через опции Block1 (запрос) и Block2 (ответ)
- UDPДатаграммы без соединения: заголовок 8 байт, порты, нет гарантий доставки
- MQTTПротокол издатель — подписчик через брокер: топики, QoS, retain, Last Will
- Режимы снаSleep mode: Idle, Power-down, пробуждение и ток
- Реализация протокола обменаКадры по паузе, длине и разделителю, COBS, CRC-16, таймауты, разбор потока