Изначально была мысль повысить доступность openHAB средствами виртуализации. Ставим два гипервизора, настраиваем High availability, при отказе хоста виртуалка с openHAB перезапустится на соседнем сервере. И все бы ничего, но для работы HA нужно общее хранилище. Какой-то NAS допустим у меня есть, но выход его из строя даже более вероятен, чем отказ хоста. А городить что-то на DRBD или подобном не хотелось. Поэтому было решено кластеризовать openHAB другим способом, см. рисунок ниже.
Идея
Разворачиваются две виртуалки. Также можно использовать физические машины, разные малинки и т.п. В качестве дистрибутива я использовал CentOS 9 Stream, но это не принципиально. Настраиваем keepalived для перекидывания IP-адреса с одной машины на другую. Настраиваем lsyncd для синхронизации данных openHAB, поднимаем mosquitto и, кажется, все. Теперь подробнее.
Установка openHAB
Процесс установки описан тут - https://www.openhab.org/docs/installation/linux.html.
Если вкратце, то для CentOS 9 Stream создаем файл /etc/yum.repos.d/openhab.repo
С таким содержимым:
[openHAB-Stable]
name=openHAB Stable
baseurl=https://openhab.jfrog.io/artifactory/openhab-linuxpkg-rpm/stable
gpgcheck=1
gpgkey="https://openhab.jfrog.io/artifactory/api/gpg/key/public"
enabled=1
Затем делаем:
# dnf update
# dnf install openhab
# dnf install openhab‑addons
# dnf install java-17-openjdk
Если есть другие инсталляции java, то их нужно удалить, например:
# dnf remove java-11-openjdk
Либо запустить команду:
# alternatives --config java
И выбрать 17ю версию.
Запускаем и добавляем в автозагрузку:
#dnf systemctl start openhab
#dnf systemctl enable openhab
Интерфейс будет доступен по адресу http://IP:8080
При первом запуске нужно создать учетную запись администратора и пройти небольшой мастер установки.
Установка и настройка keepalived
На обоих серверах пропишем имена и адреса в файл /etc/hosts
10.20.10.41 srv-oh-01
10.20.10.42 srv-oh-02
Теперь нужно установить и настроить VRRP на обоих нодах:
# dnf install keepalived
Вот такой конфигурационный файл получился/etc/keepalived/keepalived.conf
:
Hidden text
vrrp_instance failover_oh {
state BACKUP
interface ens192
virtual_router_id 10
priority 100
advert_int 1
preempt_delay 30
authentication {
auth_type AH
auth_pass active-pass
}
notify /etc/keepalived/oh.sh
unicast_peer {
10.20.10.42
}
virtual_ipaddress {
10.20.10.40 dev ens192 label ens192:vip
}
}
На обоих нодах конфигурация одинакова, за исключением unicast_peer, на втором сервере, он будет 10.20.10.41.
Прошу заметить, что на обоих серверах прописано “state BACKUP”, а приоритет тоже одинаков. Это делает ноды равнозначными и какой сервер раньше загрузился, тот и будет мастером, до момента отказа.
Кроме переключения IP-адреса мы так же выполняем notify-скрипт, который на самом деле запускает и останавливает openHAB, чтобы он не обращался ко всяким внешним биндингам (например Telegram) с двух нод одновременно, вот этот файл:
#!/bin/bash
TYPE=$1
NAME=$2
STATE=$3
case $STATE in
"MASTER") systemctl start openhab
;;
"BACKUP") systemctl stop openhab
;;
"FAULT") systemctl stop openhab
exit 0
;;
*) /usr/bin/logger "oh unknown state"
exit 1
;;
esac
Запускаем и добавляем в автозапуск keepalived
# systemctl start keepalived
# systemctl enable keepalived
Можно запустить на обоих нодах:
# journalctl -af
И посмотреть, что будет в логах при start/stop keepalived на каждой ноде:
Hidden text
Jan 24 11:32:15 srv‑oh-01 Keepalived_vrrp[924]: (failover_oh) Backup received priority 0 advertisement
Jan 24 11:32:15 srv‑oh-01 Keepalived_vrrp[924]: (failover_oh) Receive advertisement timeout
Jan 24 11:32:15 srv‑oh-01 Keepalived_vrrp[924]: (failover_oh) Entering MASTER STATE
Jan 24 11:32:15 srv‑oh-01 Keepalived_vrrp[924]: (failover_oh) setting VIPs.
Jan 24 11:32:15 srv‑oh-01 Keepalived_vrrp[924]: (failover_oh) Sending/queueing gratuitous ARPs on ens192 for 10.20.10.40
Jan 24 11:32:15 srv‑oh-01 Keepalived_vrrp[924]: Sending gratuitous ARP on ens192 for 10.20.10.40
Jan 24 11:32:15 srv‑oh-01 Keepalived_vrrp[924]: Sending gratuitous ARP on ens192 for 10.20.10.40
Jan 24 11:32:15 srv‑oh-01 Keepalived_vrrp[924]: Sending gratuitous ARP on ens192 for 10.20.10.40
Jan 24 11:32:15 srv‑oh-01 Keepalived_vrrp[924]: Sending gratuitous ARP on ens192 for 10.20.10.40
Jan 24 11:32:15 srv‑oh-01 Keepalived_vrrp[924]: Sending gratuitous ARP on ens192 for 10.20.10.40
Jan 24 11:32:15 srv‑oh-01 systemd[1]: Started openHAB — empowering the smart home.
Jan 24 11:32:20 srv‑oh-01 Keepalived_vrrp[924]: (failover_oh) Sending/queueing gratuitous ARPs on ens192 for 10.20.10.40
Jan 24 11:32:20 srv‑oh-01 Keepalived_vrrp[924]: Sending gratuitous ARP on ens192 for 10.20.10.40
Jan 24 11:32:20 srv‑oh-01 Keepalived_vrrp[924]: Sending gratuitous ARP on ens192 for 10.20.10.40
Jan 24 11:32:20 srv‑oh-01 Keepalived_vrrp[924]: Sending gratuitous ARP on ens192 for 10.20.10.40
Jan 24 11:32:20 srv‑oh-01 Keepalived_vrrp[924]: Sending gratuitous ARP on ens192 for 10.20.10.40
Jan 24 11:32:20 srv‑oh-01 Keepalived_vrrp[924]: Sending gratuitous ARP on ens192 for 10.20.10.40
Я остановил keepalived на srv-oh-02, теперь первый стал мастером, установился vIP (10.20.10.40), отправились ARP-пакеты, чтобы побыстрее обучить коммутатор и запустился openHAB.
Итак половина задачи решена, IP переезжает, сервис запускается где нужно. Теперь надо синхронизировать данные.
Установка и настройка lsyncd
В openHAB конфиги лежат в /etc/openhab, а также две базы - rrd4 (где хранятся метрики) и jsondb (где хранятся так называемые семантические элементы). Для синхронизации этих данных будем использовать lsyncd, который позволяет (при помощи rsync) сихронизировать файлы сразу после их создания или изменения, причем в обе стороны, т.е. сервер где модификация произошла позже, считается источником.
Для работы lsyncd надо сгенерировать ключи SSH, на одном из серверов, например на 1-м делаем:
# ssh-keygen
# ssh-copy-id srv-oh-02
Первая команда сгенерирует закрытый и публичный ключ, вторая скопирует публичный ключ на удаленный сервер, теперь на него можно заходить без пароля. Такую же процедуру нужно провезти на 2-м сервере, я просто скопировал этот же ключ в .ssh/authorized_keys
Теперь установим lsyncd на оба сервера:
# dnf install lsync
Напишем конфигурационный файл /etc/lsyncd.conf, на первом сервере он будет такой:
Hidden text
settings {
logfile = "/var/log/lsyncd/lsyncd.log",
statusFile = "/var/log/lsyncd/lsyncd.status",
statusInterval = 1,
nodaemon = true,
insist = true
}
sync {
default.rsync,
source = "/etc/openhab/",
target = "srv-oh-02:/etc/openhab",
delete = 'running',
--delay = 5,
rsync = {
-- timeout = 3000,
update = true,
_extra={"--temp-dir=/temp-lsync/"},
times = true,
archive = true,
compress = true,
perms = true,
acls = true,
owner = true,
verbose = true
}
}
sync {
default.rsync,
source = "/var/lib/openhab/persistence",
target = "srv-oh-02:/var/lib/openhab/persistence",
delete = 'running',
--delay = 5,
rsync = {
-- timeout = 3000,
update = true,
_extra={"--temp-dir=/temp-lsync/"},
times = true,
archive = true,
compress = true,
perms = true,
acls = true,
owner = true,
verbose = true
}
}
sync {
default.rsync,
source = "/var/lib/openhab/jsondb",
target = "srv-oh-02:/var/lib/openhab/jsondb",
delete = 'running',
--delay = 5,
rsync = {
-- timeout = 3000,
update = true,
_extra={"--temp-dir=/temp-lsync/"},
times = true,
archive = true,
compress = true,
perms = true,
acls = true,
owner = true,
verbose = true
}
}
Каждая секция sync настраивается отдельно.
На втором сервере конфигурация такая же, только в target’ах надо изменить имя сервера на srv-oh-01. Еще нужно на обоих нодах создать директорию /temp-lsync,
для хранения временных данных.
Запускаем его и добавляем в автозагрузку на обоих нодах:
# systemctl start lsyncd
# systemctl enable lsyncd
Логи можно смотреть так:
# tail -f /var/log/lsyncd/lsyncd.log
Hidden text
Jan 24 11:32:10 srv-oh-02 lsyncd[857]: 11:32:10 Normal: Calling rsync with filter-list of new/modified files/dirs
Jan 24 11:32:10 srv-oh-02 lsyncd[857]: /rrd4j/GF_Kitchen_Gas.rrd
Jan 24 11:32:10 srv-oh-02 lsyncd[857]: /rrd4j/
Jan 24 11:32:10 srv-oh-02 lsyncd[857]: /
Jan 24 11:32:10 srv-oh-02 lsyncd[857]: /rrd4j/gGas.rrd
Jan 24 11:32:10 srv-oh-02 lsyncd[857]: /rrd4j/gTemperature.rrd
Jan 24 11:32:10 srv-oh-02 lsyncd[857]: /rrd4j/GF_Kitchen_Motion.rrd
Jan 24 11:32:10 srv-oh-02 lsyncd[857]: /rrd4j/GF_Kitchen_Button_1.rrd
Jan 24 11:32:10 srv-oh-02 lsyncd[857]: /rrd4j/GF_Kitchen_Water_2.rrd
Jan 24 11:32:10 srv-oh-02 lsyncd[857]: /rrd4j/GF_Kitchen_Shutter_3.rrd
Jan 24 11:32:10 srv-oh-02 lsyncd[857]: /rrd4j/GF_Kitchen_Water_1.rrd
Jan 24 11:32:10 srv-oh-02 lsyncd[857]: /rrd4j/GF_Kitchen_Shutter_2.rrd
Jan 24 11:32:10 srv-oh-02 lsyncd[857]: /rrd4j/GF_Kitchen_Shutter_1.rrd
Jan 24 11:32:10 srv-oh-02 lsyncd[857]: /rrd4j/GF_FamilyRoom_Temperature.rrd
Jan 24 11:32:10 srv-oh-02 lsyncd[857]: /rrd4j/GF_FamilyRoom_Shutter_1.rrd
Jan 24 11:32:10 srv-oh-02 lsyncd[857]: /rrd4j/gWater.rrd
Jan 24 11:32:10 srv-oh-02 lsyncd[857]: /rrd4j/GF_FamilyRoom_Humidity.rrd
Jan 24 11:32:10 srv-oh-02 lsyncd[857]: /rrd4j/Security.rrd
Jan 24 11:32:10 srv-oh-02 lsyncd[857]: /rrd4j/OU_Toilet_Light.rrd
Jan 24 11:32:10 srv-oh-02 lsyncd[857]: /rrd4j/gLight.rrd
Jan 24 11:32:10 srv-oh-02 lsyncd[857]: /rrd4j/OU_Temperature.rrd
Jan 24 11:32:10 srv-oh-02 lsyncd[857]: /rrd4j/GF_Kitchen_Door_1.rrd
Jan 24 11:32:10 srv-oh-02 lsyncd[857]: /rrd4j/GF_FamilyRoom_Light.rrd
Jan 24 11:32:10 srv-oh-02 lsyncd[857]: /rrd4j/GF_Kitchen_Light_2.rrd
Jan 24 11:32:10 srv-oh-02 lsyncd[857]: /rrd4j/GF_Kitchen_Light_1.rrd
Jan 24 11:32:10 srv-oh-02 lsyncd[857]: /rrd4j/gShutter.rrd
Jan 24 11:32:10 srv-oh-02 lsyncd[857]: /rrd4j/GF_FamilyRoom_Gas.rrd
Jan 24 11:32:10 srv-oh-02 lsyncd[857]: /rrd4j/gMotion.rrd
Jan 24 11:32:10 srv-oh-02 lsyncd[857]: /rrd4j/gWindow.rrd
Jan 24 11:32:10 srv-oh-02 lsyncd[857]: /rrd4j/GF_Kitchen_Window_1.rrd
Jan 24 11:32:10 srv-oh-02 lsyncd[857]: /rrd4j/GF_FamilyRoom_Motion.rrd
Jan 24 11:32:10 srv-oh-02 lsyncd[857]: /rrd4j/GF_Kitchen_Temperature.rrd
Jan 24 11:32:10 srv-oh-02 lsyncd[857]: /rrd4j/GF_FamilyRoom_Shutter_4.rrd
Jan 24 11:32:10 srv-oh-02 lsyncd[857]: /rrd4j/GF_FamilyRoom_Shutter_3.rrd
Jan 24 11:32:10 srv-oh-02 lsyncd[857]: /rrd4j/GF_FamilyRoom_Shutter_2.rrd
Jan 24 11:32:10 srv-oh-02 lsyncd[857]: /rrd4j/gHumidity.rrd
Jan 24 11:32:10 srv-oh-02 lsyncd[857]: /rrd4j/gDoor.rrd
Jan 24 11:32:10 srv-oh-02 lsyncd[857]: /rrd4j/Day.rrd
Jan 24 11:32:11 srv-oh-02 lsyncd[1753681]: sending incremental file list
Jan 24 11:32:11 srv-oh-02 lsyncd[1753681]: rrd4j/Day.rrd
Jan 24 11:32:11 srv-oh-02 lsyncd[1753681]: rrd4j/GF_FamilyRoom_Gas.rrd
Jan 24 11:32:11 srv-oh-02 lsyncd[1753681]: rrd4j/GF_FamilyRoom_Humidity.rrd
Jan 24 11:32:11 srv-oh-02 lsyncd[1753681]: rrd4j/GF_FamilyRoom_Light.rrd
Jan 24 11:32:11 srv-oh-02 lsyncd[1753681]: rrd4j/GF_FamilyRoom_Motion.rrd
Jan 24 11:32:11 srv-oh-02 lsyncd[1753681]: rrd4j/GF_FamilyRoom_Shutter_1.rrd
Jan 24 11:32:11 srv-oh-02 lsyncd[1753681]: rrd4j/GF_FamilyRoom_Shutter_2.rrd
Jan 24 11:32:11 srv-oh-02 lsyncd[1753681]: rrd4j/GF_FamilyRoom_Shutter_3.rrd
Jan 24 11:32:11 srv-oh-02 lsyncd[1753681]: rrd4j/GF_FamilyRoom_Shutter_4.rrd
Jan 24 11:32:11 srv-oh-02 lsyncd[1753681]: rrd4j/GF_FamilyRoom_Temperature.rrd
Jan 24 11:32:11 srv-oh-02 lsyncd[1753681]: rrd4j/GF_Kitchen_Button_1.rrd
Jan 24 11:32:11 srv-oh-02 lsyncd[1753681]: rrd4j/GF_Kitchen_Door_1.rrd
Jan 24 11:32:11 srv-oh-02 lsyncd[1753681]: rrd4j/GF_Kitchen_Gas.rrd
Jan 24 11:32:11 srv-oh-02 lsyncd[1753681]: rrd4j/GF_Kitchen_Light_1.rrd
Jan 24 11:32:11 srv-oh-02 lsyncd[1753681]: rrd4j/GF_Kitchen_Light_2.rrd
Jan 24 11:32:11 srv-oh-02 lsyncd[1753681]: rrd4j/GF_Kitchen_Motion.rrd
Jan 24 11:32:11 srv-oh-02 lsyncd[1753681]: rrd4j/GF_Kitchen_Shutter_1.rrd
Jan 24 11:32:11 srv-oh-02 lsyncd[1753681]: rrd4j/GF_Kitchen_Shutter_2.rrd
Jan 24 11:32:11 srv-oh-02 lsyncd[1753681]: rrd4j/GF_Kitchen_Shutter_3.rrd
Jan 24 11:32:11 srv-oh-02 lsyncd[1753681]: rrd4j/GF_Kitchen_Temperature.rrd
Jan 24 11:32:11 srv-oh-02 lsyncd[1753681]: rrd4j/GF_Kitchen_Water_1.rrd
Jan 24 11:32:11 srv-oh-02 lsyncd[1753681]: rrd4j/GF_Kitchen_Water_2.rrd
Jan 24 11:32:11 srv-oh-02 lsyncd[1753681]: rrd4j/GF_Kitchen_Window_1.rrd
Jan 24 11:32:11 srv-oh-02 lsyncd[1753681]: rrd4j/OU_Temperature.rrd
Jan 24 11:32:11 srv-oh-02 lsyncd[1753681]: rrd4j/OU_Toilet_Light.rrd
Jan 24 11:32:11 srv-oh-02 lsyncd[1753681]: rrd4j/Security.rrd
Jan 24 11:32:11 srv-oh-02 lsyncd[1753681]: rrd4j/gDoor.rrd
Jan 24 11:32:11 srv-oh-02 lsyncd[1753681]: rrd4j/gGas.rrd
Jan 24 11:32:11 srv-oh-02 lsyncd[1753681]: rrd4j/gHumidity.rrd
Jan 24 11:32:11 srv-oh-02 lsyncd[1753681]: rrd4j/gLight.rrd
Jan 24 11:32:11 srv-oh-02 lsyncd[1753681]: rrd4j/gMotion.rrd
Jan 24 11:32:11 srv-oh-02 lsyncd[1753681]: rrd4j/gShutter.rrd
Jan 24 11:32:11 srv-oh-02 lsyncd[1753681]: rrd4j/gTemperature.rrd
Jan 24 11:32:11 srv-oh-02 lsyncd[1753681]: rrd4j/gWater.rrd
Jan 24 11:32:11 srv-oh-02 lsyncd[1753681]: rrd4j/gWindow.rrd
Jan 24 11:32:11 srv-oh-02 lsyncd[1753681]: sent 12,743 bytes received 161,256 bytes 115,999.33 bytes/sec
Jan 24 11:32:11 srv-oh-02 lsyncd[1753681]: total size is 20,477,492 speedup is 117.69 Jan 24 11:32:11 srv-oh-02 lsyncd[857]: 11:32:11 Normal: Finished a list after exitcode: 0
Установка и настройка MQTT-брокера
я выбрал один из популярных брокеров - Mosquitto.
Установка:
# dnf install epel-release
# dnf install mosquitto
В конфигурационный файл (/etc/mosquitto/mosquitto.conf
) нужно добавить password_file, чтобы получилось так:
listener 1883
log_type all
log_dest file /var/log/mosquitto/mosquitto.log
log_type all
password_file /etc/mosquitto/users.txt
Создаем пользователя openhab:
# mosquitto_passwd -c /etc/mosquitto/users.txt openhab
Остальные пользователи добавляются так:
# mosquitto_passwd -b /etc/mosquitto/users.txt user1 password
установим права на файл:
# chmod 644 /etc/mosquitto/users.txt
Подробности по управлению пользователями тут - https://mosquitto.org/man/mosquitto_passwd-1.html
Запускаем и добавляем его в автозапуск:
# systemctl start mosquitto
# systemctl enable mosquitto
По аналогии устанавливаем mosquitto на второй сервер.
Устанавливаем MQTT Binding в openHAB
Заходим на веб-интерфейс и идем в Add-on Store->Bindings->MQTT Binding, жмем Install. Подключаем MQTT bridge сдедующим образом: Settings->Things-> жмем СИНИЙ ПЛЮС->MQTT Binding-> MQTT Broker.
Заполняем поля:
Unique ID (Должен сгенерироваться автоматически, но можно и самому придумать);
Label;
Location;
Broker Hostname/IP;
Устанавливаем галочку “Show advanced” и далее заполняем:
Username;
Password;
После чего жмем “Create Thing"
В списке Things должен появиться MQTT Broker и статус должен стать Online.
Жмем опять СИНИЙ ПЛЮС, выбираем MQTT Binding и затем Generic MQTT Thing.
Тут выбираем Bridge который добавили ранее и жмем “Create Thing”. Вот что должно получиться в результате.
Добавим канал. Жмем на появившийся Generic MQTT Thing и переходим во вкладку Channels.
Теперь нажимаем "Add Channel".
Например, нам надо добавить канал для температуры в кухне, заполняем Channel Identifier (надо придумать), Label, можно еще указать Description, теперь выбираем тип “Number”, откроются дополнительные поля:
Тут заполняем “MQTT State Topic”, ставим галочку “Show advanced”
Устанавливаем единицы измерения - градус Цельсия.
А также желаемый формат вывода, так будет выводиться точность до десятых градуса. Жмем “Create”.
Предположим, у нас уже есть созданный Item такого плана:
Number GF_Kitchen_Temperature "Температура [%.1f]%unit%" <temperature> (GF_Kitchen, gTemperature) ["Temperature"]
Тогда жмем на создавшейся канал, теперь на маленький зеленый плюсик “Add link to Item”, откроется такое окошко:
Тут можно создать новый Item, но у нас он уже существует, поэтому жмем ”Item to Link”, выбираем из списка нужный и жмем “Link”.
Все, теперь если кто-то отправил в канал oh/kitchen/temp
значения температуры, то openHAB его оттуда возьмет. Получится вот такой график.
MQTT Explorer как инструмент отладки
Однако у нас пока нет настроенного оборудования, которое бы это делало, поэтому предлагаю проверить работу при помощи MQTT Explorer, устанавливаем отсюда - http://mqtt-explorer.com/
Подключаемся и можем читать/писать топики.
У меня была мысль поставить EMQX и настроить кластерный MQTT, или поднять mosquitto в режиме моста и как-то синхронизировать два сервера. Но оказалось, что данных репликации openHAB через lsyncd достаточно. Топики быстро переписываются и хранить данные на обоих MQTT-брокерах не обязательно, но можно.
Заключение
Вот таким образом удалось кластеризовать openHAB. В следующей статье мы соберем модуль умного дома на Arduino, подключим Ethernet, подключимся к MQTT-брокеру и сможем отправлять/получать данные, управлять реле и т.п.
Комментарии (9)
vazir
02.04.2024 08:08А почему он должен падать? Может неправильный выбор системы автоматизации просто?
t3hk0d3
02.04.2024 08:08+1На самом деле довольно неприятное явление. У меня умный дом на Home Assistant-e. Весь свет в доме контролируется через реле Shelly, либо через ZigBee контроллеры светодиодных лент.
Некоторые переключатели "отвязаны" от реле, и просто являются триггером для автоматизации в Home Assistant.
Плюс куча переключателей которые работают по Zigbee, и это работает только через HA.
Однажды у меня сдохла малинка на которой это все крутится - по какой-то причине случился USB undervoltage (судя по логам), и система подвисла.
Пока я был на работе, домашние не очень обрадовались что некоторые выключатели перестали работать, либо надо бегать и "вручную" выключать свет на этажах (на лестнице стоят ZB-кнопки которые выключают свет на всем этаже).
Проблему я впоследствии решил с помощью USB-хаба с внешним питанием, но осадочек остался.
vazir
02.04.2024 08:08Ну, от этого никто не застрахован. Кстати, зигби временами (от поддержки в прошивке устройств зависит) позволяет привязать друг-к-другу - тогда будут работать и без ХА и без координатора, если слышат друг друга (например пары кнопка икея+лампа так связаны и продавались парами), но это усложняет сетап, и появляется резонное замечание - чем гибче тем больше зависимости от "ядра". У меня были похожие "моменты" - но как ИМХО - критического ничего нет. Простой потребитель - да будет говорить "фи". Малинка - постоянно ругается на undervolt - но работает без нареканий. Хотя запитана 5ти амперным БП. Мне не нравится малинка, потому воткнул в конце себе Beelink N100. Потому следуем универсальным правилам... Там где можно планируем провода, потом уже радио, где радио делим от простого к сложному, зигби в приоритете, где невозможно там уже wifi. Как говорится your mileage may vary. И... проще относиться главное. Чем сложнее система тем более вероятны неучтенчики
t3hk0d3
02.04.2024 08:08Я просто хотел подчеркнуть что фактор hardware-отказа для домашней автоматизации очень даже реальный и неприятный (но не критичный).
У меня нет задачи построить пуленепробиваемую SLO=99.9999% систему.
Тут скорее речь не про надежность, а про resilience системы.
стати, зигби временами (от поддержки в прошивке устройств зависит) позволяет привязать друг-к-другу - тогда будут работать и без ХА и без координатора, если слышат друг друга (например пары кнопка икея+лампа так связаны и продавались парами)
у меня настроен Touchlink для некоторых вещей, но обычно он работает нормально только в рамках одного производителя (IKEA). С китайским ZigBee-устройствами вероятность фейла стремится к единице.
Малинка - постоянно ругается на undervolt - но работает без нареканий. Хотя запитана 5ти амперным БП.
У меня тоже, и обычно ничего не происходит, либо устройство просто перезагружается с kernel-panic-ом. Но тут редкий случай - оно тупо зависло, и пришлось сделать power-reset. Возможно проблема была в чем-то другом, но ругань на undervoltage была последней записью в логах.
Я решил проблему USB-хабом с внешним питанием + питанием по PoE (можно дернуть ресет через UI свича удаленно).
Там где можно планируем провода, потом уже радио, где радио делим от простого к сложному, зигби в приоритете, где невозможно там уже wifi.
Абсолютно согласен, придерживаюсь той-же идеологии.
GennPen
Не обязательно, можно настроить например репликацию раз в N минут. Но лучше всего использовать Ceph Storage.
Speccyfan Автор
С реепликацией я игрался, работает, но не все так просто, надо понимать, что упал сервер на котором работала основная копия и что нужно запустить реплику на соседнем сервере. Т.е. все должно отработать автоматически. Ну а Ceph у меня негде развернуть, используются два гипервизора, по одному SSD-диску в каждом. Да и я бы его не выбрал для такой задачи никогда.