Умный дом - теперь и у геккона

Оригинал поста на хабре

Недавно при странных обстоятельствах у меня появился вот такой зверь:

В целом он довольно неприхотлив, но хотелось обеспечить ему самые приятные условия для его хладнокровного существования. Не то чтобы это были какие-то нетривиальные задачи, мне просто показалось интересным, что у технологий есть ещё и такое внезапное применение.

Что нужно было сделать:

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

  • Поддерживать минимальную влажность

  • Включать ему ультрафиолетовую лампу в 5 утра, когда он любит выползать поваляться на камушке.

Вроде бы несложно. У меня был мешок реле, датчиков, Home Assistant и Arduino. Но если ты начал собирать умный дом, становится трудно остановиться. Единственное, что у меня вызывало опасение - это Arduino. Нет ничего более беспомощного, безответственного и испорченного, чем Arduino. Я знал, что рано или поздно я перейду и на эту дрянь.

Казалось бы, всё просто - засунь туда датчиков, подключи к ESP, да щёлкай релешками. Но хотелось точных датчиков, маленьких и автономных, и достаточно стабильной работы, чтобы не сварить и не заморозить животное. И тут оказался прям большой простор для разных вопросов и работы.

Дисклеймер

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

Датчики

Итак, вернёмся к теме. Для измерения температуры и влажности я выбрал Aqara Temperature and Humidity Sensor на Zigbee - они маленькие, красивые, и автономно работают от батареек-таблеток. Да, именно “они” - поскольку температуру нужно мерять и в холодном и в горячем углу. Кроме этого у меня ещё был похожий датчик Mija, только с LCD и работающий по BLE, а не Zigbee. Он висел сверху, и я его там и оставил, как дублирующий - много датчиков не бывает!

Для того, чтобы всё это прокинуть в Home Assistant, я использовал Xiaomi Gateway 3, специально прикупленный для этих целей. Привязываем к нему датчики, ставим нужный custom component в Home Assistant, и получаем все нужные данные! Прям сказка.

Обогрев

Для обогрева мне приглянулась керамическая лампочка. Она не производит лишнего света и по идее живёт вечно. Правда, я погорячился и взял её на 100Вт. Даже через диммер она выдаёт слишком много тепла, так что сейчас я жду, пока мне придёт такая же на 50.

Увлажнение

Для этого я поставил обычный ультразвуковой увлажнитель, направив его носиком в террариум.

Ультрафиолет

Для этого ставят специальные лампы для рептилий. Не знаю, насколько это маркетинг, но несколько герпетологов порекомендовали поставить, и я решил поверить им на слово.

Реле

Девайсы подготовлены, датчики тоже. Теперь надо всё это чем-то включать. Навскидку у меня не получилось найти трёхканальных умных реле за вменяемые деньги, так что я просто взял стандартные пятивольтовые реле для ардуинок с али. Немного неудобно тем, что я не знаю, как с них снимать ток, а так же я подумываю о замене их на твердотельные… Но пока это не вызвало каких-то проблем, и я стараюсь вкладывать усилия по мере необходимости.

Контроллер

Дома лежит мешок NodeMCU, Wemos D1 R1 и Wemos 32, так что я взял старый добрый D1 R1 на ESP8266 и решил наконец пощупать ESPHome. До этого я прошивал контроллеры через Arduino IDE по USB и использовал руками настроенные MQTT топики, а тут решил, что хватит это терпеть - есть подходящий повод разобраться.

В общем, ESPHome оказался просто волшебной штукой. Пишешь простой YAML, всё прошивается по воздуху, все топики и прочее добро создаются за тебя, и девайс сам обнаруживается в Home Assistant. Просто магия! Фактически вся настойка реле выглядела вот так:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
switch:
- platform: gpio
pin: D2
name: Relay1
id: relay1
inverted: true
- platform: gpio
pin: D3
name: Relay2
id: relay2
inverted: true
- platform: gpio
pin: D4
name: Relay3
id: relay3
inverted: true

Триггеры

Отлично, теперь есть всё железо и софт, можно включать и выключать всё через Home Assistant, однако… Ничего ещё не автоматизировано.

И в этом помогают Automations от Home Assistant. В целом они вышли довольно тривиальные:

  • Если температура ниже x, то включить обогрев
  • если температура выше x, то выключить обогрев
  • то же самое для влажности
  • в 5 утра включить лампу, в 17 выключить
  • если температура критически низкая или высокая, то послать уведомление в телеграмм

Ура, кажется, на этом наш MVP готов. Всё работает и рисует красивые полезные графики:

Но есть нюанс! Пока это не выглядит достаточно безопасным. Что, если реле залипнет, пока я сплю и не услышу уведомление в телеграмм? Я совсем не хочу получить на завтрак жареного геккона!

Тогда я понял, что нужен дополнительный способ алертинга. Можно было бы для этого переиспользовать умные колонки с Алисой, но они стоят только у детей (жаба давит ставить в каждую комнату), и не хотелось бы их пугать по ночам, если что.

Ну что же. Если у тебя в руках ардуина, то всё вокруг кажется гвоздём. Берём её, втыкаем в неё пищалку, и настраиваем её как включаемую сирену с полифонической мелодией. Добавляем включение этой сирены как переключатель в Home Assistant. Попутно ещё я закинул туда сервис для Home Assistant, который даёт играть на ней любую мелодию. Ну, потому что мог. Наверное, это единственная штука, которая была не совсем тривиальной, поэтому даже закину код:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
esphome:
name: alam
on_loop:
then:
if:
condition:
- switch.is_on: alarm_sensor
- not:
rtttl.is_playing
then:
- rtttl.play: 'MissionImp:d=16,o=6,b=95:32d,32d#,32d,32d#,32d,32d#,32d,32d#,32d,32d,32d#,32e,32f,32f#,32g,g,8p,g,8p,a#,p,c7,p,g,8p,g,8p,f,p,f#,p,g,8p,g,8p,a#,p,c7,p,g,8p,g,8p,f,p,f#,p,a#,g,2d,32p,a#,g,2c#,32p,a#,g,2c,a#5,8c,2p,32p,a#5,g5,2f#,32p,a#5,g5,2f,32p,a#5,g5,2e,d#,8d'

switch:
- platform: template
name: "Alarm Switch"
optimistic: true
id: alarm_sensor
internal: false

output:
- platform: ledc
pin: GPIO18
inverted: true
id: rtttl_out

rtttl:
output: rtttl_out
on_finished_playback:
- logger.log: 'Song ended!'

api:
services:
- service: play_rtttl
variables:
song_str: string
then:
- rtttl.play:
rtttl: !lambda 'return song_str;'

Вот так в 40 строчек программирования на ямлах получается вполне сносная сирена, которую слышно по всему дому.

Помимо этого, я подумал про случай, когда реле включилось, и на этом мой сервер Home Assistant умер и не выключил его. Я по прежнему не хочу жареного геккона, так что добавил туда простую проверку - реле обогревателя выключается через 20 минут после включения. А если вокруг правда мороз и оно всё ещё должно быть включено - не беда, Home Assistant включит его обратно!

Код такой проверки на ямлах написать у меня не получилось, и я запользовал так называемую лямбду в ESPHome:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
on_loop:
then:
lambda: |-
static unsigned long last_update = 0;
static unsigned long enabledForTime = 0;
int iteration = 5000; // every 5 sec
if((last_update + iteration) < millis()){
last_update = millis();
if(id(relay2).state){
enabledForTime+=iteration;
}
else{
enabledForTime = 0;
}
ESP_LOGD("ERM", "Heat relay enabled for: %lu", enabledForTime);
if(enabledForTime> 1000*60*20){ // 20 min, safety measure
ESP_LOGD("ERM", "Turning off heat relay");
id(relay2).turn_off();
enabledForTime = 0; // avoid confusion when HA turns on relay back
}
}

Вот теперь, кажется, всё. Возникает мысль добавить перед реле ещё яндекс розетку (которая у меня тоже управляется локально, поскольку она туя), чтобы через неё перезапустить контроллер, если что… Но не хочется добавлять точек отказа без необходимости. Да и на крайний случай всегда можно призвать соседку проверить зверя. В конце концов, мне не нужны пять девяток в стабильности, я не Яндекс.геккона делаю.

Вопросики

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

Q: А что если пропадёт интернет?

A: Ничего. Всё будет продолжать работать как работало. Только извне показания датчиков нельзя будет узнать и получить уведомления в телеграмм. Если бы интернет падал часто и это было бы супер критично, можно было бы настроить резервный канал. Но… И так сойдёт.

Q: А если пропадёт электричество?

A: Хуже, чем без умного дома, не будет. Как только электричество появится - всё восстановится. В целом дома тепло, но если бы хотелось гарантий обогрева - можно было бы поставить бесперебойник на роутер, сервер HA и реле с потребителями.

Q: А если сдохнет батарейка в датчике?

A: Триггеры опираются на показания трёх датчиков. Три одновременно - не сдохнут.

Q: И всё же. Что если залипнет реле или повиснет микроконтроллер?

A: Залипание реле можно пролечить удалённой перезагрузкой микроконтроллера. Зависание микроконтроллера - вариантом с внешней умной розеткой. Но вообще это кажется пренебрежимо редким кейсом, с которым справится уведомление, сирена, и на худой конец - визит друга.

Итоги

Мне определённо понравилось то, что получилось. Умный дом для геккона сделал жизнь приятнее и комфортнее и мне и ему.

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

Безусловно, ничего технически сложного в проделанной работе нет, и я предвижу вопросы “зачем это тут?”. Однако, мне кажется интересным именно синергетический эффект простых вещей, которые вместе дают сделать довольно прикольные штуки. Раньше я уже описывал открытие ворот, полив цветочков, управление ёлкой и детские игры на умном доме. Кажется, что со временем будет появляться всё больше таких решений, причём не для бородатых нердов, а для нормальных людей, и они будут классно и красиво работать из коробки.

Можно ли было сделать лучше и проще? Возможно, я что-то не учёл? Да наверняка. Надеюсь, вы подскажете мне в комментариях.