Вступление
В процессе выбора решений для умного дома я стараюсь обходить коробочные решения, требующие наличие связи с внешними облаками или имеющие собственные приложения, особенно решения без возможности прямого подключения к устройству. Все доступные метрики сводятся в один интерфейс — zabbix, там же организовывается система оповещений заинтересованных лиц. Ручки управления реализуются в локально расположенном веб-интерфейсе.
Предыдущие статьи:
часть первая (1wire температура, ups, водосчетчик...)
часть вторая (netping, gidrolock, датчики давления...)
Решаемые задачи в этой статье
- Масштабируемая, гибкая система защиты от протечек воды с оповещением через zabbix
- Прочие устройства на 433mhz: звонок, открытие двери и т п
- Запихиваем 1wire в MQTT
Система защиты от протечек
Требования к системе:
- множество датчиков, раскиданных по дому (в моём случае — 6 штук в разных локациях)
- никаких проводов у датчиков
- быстрое закрытие при обнаружении утечки
- вся информация о текущем состоянии в zabbix. Там же — оповещение
Состав системы
- Raspberry PI
- RTL2832U USB тюнер
- Датчики протечек 433mhz
- Netping + кран gidrolock (см предыдущую статью) для перекрытия магистрали
Про железо
В предыдущей статье я описывал решение перекрытия водоснабжения при помощи netping. У меня имеется один проводной датчик для этого решения. Это удобно, если все точки, где может произойти протечка, находятся примерно в одном месте. В моём случае netping установлен прямо на входе магистрали и там же управляет электро-механическим краном gidrolock (см предыдущую статью). Раскидывать netping+gidrolock+проводной датчик по всем точкам — дорого и громоздко. К тому же у меня уже нет возможности протаскивать новые провода по всему дому. Занимать розетки и втюхивать электрокраны — так себе решение. Решение ожидаемое — используем перекрытие общей магистрали на основе сигналов от раскинутых по локациям радио-датчиков.
Из найденного в интернете — куча различных радио-датчиков от готовых систем. Некоторые можно купить отдельно, контроллеры к датчикам покупать не стал, чтобы не плодить дополнительных элементов в схеме.
Чем можно ловить 433mhz? Оказывается — тв-тюнером на определённом чипсете. И стоит он сейчас копейки (я взял на авито за 300р) вот такой:
Заказал к нему отдельную антенку на 12dbi, т к текущая не покрывала весь дом.
Поскольку я пытался минимизировать управляющие компоненты схемы, было желание затянуть тюнер в свой домашний роутер с Openwrt, который и являлся до этого момента ядром решения умного дома для 1wire, modbus, wifi датчиков/протоколов, но, к сожалению, я исчерпал часть его ресурсов (заканчивается место на встроенной флешке под нужный софт, процессор чем-то догружать — уже будут проблемы с работой сети, а нам ещё 4k смотреть в online:), +на USB уже слишком много всего навешено, что влияет на стабильность сбора данных). Решено постепенно выносить функционал умного дома на внешнее устройство — rarpberry pi (под рукой оказалась одна из первых версий).
Про софт
Наигравшись с тв-тюнером в sdr-sharp на стационарном компьютере с windows (попробовав половить чужие рации и переговоры самолётов), стал смотреть, а видит ли «свисток» сами датчики. Да, видит отлично:
Настройка малинки
Я выбрал нативный 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 каждого датчика, по которому в будущем мы будем понимать, где именно у нас протечка (а перекрывать-то будем в любом случае).
Про датчики протечки
Уже после настройки софтовой части я заметил, что датчики с 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 клиент, позволяющий запускать скрипты при появлении топика
Комментарии (6)
Methos
20.10.2019 13:59А если к дому подходит хакермошенник и запускает ложные датчики протечки и т. д.
Вода перекрывается, сигнализация срабатывает, дом пляшет.
Это возможно?unlo Автор
20.10.2019 14:09Датчики воды срабатывают только при обнаружении протечек и просто так в эфир не спамят. Поэтому перехватить сигнал (понять протокол и id) можно, но нужно сначала дождаться самой протечки, чтобы определить все неизвестные.
Но имея представление о системе в целом и передатчик с возможностью отправки нужных пакетов — перекрыть воду в радиусе действия — действительно можно.
Правда я не испытываю по этому поводу никакого беспокойства. Это не открытие ворот/замков/снятие сигнализаций.
dsoastro
21.10.2019 13:06Сделал что-то подобное на основе датчиков ксяоми (протокол Zigbee). Есть датчики движения, утечки, температуры. Для приема сигнала использую CC2531 USB stick (www.zigbee2mqtt.io). На raspberry запускается прога на nodejs с этого же сайта, которая читает USB stick и шлет инфу на mosquito. Небольшой питоновский скрипт, используя библиотеку paho-mqtt, считывает все эти сигналы, обрабатывает, и шлет в телеграм бот.
Но воду не перекрывает)))
Нашел странную особенность датчиков. Если сигнал от USB stick слабый (далеко от него находятся), они могут отключиться через неделю работы. А активировать их снова нужно вручную…
Поиграю с 433, может стабильней работать будет
Bonio
Очень рекомендую посмотреть на NodeRed. Это система предназначенная как раз для таких автоматизаций. Имет поддержку MQTT, конфигурируется с помощью блоков и связей между ними. Можно описывать логику на javascript, если не хватает стандартных блоков. Очень мощная штука для автоматизации умного дома.
unlo Автор
Да, оно мне попалось при решении задачи. Но показалось требовательным к ресурсам.
Может быть и ошибаюсь, попробую как-нибудь на досуге поставить на малинку :)
Foreglance
NodeRED можно и на старом Андроид-фоне или таблетке запустить в Termux -е (Termux работает начиная с 5го Андроида). Но если есть малинка — тогда на ней конечно.