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

SenML

Каждый проект изобретает свой JSON вида {"temp": 23.1}, и серверу приходится знать все эти схемы. SenML задаёт одну: массив записей с именем, единицей, значением и временем, которые одинаково читаются в JSON и в CBOR.

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

SenML (Sensor Measurement Lists) — формат представления показаний датчиков и простых параметров, определённый в RFC 8428. Данные — один массив записей (pack), каждая запись — набор полей: имя источника, единица измерения, значение, время. Формат рассчитан так, чтобы устройство с минимальными ресурсами могло закодировать одно измерение, а сервер — эффективно собирать тысячи (разд. 1). Сериализаций четыре: JSON, CBOR, XML и EXI; передаётся обычно по HTTP или CoAP, для которого зарегистрированы Content-Format 110 (senml+json) и 112 (senml+cbor) (разд. 12.5).

Поля записи

ПолеМетка JSONМетка CBORСмысл
Base Namebn−2префикс, приписываемый к именам следующих записей
Base Timebt−3время, прибавляемое к t
Base Unitbu−4единица по умолчанию
Base Value / Base Sumbv / bs−5 / −6слагаемое для v и s
Base Versionbver−1версия формата, по умолчанию 10
Namen0имя датчика или параметра
Unitu1единица измерения
Valuev, vs, vb, vd2, 3, 4, 8число, строка, булево, двоичные данные
Sums5интеграл значения по времени
Timet6время измерения
Update Timeut7максимальный интервал до следующего показания

Таблица 1 RFC 8428 (разд. 4.3). Базовые поля действуют на свою запись и на все последующие, пока не встретится запись с тем же базовым полем; обычные — только на свою (разд. 4). В записи должно быть ровно одно поле значения, если нет Sum (разд. 4.2). Поле ut позволяет серверу заметить, что датчик замолчал.

Пример из разд. 5.1.2 — напряжение и ток одного устройства «сейчас»:

[
  {"bn":"urn:dev:ow:10e2073a01080063:","n":"voltage","u":"V","v":120.1},
  {"n":"current","u":"A","v":1.2}
]

Имя после склейки с bn должно состоять только из символов A–Z, a–z, 0–9, -, :, ., /, _ и начинаться с буквы или цифры; стандарт рекомендует URI или URN — например, адрес 1-Wire или UUID (разд. 4.5.1). Единицы берутся из реестра IANA «SenML Units»: Cel, V, A, W, Hz, lx, Ohm и другие символы СИ; g (грамм) помечен как нерекомендуемый — положено kg (разд. 12.1). Масштабированных единиц в u нет вовсе: SenML требует немасштабированных единиц СИ, и единственное исключение — Cel вместо K (RFC 8798, разд. 2.1). Милливольты и миллисекунды датчик переводит в V и s сам; для таких единиц RFC 8798 завёл отдельный реестр вторичных единиц с масштабом и смещением (ms — s × 1/1000, mV — V × 1/1000, dBm — dBW со смещением −30), но в SenML версии 10 поле u принимает только основные единицы (разд. 3). Двоичное значение vd в JSON — Base64 с URL-безопасным алфавитом без дополнения, в CBOR — байтовая строка.

Время без часов

Время измерения — сумма bt и t (разд. 4.5.3). Значения меньше 2^28 (268 435 456) относительны «сейчас»: 0 — только что, −5 — пять секунд назад, положительные — в будущем, что удобно для команд исполнительным механизмам. Значения от 2^28 — абсолютные секунды Unix с 1970-01-01T00:00Z, так что самая ранняя абсолютная дата — 1978-07-04 21:24:16 UTC. Датчик без синхронизации времени шлёт относительные метки, а шлюз переводит их в абсолютные при приёме. В разд. 5.1.2 ряд токов за последние пять секунд записан как "t":-5 … "t":-1 плюс последняя запись без t, то есть «сейчас», при одном bt на весь пакет.

CBOR и потоки

В CBOR метки заменяются целыми: базовые — отрицательными, остальные — от 0 (разд. 6), так что {"n":"current","t":-4,"v":1.3} превращается в карту {0: "current", 6: -4, 2: 1.3}. Дамп примера из разд. 6 с семью записями заканчивается смещением 0xc3 — 195 байт. Для непрерывной записи есть потоковый вариант SenSML (разд. 4.8): в CBOR массив открывают с неопределённой длиной и читают запись за записью, не дожидаясь конца. Тот же формат годится для настройки: пакет SenML в POST или PUT трактуется как команда установить значения названных ресурсов в заданное время (разд. 4.9). SenML используют с CoAP, HTTP и MQTT; как собрать и разобрать такую запись в прошивке без динамической памяти — в статье о реализации протоколов.

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

Как выглядит минимальная запись SenML?

Массив с одной записью: [{"n":"urn:dev:ow:10e2073a01080063","u":"Cel","v":23.1}] — пример из разд. 1 RFC 8428. Поле n — имя датчика (здесь URN с адресом 1-Wire), u — единица из реестра SenML, v — числовое значение. Времени нет, значит измерение сделано «сейчас». Для булевых, строковых и двоичных значений есть поля vb, vs и vd.

Зачем нужны базовые поля bn, bt, bu?

Чтобы не повторять общее в каждой записи. Базовое поле действует на свою запись и на все следующие, пока не встретится запись с таким же базовым полем. Base Name приписывается спереди к n, Base Time складывается с t, Base Unit подставляется, если u не задано. В примере разд. 5.1.2 bn задаёт устройство один раз, а записи несут только короткие имена voltage и current.

Как SenML кодирует время, если у датчика нет часов?

Относительно момента отправки. Значения Time меньше 2^28 считаются секундами от «сейчас»: 0 — измерение только что, −5 — пять секунд назад, положительные — в будущем, для команд исполнительным механизмам. Значения от 2^28 и выше — абсолютные секунды Unix с 1970 года; поэтому самое раннее абсолютное время в SenML — 4 июля 1978 года. Получатель с точными часами переводит относительные метки в абсолютные при приёме.

Источники

  1. C. Jennings, Z. Shelby, J. Arkko, A. Keranen, C. Bormann. Sensor Measurement Lists (SenML). RFC 8428, August 2018 — разд. 1: формат и медиатипы для простых показаний датчиков в HTTP и CoAP, единственный массив записей, сериализации JSON, CBOR, XML и EXI, пример [{"n":"urn:dev:ow:10e2073a01080063","u":"Cel","v":23.1}]; разд. 4: базовые поля действуют на свою запись и все последующие до записи с тем же базовым полем, обычные — только на свою; разд. 4.1: Base Name, Base Time, Base Unit, Base Value, Base Sum, Base Version (по умолчанию 10); разд. 4.2: Name, Unit, Value — v число, vb булево, vs строка, vd двоичные данные, ровно одно поле значения, если нет Sum; Sum — интеграл в единицах, умноженных на секунды; Time; Update Time — максимальный период до следующего показания; разд. 4.3, табл. 1: метки bn −2, bt −3, bu −4, bv −5, bs −6, bver −1, n 0, u 1, v 2, vs 3, vb 4, vd 8, s 5, t 6, ut 7; vd — Base64 с URL-безопасным алфавитом без дополнения, в CBOR — байтовая строка; разд. 4.5.1: имя из символов A–Z, a–z, 0–9, «-», «:», «.», «/», «_», начинается с буквы или цифры, рекомендованы URI и URN, в том числе адрес 1-Wire и UUID; разд. 4.5.3: время = Base Time + Time, значения меньше 2^28 (268 435 456) — относительно «сейчас» (0 — сейчас, отрицательные — в прошлом), от 2^28 — секунды Unix с 1970-01-01T00:00Z, наименьшее абсолютное время — 1978-07-04 21:24:16 UTC; разд. 4.8: потоковый вариант SenSML; разд. 4.9: конфигурирование и управление через POST или PUT; разд. 5.1.2: пример с bn, voltage 120.1 V и current 1.2 A, затем ряд значений тока с t от −5 до −1 и последняя запись без t при bt 1.276020076001e+09; разд. 6: в CBOR метки — целые, базовые отрицательные, потоковый массив — неопределённой длины, дамп примера заканчивается смещением 0xc3; разд. 12.1: реестр единиц — символы СИ m, kg, s, A, K, Hz, V, Ohm, W, Cel, lx и другие, g помечена как нерекомендуемая; разд. 12.5, табл. 8: CoAP Content-Format 110 senml+json, 111 sensml+json, 112 senml+cbor, 113 sensml+cbor, 114 и 115 exi, 310 и 311 xml
  2. C. Bormann. Additional Units for Sensor Measurement Lists (SenML). RFC 8798, June 2020 — разд. 2, табл. 1: новые основные единицы B, VA, VAs, var, vars, J/m, kg/m3 и deg (помечена как нерекомендуемая); разд. 2.1: SenML требует немасштабированных единиц СИ, единственное исключение — Cel вместо K; разд. 3, табл. 2: реестр вторичных единиц с масштабом и смещением — ms (s, 1/1000), min (s, 60), h (s, 3600), kW (W, 1000), mV (V, 1/1000), mA (A, 1/1000), mm, cm, km (m), KiB (B, 1024), dBm (dBW, масштаб 1, смещение −30); пример: 100 ms → 0,1 s, 10 dBm → −20 dBW; в SenML версии 10 поле u допускает только основные единицы, вторичные — через новую версию или поле с «_» на конце; разд. 4: реестр не скачивать с IANA каждым устройством, а раздавать вместе с обновлением ПО
Страница помогла?

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