[Из песочницы] Умный дом без пультов, но с кубиком
Проблема
На время ремонта новой квартиры я вернулся в квартиру, в которой не жил 10 лет и решил поупражняться в дисциплине «Умный дом», чтобы со знанием дела обустраивать уже новую квартиру. Техника в этой квартире тоже не самая умная и не самая новая, ибо была произведена ~10 лет назад. Больше всего в квартире меня напрягало обилие инфракрасных пультов, они терялись и нагружали мозг подбором нужного. До недавнего времени было принято на пультах делать огромное количество малоиспользуемых кнопок. А еще пульты не эстетичны и не гигиеничны, одни угловатые, другие с скруглёнными гранями, кнопки желтеют, в них копятся остатки жизнидеятельности обитателей на которых образуется «подкнопочный биоциноз». В итоге по дому разбросано десяток пультов с кучей ненужных кнопок, для простой операций приходилось искать по две-три штуки, их вид царапает взор, хотелось удобного тактильного и модного голосового управления.
Цель
На замену куче пультов хотелось взять современное устройство с приятным дизайном, чтобы разница по сравнению с пультами бросалась в глаза. Ответной частью контроллера должно стать устройство умеющее обучаться инфракрасным сигналам с существующих пультов. Беглый поиск и маркетинг xiaomi сделали своё грязное дело и взор мой пал на Xiaomi universal IR remotecontroller и Xiaomi Mi Smart Home Magic Cube, а чтобы эти ребята могли общаться пришлось купить Xiaomi smart home gateway 2
Приключения
В теории всё казалось просто, вот кубик, вот излучатель IR сигналов, вот их предводитель — ZigBee гейт. Но жизнь, как обычно, богаче.
Уже при подключении этого всего стало весело, без интернета это всё не настроить, все устройства требуют связи с серверами xiaomi, кроме того, продаваемые устройства произведены для китайского рынка и для их работы в родном приложении Mi Home требуется установить регион «Китай». Всё бы ничего, но если у вас регион Китай то используйте и китайские сервера, выбора не предоставляется. Я не параноик, не против чтобы КГБ товарища Си Цзиньпина знало когда и какие инфракрасные сигналы я посылаю своим колонкам и телевизорам. На практике оказалось, что почти все способности умных устройств гвоздями прибиты к серверам и без их ведома почти ничего не делают, сами сервера далеко (в Китае) в итоге послав из приложения Mi Home 10 сигналов увеличивающих громкость колонок приходилось ждать секунд 5 до начала увеличения звука, и еще секунд 30 до завершения обработки всех 10 сигналов, да и сами сигналы излучались не быстренько, а рывками, звук увеличивается на 1 затем ждет секунду еще на два, снова ожидание итд. Удобство так себе, врагу не пожелаешь…
Беда из Китая не приходит одна, кроме тормозов натирать стала невозможность прикрутить умный кубик к управлению звуком.
Кубик управляется жестами:
- Встряхнуть
- Подвинуть на плоскости
- Повернуть на 90/180 градусов вокруг горизонтальной оси
- Повернуть вокруг вертикальной оси
- И др…
Все действия триггеры — то есть сделал действие, пришел сигнал о том, что оно случилось, но для поворота вокруг вертикальной оси кубик умеет мерять еще и градус поворота, поэтому жест поворота удобно использоваться для управления звуком, повернул на 90 градусов по часовой стрелке — звук увеличился на 10 пунктов, повернул на 45 против часовой стрелки — звук уменьшился на 5 итд. В родном приложении нет возможности реализовать такое поведение в связки с инфракрасным излучателем, лучшее что умел мой комплект — это управление яркостью светодиодов на гейте ZigBee, это настолько-же прикольно насколько бесполезно, да еще и с 3х секундной задержкой имени Китайских серверов.
Чтобы одолеть сию оказию начал смотреть как устройства дружат с опенсорсными проектами типа Home Assistant, оказалось что да, есть такая возможность, но в Xiaomi явно решили придушить её, спрятав токены для общения с излучателем и закрыв порты через которые идет общение с ZigBee гейтом. Security token для общения с IR излучателем были по советам из интернетов выужены из логов на андроид устройстве, для этого пришлось установить приложение Mi Home годичной давности в котором был такой баг. С xiaomi gateway было чуть сложнее, пришлось подпаиваться к его UART RX/TX для того чтобы с консоли открыть порты через которые с ним общается Home Assistant.
Сам Home Assistant надо где-то запускать, под эту задачу подошел Synology DS718+ который использовался у меня как DLNA медиацентр и торрентокачалка. Это устройство умеет запускать Docker контейнеры и в нем легко завёлся контейнер с Home Assistant. Home Assistant штука крутая, но в отличии от Mi Hime всю умность дома в нем нужно писать ручками в yaml. Освоив DSL понимаемый Home Assistant и поплевавшись от еще одного средства программирования не требующего знания ЯП удалось состряпать костыль нужной формы.
Код автоматизации:
- id: volume_up alias: Volume up trigger: - event_data: action_type: rotate entity_id: binary_sensor.cube_0000000103ec74 event_type: xiaomi_aqara.cube_action platform: event condition: condition: template value_template: "{{ trigger.event.data.action_value > 0 }}" action: - service_template: "script.bbk_vol_up_{{ (trigger.event.data.action_value / 3) | int }}"
Эта автоматизация отлавливает событие поворота по часовой стрелке и вызывает скрипт в имя которого подставляется кол-во сигналов увеличения звука которые должен послать инфракрасный излучатель. Как вы наверное догадались, для каждого угла поворота требуется свой скрипт, на их создание была призвана копипаста, она и народила мне вот таких скриптов 20 штук:
bbk_vol_up_10: sequence: - data: command: - bbk_vol_up delay_secs: 0.04 num_repeats: 10 entity_id: remote.xiaomi_miio_192_168_2_62 service: remote.send_command
Конфигурация излучателя с перехваченными сигналами с пульта колонок выглядят вот так:
remote: - platform: xiaomi_miio host: 192.168.2.62 token: 392cbed325e862ffff983c4575b7a6f2 commands: bbk_power: command: raw:nE5m0wlk0msxmEsmszmEsm0wAHKaABkAoQAcAL1MZtOQEFmM3ARMCHwCymM2m4ENgXEAioHlgy+AwoL3gvYAh4L0gGGEBYLCAL0BR4CHhU4B+wQ8TCAA bbk_vol_up: command: raw:nMwmUwlk0mk1mEsms3ADKbABlM5hLJtMAD2ALKazkAdgAymM3AYMBApjNgKTmgGLABuBD4IaAEKA1YJrgyuBDwJvgZeEx4C/geHMZsA4YCDgxoAgwR3hU+A1ICJTCAA= bbk_vol_down: command: raw:nE5m0wlk0msxmEsmszmEsm0wAHKaABkAoQAcAL1MZtOQEFmM3ARMCHwIfAdQBFZuAQYFfAfuBCoHngveEx4C/gL+Cj4R2ANfLJqAYQUChU3MIAA=
Ура! Звук управляет поворотом кубика вокруг вертикальной оси, а включаются и телевизор и колонки поворотом кубика вокруг горизонтальной оси на 90 градусов.
Из Home Assistant все управляется, но хочется же еще и голосом этим рулить, Google Assistant подключается в Home Assistant, но тоже не без приключений. GA не показывает в интерфейсе скрипты, зато показывает выключатели. Понятие выключателя не ложилось на мой телевизор, так как не существовало программного способа понять включен он или выключен. Однако я нашел у телевизора разьём для Ethernet кабеля, но не нашел описания протокола общения по нему, поэтому решил использовать признак наличия IP адреса телевизора в сети в качестве сенсора, если IP телевизора в сети есть — он включен, если нет выключен. Чтобы реализовать такой сенсор пришлось написать простенький custom_component для Home Assistant:
import logging from homeassistant.helpers.entity import Entity from pythonping import ping logger = logging.getLogger(__name__) def setup_platform(hass, config, add_entities, discovery_info=None): entities = [] for name, ip in config['hosts'].items(): entities.append(IPSensor(name, ip)) add_entities(entities) class IPSensor(Entity): def __init__(self, name, ip): self._name = name self._ip = ip self._state = None self._is_on = None @property def name(self): return self._name @property def state(self): return self._state @property def state_attributes(self): return {'ip_address': self._ip} @property def device_class(self): return 'connectivity' @property def is_on(self): return self._is_on def update(self): result = ping(self._ip, count=1, timeout=0.1) self._is_on = result.success() self._state = 'on' if result.success() else ‘off'
Затем связать инфракрасный излучатель с сенсором в переключатель вот так:
switch: - platform: template switches: toshiba_tv: value_template: "{{ is_state('binary_sensor.toshiba_tv', 'on') }}" turn_on: service: script.toshiba_power turn_off: service: script.toshiba_power
И вот такой вот переключатель стал отображаться в Google Home и управляться с голоса.
P.S. Упражнение с умным домом прошло успешно, пошел закупать новые устройства!
P.P. S. А ZigBee хаб теперь зачем-то освещает прихожую…