Мы часто думаем о том, как автоматизировать свое жилище, но часто этот вопрос упирается в то, что готовые системы слишком негибки и дороги, а разбираться, как сделать что-нибудь самому совершенно нет времени.

Под катом - подробный гайд по настройке системы умного дома: сделаем возможным работу устройств ZWave и кастомных MQTT-устройств на базе ESP8266, настроим управление домом при помощи HomeKit и Яндекс Алисы.

Первоначальная настройка Raspberry PI

Установка системы

На распберри ставим raspberry pi os https://www.raspberrypi.org/downloads/raspberry-pi-os/ Записываем ее на MicroSD от 16 ГБ. Обязательно класса 10 и выше, иначе не хватает скорости доступа для работы операционной системы.

$ sudo dd bs=4M if=raspbian.img of=/dev/sdf status=progress

Headless

Если не хотим подключать монитор

SSH

В boot разделе создаем файл с именем ssh(это одноразовый способ: при наличии файла с именем ssh в разделе при старте raspberry sshd запускается и удаляется этот файл, поэтому не забываем в sudo raspi-config включить ssh насовсем)

# mkdir /mnt/boot_partition
# mount /dev/sdf1 /mnt/boot_partition
# touch /mnt/boot_partition/ssh
# umount /dev/sdf1

Теперь при первом запуске у нас будет возможность подключиться к системе по ssh.

Wi-Fi

Если необходимо подключение к локальной сети посредством wifi, создаем в boot разделе файл wpa_supplicant.conf

# mkdir /mnt/boot_partition
# mount /dev/sdf1 /mnt/boot_partition
# vim /mnt/boot_partition/wpa_supplicant.conf
# umount /dev/sdf1

Содержимое файла wpa_supplicant.conf

ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
country=RU
network={
 ssid="your_ssid"
 psk="your_wifi_password"
}

Подробнее об этом конфиге

Первый запуск

Вставляем флешку в малину, подключаем ее по ethernet к сети, если не настроили wifi, подаем питание по microUSB, используя блок питания с предельным током как минимум 2 ампера.

Raspberry PI должна загрузить систему, а также подключиться к сети.

Попробуем получить к ней доступ по ssh.

Для этого нам необходимо узнать, какой ip-адрес получила raspberry pi в нашей локальной сети. Вы можете зайти в веб интерфейс маршрутизатора и посмотреть список активных хостов, но я предпочитаю использовать nmap. Выполняю сканирование сети посредством пингования всех ip адресов подсети.

# nmap -sn 192.168.0.1/24
Starting Nmap 7.80 ( https://nmap.org ) at 2020-08-23 23:49 MSK
Nmap scan report for 192.168.0.1
Host is up (0.00033s latency).
Nmap scan report for 192.168.0.105
Host is up (0.00016s latency).
Nmap scan report for 192.168.0.120
Host is up (0.00050s latency).
Nmap done: 256 IP addresses (3 hosts up) scanned in 2.57 seconds

Здесь можно заметить, что кроме самого роутера(192.168.0.1) и моего ПК(192.168.0.105) появился еще один хост 192.168.0.120 - многовероятно, что это и есть наша малина.

Попробуем подключиться. Стандартная пара логин/пароль: pi/raspberry.

# ssh pi@192.168.0.120
Linux raspberrypi 4.19.118-v7+ #1311 SMP Mon Apr 27 14:21:24 BST 2020 armv7l

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Sun Aug 23 21:54:16 2020 from 192.168.0.105
pi@raspberrypi:~ $

Мы успешно вошли по ssh на raspberry pi и теперь можем приступать к дальнейшей настройке системы.

Установка Domoticz

Domoticz - программная система для управления умным домом с открытым исходным кодом. Написана на C++. На хабре я видел статьи про аналоги этой системы, такие как openhub и home assistant, но мой выбор пал на domoticz вследствие того, что эта платформа максимально проста для конфигурирования, а кроме того, написана на C++, что делает ее гораздо менее требовательной к вычислительным мощностям для работы, чем аналоги, использующие java и python. Кроме того, подкупила простая система написания сценариев на Lua или python.

Итак, установим domoticz на наш одноплатник. Установка максимально простая, за что личный респект разработчикам.

pi@raspberrypi:~ $ curl -L install.domoticz.com | sudo bash

На экране, спустя некоторое время, появится псевдографический диалог установки, в котором будет возможно выбрать порты и протоколы для веб интерфейса, директорию для установки. Лично я оставил исключительно HTTP на 80 порту, но вы вольны в своих решениях.

После окончания установки и, на всякий случай, ребута, проверяем, что демон domoticz поднялся:

pi@raspberrypi:~ $ sudo service domoticz status

Также проверим, что web интерфейс доступен: http://192.168.0.120/

Watchdog

В процессе эксплуатации я заметил, что Domoticz иногда падает с ошибкой. Чтобы поднимать его автоматически, напишу watchdog с помощью cron.

#!/bin/sh
# /etc/scripts/check_domoticz_online.sh
# check domoticz
status=`curl -s -i -H "Accept: application/json" "http://localhost:8080/json.htm?type=devices&rid=1" | grep "status"| awk -F: '{print $2}'|sed 's/,//'| sed 's/\"//g'`
if [ $status ]
then
    echo "Domoticz has already been started"
else
    /home/pi/domoticz/domoticz.sh restart   
fi
pi@raspberrypi:~ $ sudo crontab -e -u root
*/5 * * * * /etc/scripts/check_domoticz_online.sh > /dev/null 2>&1

Теперь каждые 5 минут будет запускаться скрипт, который проверит, работает ли Domoticz и перезапустит его, если это необходимо

Настройка domoticz для работы с устройствами

Теперь, когда система работает и готова к продолжению конфигурирования, можно настроить какие нибудь устройства.

IP-камера

Самое простое, что можно настроить в Domoticz - это камера. Для этого зайдем в web-интерфейсе в Setup -> More options -> Cameras -> Add camera.

Вводим данные о своей камере. У меня возникли сложности с определением picture url, но они решились вот этим сервисом.

После того, как мы сохранили новую камеру, у нас появилась строка в таблице с кнопками, чтобы посмотреть изображение или видео.

Z-Wave USB Stick

Посредством Domoticz, мы можем управлять домашней сетью Z-Wave IoT устройств. Это удобный протокол, позволяющий устройствам взаимодействовать друг с другом так, чтобы некоторые из них являлись, помимо своего основного назначения, Z-Wave ретрансляторами, своей работой расширяя радиус покрытия Z-Wave. Протокол закрытый, проприеритарный, поэтому просто создать свое Z-Wave устройство не выйдет, поэтому обычно, по этому протоколу работают покупные устройства/компоненты умного дома.

По моему опыту, настройка Z-Wave сети в Domoticz оказалась сильно проще и, в отличие от систем Home Assistant и openHub, здесь USB Stick заработал сразу и без проблем.

Для того, чтобы настроить свою сеть Z-Wave, я приобрел Z-Wave USB Stick. Подключив его к Raspberry pi, я добавил его как еще одну Hardware, с Type OpenZWave USB. Путь к Serial Port у меня выглядел примерно так: /dev/serial/by-id/usb-0658_0200-if00

После добавления стика, появится запись в таблице с ним, в которой будет кнопка Setup, открывающая возможность настраивать ZWave сеть. В меню настройки можно включать режим обнаружения новых ZWave устройств, а также изменять параметры сети и устройств в ней.

ВАЖНО: следите, чтобы рабочая частота Z-Stick соответствовала рабочей частоте Z-Wave устройств

MQTT-брокер

Для создания кастомных IoT устройств я собираюсь использовать Arduino с подключением к локальной сети. В рамках данной сети общепринятым стандартом общения между устройствами является MQTT - протокол, ориентированный для обмена сообщениями по принципу издатель-подписчик. Для передачи сообщений посредством данного протокола нам необходим MQTT-брокер - своеобразный хаб для сообщений. Domoticz и IoT устройства выступят в качестве клиентов сети, подключившись к брокеру.

Установим свободный MQTT-брокер Mosquitto.

pi@raspberrypi:~ $ sudo wget http://repo.mosquitto.org/debian/mosquitto-repo.gpg.key  
pi@raspberrypi:~ $ sudo apt-key add mosquitto-repo.gpg.key  
pi@raspberrypi:~ $ cd /etc/apt/sources.list.d/  
pi@raspberrypi:/etc/apt/sources.list.d/ $ sudo wget http://repo.mosquitto.org/debian/mosquitto-jessie.list
pi@raspberrypi:/etc/apt/sources.list.d/ $ cd
pi@raspberrypi:~ $ sudo apt-get install mosquitto mosquitto-clients
pi@raspberrypi:~ $ rm mosquitto-repo.gpg.key

Теперь Mosquitto установлен и работает. Мы можем подключиться к нему без аутентификации по адресу 0.0.0.0:1883. Таких настроек нам хватит на первое время.

Domoticz - MQTT клиент

Подключим domoticz к MQTT-брокеру. В web-интерфейсе Domoticz - Setup -> Hardware.

  • Type - MQTT Client Gateway with LAN interface.

  • Remote address - localhost

  • Port - 1883

  • Data Timeout - disabled

  • Username и password - оставляем пустыми до лучших времен

  • Prevent loop - в большинстве случаев эту настройку следует оставить включенной, но в нашем случае мы собираемся подключать собственные устройства по MQTT и управлять ими внешними методами, поэтому мы выключим prevent loop и domoticz будет пересылать все обновления статусов устройств из domoticz/in в domoticz/out. Это нужно, тк внешнее управление осуществляется посредством публикаций в domoticz/in, а наши устройства слушают domoticz/out, и если domoticz не будет пересылать сообщения из in в out, то устройства не смогут узнать об обновлениях их статусов.

  • Publish topic - топик, куда domoticz будет публиковать все обновления статусов. Для себя я оставил стандартно - out, и domoticz публикует в топик domoticz/out.

После нажатия на Add у нас добавился новый hardware. Если все хорошо, то в таблице, в колонке Enabled мы увидим Yes.

Dummy switch

Хотелось бы быстро проверить работу нашей системы. Для этого есть виртуальные устройства - не имеющие физических воплощений(по крайней мере, пока мы их не сделаем), но имеющие статус в системе domoticz и управляемые из нее.

Добавим Dummy hardware. В web-интерфейсе Domoticz - Setup -> Hardware

  • Type - Dummy (Does nothing, use for virtual switches only)

Добавляем. В таблице появилась еще одна запись. Можно увидеть, что в таблице рядом с Type есть кнопка Create virtual sensors. Нажимаем ее, вводим параметры

  • Name - lamp

  • Sensor type - Switch

Сохраняем и переходим в меню Switches. Теперь здесь можно увидеть новый переключатель:

Теперь мы можем посмотреть, как изменение переключателя отражается в топике MQTT.

pi@raspberrypi:~ $ mosquitto_sub -h localhost -v -t "domoticz/out"

Мы использовали клиент MQTT, который установили вместе с брокером, и подписались на топик, куда domoticz публикует свои обновления. Нажмем на лампочку в веб-интерфейсе

Смотрим в терминал и видим сообщение из топика:

domoticz/out {
    "Battery" : 255,
    "RSSI" : 12,
    "description" : "",
    "dtype" : "Light/Switch",
    "hwid" : "4",
    "id" : "00014052",
    "idx" : 2,
    "name" : "lamp",
    "nvalue" : 1,
    "stype" : "Switch",
    "svalue1" : "0",
    "switchType" : "On/Off",
    "unit" : 1
}

В подобных сообщениях Domoticz сообщает нам об изменении своего состояния. Формат тела сообщения - JSON. В поле name видим название, которое мы ранее установили для switch'а в domoticz. Новое состояние свитча мы можем увидеть в поле nvalue.

Программируем собственные IoT устройства на базе Arduino-like контроллеров.

Теперь, когда MQTT-брокер доступен из сети и Domoticz публикует туда сообщение каждый раз, когда мы переключаем switch, можно заняться программированием микроконтроллера. Задача: подключиться к сети, подключиться к брокеру MQTT, подписаться на нужный топик и парсить сообщения от Domoticz, выделяя те, поле name которых совпадает с названием, захардкоженым в программу, и выполняя переключения встроенного светодиода в зависимости от нового состояния из сообщения. Впоследствии переключаться будет не встроенный светодиод, а реле, управляя каким-либо процессом.

Для реализации данного функционала я использую клон Arduino Uno, Ethernet Shield, а также Arduino-like плату на основе контроллера ESP8266, который способен подключаться к сети по WiFi. Таким образом, у меня будут две версии устройства - с подключением по Ethernet и по WiFi.

Для работы с MQTT я использовал библиотеку MQTT.h. Для парсинга JSON - ArduinoJSON.h.

Изначально, написав скетч для Arduino, я, выставив значение для буферов MQTTClient и ArduinoJSON в 500 байт и использовав преобразование входных данных в класс String, превысил мизерное количество оперативной памяти в 2 килобайта. Уменьшив размер буферов до 300 байт и использовав "сишные" строки, мне удалось уложиться в данный лимит, и даже оставить 300-400 свободных байт, но стало понятно, что модифицировать и усложнять программу, добавлять дополнительную логику в случае этой платы будет затруднительно.

Исходный код скетча Arduino + Ethernet.

Программировать ESP8266 оказалось сильно проще, так как оперативной памяти здесь на порядок больше.

Исходный код скетча для ESP8266(WiFi).

Отлично! Оба устройства отслеживают изменения значения переключателя в интерфейсе Domoticz, и переключают светодиод соответственно значению переключателя!

Для себя в данный момент я сделал вывод, что гораздо разумнее использовать платы на основе ESP8266, потому что:

  • нет давящего ограничения по оперативной памяти

  • цена за комплект Arduino UNO + Ethernet Shield - 1100 руб, а на плату с работающим из коробки WiFi - 400

Таким образом, мы научились управлять собственным WiFi устройством прямо из интерфейса Domoticz, что открывает перед нами гигантские перспективы для автоматизации

Управляем всем через Яндекс Алису

Domoticz как таковой не поддерживает интеграцию с Алисой, потому что для этого необходим работающий навык Алисы и какой-то облачный интерфейс. Поэтому, для работы с Алисой предлагается следующий костыль: к mqtt брокеру, куда domoticz публикует изменения своих статусов, подключить homebridge - средство для подключения умного дома Apple, и передавать команды от Алисе к domoticz через него.

Поставим все необходимое ПО:

pi@raspberrypi:~ $ sudo apt update
pi@raspberrypi:~ $ sudo apt install -y nodejs npm libavahi-compat-libdnssd-dev
pi@raspberrypi:~ $ sudo npm install -g --unsafe-perm homebridge homebridge-config-ui-x
pi@raspberrypi:~ $ sudo npm install -g -g --unsafe-perm homebridge-edomoticz

Запускаем

sudo hb-service install --user homebridge

Теперь заходим на веб-интерфейс homebridge по порту 8581, логинимся admin:admin и видим qr-код устройства, который сканируем приложением Дом на iphone. Homebridge своим плагином для domoticz должен видеть все устройства, зарегистрированные в domoticz, и когда мы добавим homebridge в приложение Дом на iphone, то мы сможем ими управлять. Происходит это посредством отправки сообщений в domoticz/in. Чтобы мое самодельное устройство начало получать эти изменения своего статуса, я отключил в настройках mqtt domoticz prevent loop. Таким образом, теперь, когда domoticz получает обновления статусов устройств через domoticz/in, он дублирует их в domoticz/out и устройства, слушающие domoticz/out, могут их получить. Позаботьтесь о том, чтобы ваши устройства не отвечали в domoticz/in на изменения своего статуса, чтобы не образовывались петли.

Для подключения Homebridge к Алисе я использовал g-on плагин. По ссылке - исчерпывающее описание настройки.

После окончания настройки мы имеем возможность управлять устройствами Domoticz, используя приложение Дом или Алису

Итог

Результатом моей работы стала система, обладающая приемлемой стабильностью, способная управлять IoT устройствами без необходимости подключения к интернету, позволяющая интегрировать собственные IoT устройства, работающие в сети WiFi, а также управлять этими устройствами голосовыми командами через Алису, или же с помощью облачного сервиса Apple

P.S.

Демонстрация работы системы. Торшер подключен к самодельной "умной розетке", состоящей из реле, которым управляет ESP8266. Розетка по MQTT общается с Domoticz

P.P.S

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

Исправление костыля с watchdog'ом

Большое спасибо автору этой статьи, который показал на примере из моей статьи, что в данном случае более подходящим инструментом для контроля работы domoticz будет systemd. И действительно, systemd снимает с нас необходимость следить за работой демонов, предоставляя гибкий интерфейс для настройки управления ими

Tasmota

Использование готовой прошивки для ESP8266 позволит не писать свой код для нее. Я проверил работоспособность этой прошивки на плате Wemos D1 R32.

Прошивку скачиваем отсюда

Прошиваем:

# esptool.py --chip esp32 --port /dev/ttyUSB0 --baud 921600 erase_flash
# esptool.py --chip esp32 --port /dev/ttyUSB0 --baud 921600 --before default_reset --after hard_reset write_flash -z --flash_mode dout --flash_freq 40m --flash_size detect 0x1000 bootloader_dout_40m.bin 0x8000 partitions.bin 0xe000 boot_app0.bin 0x10000 tasmota32.bin

Можем посмотреть логи tasmota через монитор последовательного порта

# screen /dev/ttyUSB0 115200

Подключаемся к wifi сети tasmota, открываем web морду устройства: http://192.168.4.1

Вводим данные wifi сети и ждем, пока esp8266 не подключится к ней.

Теперь смотрим в логах, какой ip адрес получила esp8266, и снова открываем веб интерфейс, уже используя новый адрес.

Сначала настраиваем MQTT: все оставляем стандартно, кроме логопассов и IP адреса MQTT брокера. После этого настраиваем модуль: выбираем порты, которыми хотим управлять, указываем, что за устройство на них висит: реле, кнопка или что-то еще. После этого настраиваем Domoticz - смотрим, какое idx у dummy device, и записываем его в соответствующее поле. Теперь мы можем управлять этим устройством при помощи domoticz