Перейти к содержимому

Node-RED — MQTT-событие в HTTP ​

Устройство публикует готовое событие в MQTT. Node-RED подписывается на тему, преобразует его в HTTP-запрос и отправляет в Депешер. Входящего MQTT-протокола у Депешера нет; брокер и мост работают у вас.

text
MQTT in → JSON → Function → HTTP request → Debug статуса

Пример использует стандартные узлы Node-RED. Подходит и для другого источника flow: вместо MQTT in подключите узел, который выдаёт такой же объект события.

Подготовьте канал и окружение ​

Создайте защищённый входящий канал по IoT-инструкции и выберите способы доставки. Задайте шаблон:

text
Объект: {{json.site.name}}
Датчик: {{json.device.id}}
Событие: {{json.event.type}}

В окружении процесса Node-RED задайте DEPESHER_URL и DEPESHER_TOKEN со своими значениями и перезапустите процесс. Для контейнера это переменные сервиса. Их чтение в Function поддерживается через environment variables.

Соберите flow ​

  1. Добавьте mqtt in, укажите свой брокер и тему building/kitchen/events. Не указывайте адрес Депешера как MQTT-брокер.
  2. Выберите строковый выход и подключите узел json, преобразующий строку в объект. Если mqtt in уже настроен выдавать JSON-объект, второй раз декодировать его не нужно. Это описано в MQTT JSON recipe.
  3. Добавьте function со следующим кодом:
javascript
const source = msg.payload;
const url = env.get("DEPESHER_URL");
const token = env.get("DEPESHER_TOKEN");

if (!url || !token) {
  node.error("Не заданы настройки Депешера");
  return null;
}

if (msg.retain === true) {
  return null;
}

if (!source || !["leak_detected", "restored"].includes(source.event_type)) {
  node.warn("Пропущено неизвестное событие датчика");
  return null;
}

msg.url = url;
msg.method = "POST";
msg.headers = {
  "Content-Type": "application/json",
  Authorization: `Bearer ${token}`,
};
msg.payload = JSON.stringify({
  site: { name: "Дом" },
  device: { id: "kitchen-water" },
  event: { type: source.event_type },
});

return msg;
  1. Подключите http request: метод из msg.method, URL из msg.url — поле URL оставьте пустым, Return → UTF-8 string. Заголовки передаются через msg.headers, как в официальном примере.
  2. После HTTP request добавьте debug только для msg.statusCode. Для ошибок узлов добавьте catch, связанный с Debug сообщения ошибки. Не выводите весь объект с URL/Authorization в обычный журнал.
  3. Нажмите Deploy.

Фильтр msg.retain пропускает сохранённые брокером события после переподключения. QoS не гарантирует отсутствие дубликатов. Отправляйте события перехода отдельной темой, а ограничение частоты измерений задавайте до HTTP Request.

Проверьте без физического датчика ​

Подключите inject к Function и выберите JSON payload:

json
{ "event_type": "leak_detected" }

Нажмите Inject: Debug должен показать 202, в истории должно появиться новое сообщение:

text
Объект: Дом
Датчик: kitchen-water
Событие: leak_detected

Затем отправьте {"event_type":"restored"} и проверьте второе событие. {"event_type":"reading"} должно быть пропущено Function без HTTP-запроса. После этого проверьте такие же публикации в MQTT-тему и получение в Депешере.

Ответ 202 относится к приёму HTTP, а не к доставке. При 401 сверяйте токен, при 429 учитывайте Retry-After; Function сам по себе не ставит неудачные запросы в очередь. Правила разной важности настраиваются как в рецепте Home Assistant, ответы — в HTTP-справке.