Энергия, тепло и вода часть третья: выходим в радио

в 10:00, , рубрики: 433mhz, IoT, mqtt, water leak, zabbix, Интернет вещей, протечки, умный дом

Вступление

В процессе выбора решений для умного дома я стараюсь обходить коробочные решения, требующие наличие связи с внешними облаками или имеющие собственные приложения, особенно решения без возможности прямого подключения к устройству. Все доступные метрики сводятся в один интерфейс — zabbix, там же организовывается система оповещений заинтересованных лиц. Ручки управления реализуются в локально расположенном веб-интерфейсе.

Предыдущие статьи:

часть первая (1wire температура, ups, водосчетчик...) habr.com/ru/post/446864
часть вторая (netping, gidrolock, датчики давления...) habr.com/ru/post/447572

Решаемые задачи в этой статье:

  • Масштабируемая, гибкая система защиты от протечек воды с оповещением через zabbix
  • Прочие устройства на 433mhz: звонок, открытие двери и т п
  • Запихиваем 1wire в MQTT

Система защиты от протечек

Требования к системе:

  • множество датчиков, раскиданных по дому (в моём случае — 6 штук в разных локациях)
  • никаких проводов у датчиков
  • быстрое закрытие при обнаружении утечки
  • вся информация о текущем состоянии в zabbix. Там же — оповещение

Состав системы

  • Raspberry PI
  • RTL2832U USB тюнер
  • Датчики протечек 433mhz
  • Netping + кран gidrolock (см предыдущую статью) для перекрытия магистрали

Про железо

В предыдущей статье я описывал решение перекрытия водоснабжения при помощи netping. У меня имеется один проводной датчик для этого решения. Это удобно, если все точки, где может произойти протечка, находятся примерно в одном месте. В моём случае netping установлен прямо на входе магистрали и там же управляет электро-механическим краном gidrolock (см предыдущую статью). Раскидывать netping+gidrolock+проводной датчик по всем точкам — дорого и громоздко. К тому же у меня уже нет возможности протаскивать новые провода по всему дому. Занимать розетки и втюхивать электрокраны — так себе решение. Решение ожидаемое — используем перекрытие общей магистрали на основе сигналов от раскинутых по локациям радио-датчиков.
Из найденного в интернете — куча различных радио-датчиков от готовых систем. Некоторые можно купить отдельно, контроллеры к датчикам покупать не стал, чтобы не плодить дополнительных элементов в схеме.

Чем можно ловить 433mhz? Оказывается — тв-тюнером на определённом чипсете. И стоит он сейчас копейки (я взял на авито за 300р) вот такой:

image

Заказал к нему отдельную антенку на 12dbi, т к текущая не покрывала весь дом.

Поскольку я пытался минимизировать управляющие компоненты схемы, было желание затянуть тюнер в свой домашний роутер с Openwrt, который и являлся до этого момента ядром решения умного дома для 1wire, modbus, wifi датчиков/протоколов, но, к сожалению, я исчерпал часть его ресурсов (заканчивается место на встроенной флешке под нужный софт, процессор чем-то догружать — уже будут проблемы с работой сети, а нам ещё 4k смотреть в online:), +на USB уже слишком много всего навешено, что влияет на стабильность сбора данных). Решено постепенно выносить функционал умного дома на внешнее устройство — rarpberry pi (под рукой оказалась одна из первых версий).

Про софт

Наигравшись с тв-тюнером в sdr-sharp на стационарном компьютере с windows (попробовав половить чужие рации и переговоры самолётов), стал смотреть, а видит ли «свисток» сами датчики. Да, видит отлично:

image

Настройка малинки

Я выбрал нативный raspbian. Записал на флешку последний образ под mac/linux:

sudo dd if=2019-07-10-raspbian-buster-lite.img of=/dev/disk2 bs=1048576 conv=sync

Загружаемся, настраиваем сеть и ssh.

Далее — ставим на малинку пакеты rtl-sdr, rtl_433:

sudo apt-get install cmake build-essential python-pip libusb-1.0-0-dev libusb-1.0 python-numpy git
git clone https://github.com/merbanan/rtl_433.git
cd rtl_433/
mkdir build
cd build
cmake ..
make
make install

rtl_433 имеет встроенные протоколы, расшифровывающие данные с разных устройств, работающих в диапазоне 433mhz.

Запускаем rtl_433

rtl_433 -f 433.9e6

Опускаем датчики в воду и получаем заветное:

time      : 2019-09-17 15:04:39
model     : Smoke detector GS 558                  id        : 16919
unit      : 1            learn     : 0             Raw Code  : c842e1

Smoke detector? Ок, поставим на оповещение от этих датчиков песню «Smoke on the water»… :)
А если серьёзно — у нас есть id каждого датчика, по которому в будущем мы будем понимать, где именно у нас протечка (а перекрывать-то будем в любом случае).

Про датчики протечки

image image image

Уже после настройки софтовой части я заметил, что датчики с aliexpress (левое фото) шлют одиночный сигнал при попадании воды на контакты. Плюс одиночный сигнал, если вода перестаёт замыкать контакты. Меня это никак не устраивает (ожидаемое поведение: постоянно слать alarm-сигнал, когда датчик чувствует воду, т к одиночный сигнал может потеряться). Аналогичное поведение наблюдается, если замкнуть контакты проводом. Но что странно — alarm происходит каждые 2-3 секунды, если замыкать контакты руками (кожей). Тут у меня пока два пердположения: либо китайцы напортачили с замерами сопротивления, либо в датчиках есть какой-то другой режим работы, в котором они ведут себя как-то иначе (например спаренный с контроллером), либо есть и другие частоты (пока не нашёл).

Кстати, отпишите в комментариях, может кто-то работал именно с этими датчиками, можно ли их как-то «научить» слать сигнал о протечке постоянно?

Я отложил эти датчики, в арсенале был ещё один от rubetek (правое фото) и купленный в леруа: GAL SHW-1005 (среднее фото)
Поведение rubetek датчика показалось каким-то совсем непредсказуемым (не прогнозируемая реакция «видит воду/не видит»).
Зато датчик из леруа с ходу показал именно то, что мне и требовалось: есть вода — спамлю в эфир, нет воды — молчу. Единственный его минус — меньший радиус действия, чем у прочих датчиков. Но проблема решена покупкой более чувствительной антенны для приёмника.

MQTT

Как же направить вывод rtl_433 в zabbix? Кормить агенту? Отсылать zabbix_sender-ом, анализируя процесс? Может через syslog?
Тут нужно вспонить, что мой zabbix находится где-то в облаках. И уж точно не стоит перекрывать воду при помощи его триггеров. Пол дома зальёт, пока он примет решение (если вообще будет доступен).
Хорошая новость — rtl_433 умеет слать информацию по MQTT. Из коробки. При этом данные в брокер отправляются в формате json.

Значит нужно:

  • Разместить локальный mosquitto брокер (сделаем это на малинке).
  • Сливать инфу в брокер с нужным топиком, чтобы потом это можно было парсить.
  • Подключиться к брокеру локально на малинке и отправлять команды в netping
  • Подключаться к брокеру с места, где будет происходить перенаправление в zabbix ( zabbix-сервер в моём случае тоже является MQTT-клиентом)

Установка-настройка mosquitto MQTT:

apt-get install mosquitto mosquitto-clients
systemctl enable mosquitto
systemctl start mosquitto

Отправляем информацию в брокер с указанием id устройства:

rtl_433 -f 433.88e6 -F mqtt://127.0.0.1,events=/433/[id]

В mqtt клиенте будем получать примерно следующее:


mosquitto_sub -h 127.0.0.1 -t '#' (подписаться на все топики)
/433/16919 {"time":"2019-09-18 11:55:29","model":"Smoke detector GS 558","id":16919,"unit":1,"learn":0,"code":"c842e1"}

Скрипт подключения к брокеру и отправка команды в netping:

Набросал простенький скрипт-клиент MQTT, позволяющий при появлении заданного в конфигурации топика запускать ассоциированный с топиком скрипт. Таким образом можно при срабатывании определённого датчика и появлении информации об этом в «Эфире» (например /433/16919) выполнить какое-либо действие (в случае netping — отправить curl запрос на закрытие крана, см предыдущую статью). Ссылка на скрипт — в конце статьи.

Перенаправление в zabbix:

я использовал готовое решение mqtt-zabbix. На его уровне понимаем, в какой item отправить значение (по id).
В keys.cfg указываем:

/433/16919,mqtt.ventilation.waterleak::hostname

где hostname — имя хоста с заведённым item-ом типа «trapper» в Zabbix.
Важно!!! Имя хоста в настройках должно соответствовать отправляемому имени в скрипте, тип item (элемента данных) — подходить для посылаемых данных (например для json — текст), иначе будете ловить ошибки вида:

2019-09-18 14:29:48,749 Got response from Zabbix: {u'info': u'processed: 0; failed: 1; total: 1; seconds spent: 0.000055', u'response': u'success'}

Причём большего дебага (а почему именно failed) от zabbix добиться сложно.
Настраиваем /etc/mqtt-zabbix/mqtt-zabbix.cfg (указываем ip mqtt брокера и адрес zabbix-сервера).

Что ещё подключить по 433?

Да всё что угодно! :)

Датчики метеостанций

Пока ковырялся с беспроводными датчиками протечки, случайно словил сигнал внешнего датчика от метеостанции. Выглядело так:


time      : 2019-09-19 10:48:54                    Protocol  : 56
model     : TFA pool temperature sensor            Id        : 182
Channel   : 3            Temperature: 19.3 C
Modulation: ASK          Freq      : 433.9 MHz
RSSI      : -0.1 dB      SNR       : 35.0 dB       Noise     : -35.2 dB

time      : 2019-09-20 10:57:29                    Protocol  : 12            brand     : OS
model     : THN132N      House Code: 4
Channel   : 3            Battery   : OK            Celsius   : 20.00 C
Modulation: ASK          Freq      : 432.9 MHz
RSSI      : -0.2 dB      SNR       : 31.5 dB       Noise     : -31.7 dB

Таким образом, бонусом получил возможность мониторинга температуры точек по радиоканалу с отображением в zabbix. Как раз в некоторые помещения не могу протянуть кабель.

Дверной звонок

Очень многие радио-звонки работают в том же диапазоне частот ~433mhz. Таким образом, мы можем перехватывать нажатие кнопки звонка (даже не обязательно иметь сам звонок, достаточно только кнопки). Зачем? Например чтобы настроить дополнительное оповещение через СМС/в телеграм/whatever или вывести на монитор изображение с камеры.

Мною был куплен звонок: Evology QA-688-E RU.

Чтобы кнопку звонка увидел rtl_433, нужно активировать «тестовые» протоколы, например запустив с опцией «G» или указав конкретный дополнительный протокол, заодно добавим вывод информации о протоколе и частоте:

rtl_433 -f 433.9e6 -G -M protocol -M level -F mqtt://127.0.0.1,events=/433/[id] &

получим в MQTT:

{"time":"2019-09-30 10:57:00","protocol":72,"model":"RF-tech","id":0,"battery":"LOW","temperature_C":0,"button":0,"mod":"ASK","freq":433.84822,"rssi":-3.5981,"snr":33.77488,"noise":-37.373}

Тут можно заметить id=0. При этом у меня оказалось несколько устройств, определяющихся как RF-tech. У всех у них id был равен 0. В итоге все устройства в zabbix отображаются как один item. Различить то, какое именно устройство сработало, можно только по частоте.
Частоту вытаскиваем в отдельный зависимый item: mqtt.outside.doorbell.freq с предобработкой JSON-ом по $.freq (zabbix это умеет с 4-ой версии).

На этот item делаем триггер с выражением:

{HOME_PI:mqtt.outside.doorbell.freq.last()}>433.8 and {HOME_PI:mqtt.outside.doorbell.freq.last()}<433.81 and {HOME_PI:mqtt.outside.doorbell.freq.nodata(30)}=0

Т.е. если вдруг появилось значение в общем item mqtt.outside.doorbell.freq (nodata) и частота находится в заданном диапазоне между 433.8 и 433.81, можем делать вывод, что нам звонят (и например продублировать звонок в СМС).

Датчики открытия двери/окна

У меня в наличии есть датчик «проникновения» от rubetek. Посылает следующее:

{"time":"2019-09-30 14:11:28","protocol":86,"model":"Smoke detector GS 558","id":12262,"unit":16,"learn":0,"code":"e5fcd0","mod":"ASK","freq":433.85021,"rssi":-3.99241,"snr":33.38058,"noise":-37.373}

закрытие двери:
{"time":"2019-09-30 14:11:28","protocol":68,"model":"Kerui Security","id":46074,"cmd":7,"state":"close","mod":"ASK","freq":433.85021,"rssi":-3.99241,"snr":33.38058,"noise":-37.373}

открытие двери:
{"time":"2019-09-30 14:11:21","protocol":68,"model":"Kerui Security","id":46074,"cmd":14,"state":"open","mod":"ASK","freq":433.85005,"rssi":-11.0148,"snr":25.1088,"noise":-36.1236}

Как только последний радиодатчик был добавлен в zabbix, захотелось всё переделать именно на MQTT. Удобная каталогизация, можно topic-ах определять и место размещения и типы устройств. Получаешь общий эфир всех событий.

1wire to MQTT

Хочу чтобы всё было в MQTT, как минимум для однотипности реализации. Хочу получить общий «эфир» событий и общий подход в реакции на эти события. Безусловно, zabbix решает задачу реакций, и я оставляю на нём оповещения. Но управление хочется сделать более легковестным, приближенным к системе и «эфиру».

Готовые решения ретрансляции состояний датчиков из 1wire сети в MQTT существуют, но мне не подошли. Готовые решения на node либо тащат за собой кучу зависимостей, либо съедали весь процессор малинки. Часть решений из топ 10 в поиске гугла заброшено авторами, часть поддерживают только температурные датчики. Ещё есть класс gateway-ев, собирающих информацию через интерфейс gpio. Всё это мне не подошло.

У меня есть смонтированная псевдо-файловая система с 1wire устройствами в /mnt/1wire, именно оттуда я хочу брать всю необходимую информацию. Для этого достаточно сделать простой однострок на bash, пересылающий данные через mosquitto_pub по каждому из датчиков. Однако появляются вопросы запуска этих скриптов (по крону, загонять в какой-то демон?), нормального представления данных (получение того-же json-а), добавления нового датчика и т п. Чем дальше развивалась мысль — тем больше костылей рождалось. Оказалось проще написать под эту задачу yet another owfs to mqtt шлюз.

Есть файлик конфигурации, в который нужно заносить id датчиков и те файлы из fuse.OWFS, которые мы хотим паблишить в mqtt.

На выходе в mqtt получается такая json-ка:

/1wire/28.0425260a0000 {"type": "DS18B20", "temperature": "30"}
/1wire/28.bf16270a0000 {"type": "DS18B20", "temperature": "7.9375"}
/1wire/26.da2f71010000 {"temperature": "25.2812", "IAD": "1", "CA": "0", "VAD": "0.91", "VDD": "4.59", "type": "DS2438"}
/1wire/28.48b3010b0000 {"type": "DS18B20", "temperature": "40.5625"}
/1wire/1d.6a9306000000 {"type": "DS2423", "counter.B": "9", "counter.A": "9219"}
/1wire/28.61cc260a0000 {"type": "DS18B20", "temperature": "12.5"}

Добавляем в автозапуск, ставим интервал поллинга. Задача решена.

Ссылки

github.com/merbanan/rtl_433 — тула для декодинга радио-протоколов
github.com/kylegordon/mqtt-zabbix — MQTT в Zabbix
github.com/unlo/1wire2mqtt — 1wire в MQTT, MQTT клиент, позволяющий запускать скрипты при появлении топика

Автор: Евгений Мартынов

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js