91. Платформы интернета вещей
Платформа — программное обеспечение между приборами и приложениями. Она подключает приборы, хранит их данные, выполняет правила, показывает графики и отдаёт данные наружу. Раздел отвечает на четыре вопроса: - из чего состоит платформа; - какие платформы бывают; - как выбирать; - почему прошивка не должна зависеть от конкретной платформы.
Проверено опытом: настоящая открытая платформа ThingsBoard в контейнере и тот же код MQTT прибора, что в разделе 87. Добавилось одно — токен в поле имени пользователя.
Как это называется в документации
Оригинал Перевод IoT platform платформа интернета вещей device provisioning заведение приборов access token токен доступа прибора telemetry, attributes телеметрия (временной ряд), свойства (текущее состояние) RPC — remote procedure call команда прибору с ответом rule engine, rule chain движок правил, цепочка правил dashboard панель показателей multi-tenancy несколько независимых клиентов на одной установке cloud (SaaS), self-hosted (on-premises) облачная услуга, своя установка vendor lock-in привязка к поставщику
91.1 Зачем платформа
В любом проекте с приборами приходится решать одни и те же задачи: - вести учёт приборов и их ключей; - хранить данные; - поднимать тревоги по правилам; - показывать графики; - давать права пользователям; - открывать программный интерфейс для других систем.
Прибор у каждого свой, а эти задачи повторяются из проекта в проект. Платформа берёт их на себя. Без неё всё это пишут сами: сервер из раздела 94, базу, правила, интерфейс пользователя — и сопровождают годами.
91.2 Из чего состоит платформа
| Часть | Что делает | В опыте |
|---|---|---|
| подключение и приведение к единому виду | брокер MQTT, приём CoAP и HTTP, единый формат данных | брокер на порту 1883, телеметрия в JSON |
| управление приборами | регистрация, ключи, настройки, состояние, обновление прошивки | прибор заведён через программный интерфейс, выдан токен |
| база данных | временные ряды и свойства | три значения и два свойства |
| обработка и действия | правила: сохранить, сравнить с порогом, поднять тревогу, послать команду | цепочка правил по умолчанию сохранила данные |
| аналитика | сводки, отклонения, прогнозы | — |
| визуализация | панели и графики | — |
| служебные инструменты | пользователи, права, клиенты | вход администратора клиента |
| внешние интерфейсы | REST, MQTT для приложений, интеграции | данные прочитаны и команда отправлена через REST |
Для прибора из этого важны три вещи: как подключиться, куда слать и откуда ждать команд. Всё остальное происходит на стороне платформы.
91.3 Опыт: прибор на ThingsBoard
Платформа ThingsBoard запущена в контейнере со встроенной базой. Прибор заведён через её REST, после чего «прибор» — программа на C — подключился к её брокеру:
| Шаг | Что произошло |
|---|---|
| прибор заведён через REST | платформа выдала токен доступа — 20 символов |
| подключение с чужим токеном | отказ уже в CONNACK, код 5 — «не авторизован» |
| подключение со своим токеном | CONNACK с кодом 0 |
подписка на v1/devices/me/rpc/request/+ |
SUBACK, выдано QoS 0 |
свойства {"fw":"1.0.3","sf":7} в v1/devices/me/attributes |
сохранены как свойства прибора |
три значения в v1/devices/me/telemetry |
сохранены как временной ряд: 21,5, 21,75 и −12,34 |
команда setInterval через REST |
пришла прибору по MQTT, ответ {"ok":true,"interval":900} вернулся в REST |
Прибору понадобились три новых кусочка к пакетам из раздела 87:
/* CONNECT с именем пользователя и чистой сессией: флаги 0x82 */
size_t mqtt_connect_user(uint8_t *buf, const char *client_id, const char *user, uint16_t keepalive)
{
uint32_t rem = 10u + 2u + (uint32_t)strlen(client_id) + 2u + (uint32_t)strlen(user);
size_t k = 0;
buf[k++] = 0x10;
k += mqtt_put_len(buf + k, rem);
k += put_str(buf + k, "MQTT");
buf[k++] = 4;
buf[k++] = 0x82;
buf[k++] = (uint8_t)(keepalive >> 8);
buf[k++] = (uint8_t)keepalive;
k += put_str(buf + k, client_id);
k += put_str(buf + k, user);
return k;
}
/* Разбор PUBLISH с QoS 0: тема и данные указывают внутрь пакета.
* Вернёт 0 или −1, если это не такой PUBLISH или пакет обрезан. */
int mqtt_parse_publish(const uint8_t *p, size_t n, const char **topic, size_t *tlen,
const uint8_t **data, size_t *dlen)
{
if (n < 2 || (p[0] & 0xF0) != 0x30 || (p[0] & 0x06))
return -1;
size_t k = 1, rem = 0, mul = 1;
do {
if (k >= n || k > 4)
return -1;
rem += (p[k] & 127u) * mul;
mul *= 128;
} while (p[k++] & 128);
if (rem < 2 || k + rem > n)
return -1;
size_t tl = ((size_t)p[k] << 8) | p[k + 1];
if (2 + tl > rem)
return -1;
*topic = (const char *)p + k + 2;
*tlen = tl;
*data = p + k + 2 + tl;
*dlen = rem - 2 - tl;
return 0;
}
/* Номер команды из темы v1/devices/me/rpc/request/<номер>; −1 — не команда */
long tb_rpc_id(const char *topic, size_t tlen)
{
static const char pre[] = "v1/devices/me/rpc/request/";
size_t pl = sizeof pre - 1;
if (tlen <= pl || memcmp(topic, pre, pl) != 0)
return -1;
long id = 0;
for (size_t i = pl; i < tlen; i++) {
if (topic[i] < '0' || topic[i] > '9')
return -1;
id = id * 10 + (topic[i] - '0');
}
return id;
}
Команда приходит обычной публикацией в тему, на которую прибор
подписан. Прибор отвечает в тему …/rpc/response/<тот же номер>, и по
номеру платформа находит, кто ждал ответа. Разбор ничего не копирует:
тема и данные указывают прямо в принятый пакет, стека уходит 16 байт.
Телеметрия собирается из сотых долей градуса без float, как в
разделе 88. Отправляется она той же mqtt_publish из раздела 87.
Пакеты CONNECT и SUBSCRIBE независимо пересобраны на Python.
Телеметрия и свойства — разные вещи. Телеметрия — временной ряд: у каждого значения своя отметка времени, история хранится. Свойство — текущее состояние: версия прошивки, SF, интервал отправки. Хранится последнее значение. Версию прошивки как телеметрию не шлют: получится тысяча одинаковых точек на графике. Настройки платформа тоже держит свойствами и может сама отправить их прибору.
Токен — это пароль. Он у каждого прибора свой, хранится как ключ (раздел 43), его можно отозвать. В опыте прибор подключался к порту 1883 без шифрования — токен в пакете CONNECT шёл открытым текстом, и его прочтёт любой, кто слушает сеть. В работе — порт 8883 с TLS (раздел 37.4). Для больших парков вместо токенов выдают сертификаты.
91.4 Какие бывают платформы
Одна платформа редко закрывает всё, и обычно это цепочка:
| Вид | Что делает | Примеры |
|---|---|---|
| платформа связи | подключение по своей технологии | сетевой сервер LoRaWAN (раздел 94), платформы операторов для SIM-карт NB-IoT |
| облачная | брокер, учёт приборов, правила, хранение как услуга | AWS IoT Core, Azure IoT Hub |
| платформа приборов | учёт, настройки, обновление прошивки | часто входит в облачную |
| аналитическая | обработка больших данных, прогнозы | отдельные сервисы |
| открытая для своей установки | всё перечисленное на своих серверах | ThingsBoard, ChirpStack; есть и отечественные |
⚠️ Платформы закрываются. В 2023 году перестали работать Google Cloud IoT Core и IBM Watson IoT Platform. Их клиенты переводили приборы, которые уже стояли на объектах, на другие платформы. Прибор, у которого адрес сервера и способ входа зашиты в прошивку намертво, в такой день становится мусором.
91.5 Облако или своя установка
| Облачная услуга | Своя установка | |
|---|---|---|
| начать | за день | нужно развернуть и настроить (раздел 87) |
| сопровождение | у поставщика | ваше: обновления, копии, наблюдение (раздел 90.7) |
| цена | за прибор и за сообщения | серверы и люди |
| где данные | у поставщика, иногда в другой стране | у вас — важно, если закон требует хранить данные в стране |
| уйти | зависит от выгрузки данных | всё ваше |
Цена облака растёт с числом сообщений, и здесь окупается раздел 90.4. 1000 приборов по 98 сообщений в сутки — это 2,94 миллиона сообщений в месяц. Если слать каждую секунду — 2,59 миллиарда.
«Строить или покупать» решают трезво. Прибор у вас уникален, а учёт, хранение и графики — нет. Своя платформа — это не разработка на месяц, а сопровождение на годы.
91.6 Как выбирать
| Вопрос | Зачем |
|---|---|
| какие протоколы: MQTT, CoAP, HTTP, приём от сети LoRaWAN | прибор должен говорить стандартом, а не библиотекой платформы |
| как заводить тысячи приборов | вручную тысячу токенов не раздать |
| есть ли обновление прошивки по воздуху | ошибка найдётся после установки (раздел 48) |
| правила и тревоги | что платформа сделает без программиста |
| программный интерфейс и выгрузка данных | это ваш выход с платформы |
| где хранятся данные | требования закона и заказчика |
| сколько стоит при вашем потоке | считать по потокам данных из проекта (раздел 90.7) |
| кто поставщик: история, планы, сообщество | будет ли платформа через пять лет |
| безопасность | шифрование канала, права пользователей, журнал действий |
91.7 Прошивка, которая переживёт платформу
- Стандартный протокол. Прибор говорит на MQTT или CoAP. Опыт это показал: код из раздела 87 заработал с ThingsBoard, когда в подключение добавили имя пользователя.
- Всё платформенное — в настройках. Адрес сервера, темы, имена полей и токен лежат в настройках прибора и меняются по воздуху, а не в константах прошивки.
- Прослойка. Остальная программа знает только «отправить измерение» и «принять команду». Под платформу пишется небольшой переходник.
- Автономность. Без платформы прибор продолжает работать и копит данные (раздел 90.6).
91.8 Грабли
Прибор написан на фирменной библиотеке платформы. Платформа закрылась или подорожала, а переделать прошивку на тысячах приборов нельзя.
Один токен на все приборы. Украли у одного — подделали всех.
Версия прошивки в телеметрии. На графике тысяча одинаковых точек, а текущее значение не найти. Это свойство.
Команда уходит в тайм-аут. Прибор на LoRaWAN класса A спит, и команда должна ждать в очереди сервера (раздел 94.6), а не в синхронном вызове.
Нет выгрузки данных. С платформы вас не отпустят.
Счёт за облако вырос в тысячу раз. Прибор шлёт каждую секунду.
Демонстрационные учётные записи платформы оставлены. Их создаёт установка, и о них знают все. Меняют их первым делом.
91.9 Итоги
- Платформа закрывает общие задачи: подключение, учёт приборов, хранение, правила, графики и внешние интерфейсы.
- ThingsBoard в контейнере принял прибор на том же MQTT, что в разделе 87, с токеном в поле имени пользователя. Чужой токен отвергнут в CONNACK. Данные и свойства сохранены. Команда через REST дошла до прибора, ответ вернулся.
- Телеметрия — временной ряд, свойства — текущее состояние.
- Платформы закрываются: прибор говорит стандартом, а всё платформенное держит в настройках, которые меняются по воздуху.
- Облако быстрее на старте, своя установка даёт контроль и оставляет данные у вас. Цена облака растёт с числом сообщений.
Дальше: раздел 92 «Радиообследование и карта покрытия».