OpenHAB и Siri
Я не большой фанат голосового управления, хотя испытываю его уже лет 10 с переменным успехом в разных устройствах. И машины две последние у меня голос понимали и Яндекс.Станцию купил и думал одно время о покупке Alexa и HomePod, но так как семья у меня не любит говорить на иностранных языках, а сам я предпочитаю кнопки жать ибо так мне проще почему-то…
Ну и вот сегодня в день программиста (хотя там не программирование, а писание конфигов и правил) я решил уже сделать что бы умный дом управлялся и голосовыми командами тоже. Так как та часть семьи, что живёт в доме, а не по другим городам, у меня использует продукцию Apple, то задача сводилась к тому что бы разобраться как правильно анонсировать элементы (Items) из OpenHAB в HomeKit API. Системы весьма разные по логике и форматам, так что, я начал с простых, но востребованных функций типа «открыть калитку» или «включить торшер».
Сразу скажу, что вряд ли я в полной мере освоил HomeKit API за сегодня, так что опишу самые простые вещи и то сколь просто они делаются.
Для начала, короткое пояснение как у меня устроен умный дом. В нём куча разных технологий объединяются через OpenHAB. Отопление у меня управляется через KNX, пара плат реле по 16 портов управляется вовсе через Web-JSON, кроме того, есть всякие странные штуки которые работают через WiFi и MQTT и просто через какие-то облака, есть даже SNMP. Например, данные своей метеостанции мне удобнее считывать не с неё напрямую (хотя я это делал), а через API WeatherUnderground ибо там ещё и прогноз весьма точный по моей локации рассчитывают ну и владельцам метеостанций которые публикуют им данные с них они лают бесплатный доступ к API чем всегда приятно воспользоваться. Кондиционеры вот я думал делать с локальным управлением, но у заводских решений ценник меня как-то совсем не устроил, а городить самому отдельные контроллеры на каждый кондиционер мне совсем лениво, так что, пока использую облако от производителя кондиционеров ибо там вышло недорого и вполне неплохо работает.
Весь этот «зоопарк» рапортует о всех событиях в OpenHAB, который крутится под Linux на Jetson Nano. Ну и обычно я управлял умным домом либо чрез панели на стене подключенные к KNX, либо приложением на телефоне (у OpenHAB вполне неплохое приложение). Смысл сводить всё это странное на одну платформу в том, что бы можно было писать правила, не обращая внимание на то как подключено устройство. Мне очень понравилась идеология OpenHAB в плане как возможностей, так и продуманности. Уже 5 лет им пользуюсь и не перестаю удивляться как возможностям, так и вновь появляющимся модулям интеграции.
Сразу скажу, что без вот этой платформы в центре никакой разумной возможности довести дело до команд Siri не предоставлялось мне возможным.
Теперь пару слов о Siri — это голосовой помощник от Apple, который работает практически на всех устройствах Apple, но наиболее удобен он на часах, как мне кажется. Так как Siri и HomeKit — это разработка Apple, то интегрированы они друг в друга так что «нет никаких настроек», то есть Siri просто по умолчанию понимает все устройства которые есть HomeKit. То есть, если я в HomeKit описал «торшер» то сразу можно говорить «Сири, включи торшер» и он включится! Для управления HomeKit используется приложение «Дом» на устройствах там можно как кнопки нажимать, так и слова на которые Сири будет понимать о каком устройстве идёт речь понимать. Важно так же сказать, что в HomeKit есть понятие «комнаты» и Siri его тоже понимает, Суть комнат в том, что устройства с один названием (у меня, например, это «кондиционер» и «торшер») находятся в разных комнатах. Если сказать: «Сири, включи торшер» имея в HomeKit несколько устройств с названием «торшер», то включатся все. Но если сказать: «Сири, включи торшер в кабинете», то включится торшер в комнате названной «кабинет» в HomeKit. Однако, приложение «Дом» меня откровенно расстроило — оно УБОГОЕ!!! Там нет уймы простых и важных функций, например, при всей такой вот интеграции с разными устройствами Apple фото помещения не предаётся на другой устройство при том, что всё остальное там видно. Интерфейс у приложения Дом тоже выглядит «как не родной», что удивительно. Но та как у меня была задача дойти до управления голосом, то это мне не особо важно ибо кнопки я могу и в приложении OpenHAB нажимать, где они намного удобнее. Не уверен, что устройства можно анонсировать сразу в конкретных помещениях из OpenHAB в HomeKit, хотя это было бы удобно, но явно проблема с однозначностью, так как в OpenHAB используется понятие «группы», которое может быть как комнатами, так и типа ми устройств или вовсе этажами. Ну и в логике OpenHAB одно устройство может входить в множество групп.
Перейдём от общих слов к конкретике. Первое что я сделал — это добавил открытие ворот в режиме калитки. Эта функция нужна когда мы возвращаемся домой или когда к нам приходят гости. У меня ворота откатные управляются через виртуальный элемент «Vorota» для однозначности и удобства интерфейса. То есть в описание элементов (Items) написано буквально:
Number Vorota "Ворота var" <door>
в угловых скобках тип элемента который выглядит как дверь в мобильном приложении. Сделана эта переменная была ради «дизайна» что бы в одной строчку разместить как полное открытие ворот, так как и частичное (калитка). Выглядит это в файл типа .sitemap следующим образом:
Switch item=Vorota label="Ворота +" mappings=[2="Калитка",1="Открыть"]
а на телефоне выглядит вот так (иконка приоткрытой двери тут унаследовалась из описание Item где тип элемента описан:
Интеграция OpenHAB и HomeKit требует описания или тэга или мета-данных, то есть в простом случае достаточно нужному элементу просто добавить тэг Switchable. При конфигурации через конфигурационные файлы типа .items нужно просто добавить в строку описания элемента [ "Switchable" ]
. но тут возникает проблема, что когда я делал логику управления воротами, то рассматривал не сами ворота и положение конкретного переключателя, и оно получилось инверсным к понятию открытой/закрытой двери в HomeKit. Так что, переменная Vorota мне не подошла и пришлось делать новую:
Switch VorotaSiri "Ворота" <door> [ "Lock" ]
Тут тег Lock выглядит как замочек в приложении «Дом» на телефоне:
Однако, тут видно, что Гараж и Сарай пока выглядят как выключатели и этому есть причина — я пока не придумал как сделать их «замочками» что б оно корректно, хотя герконы для решения этой задачи уже заказал на Aliexpress. Наверное, можно и без концевиков, но хочется сразу решить несколько задач, то есть, я их заказал не для голосового управления, но пока думал как лучше делать пришёл к выводу, что лучше дождаться герконов с магнитами и сразу делать новые правила формирования импульсов.
Для того что бы виртуальная, то есть без привязки к железу, переменная VorotaSiri чего-то делала я написал пару правил в фале типа .rules
rule "Открыть калитку"
when
Item Kalitka received command OFF
then
Vorota.postUpdate(2)
end
rule "Закрыть калитку"
when
Item Kalitka received command ON
then
sendCommand(MySwitch3, ON)
end
В первом правиле меняется значение виртуального элемента Vorota что бы сработало правило, которое работает для OpenHAB, в во втором в просто включается реле которое. Тут важно знать, что есть правило, которое при включении реле, которое должно формировать импульс, то есть имитировать нажатие кнопки, через секунду его выключает. Выглядит это правило вот так и существуют подобные правила у меня давным давно и доказали свою полезность.
rule Close
when Item MySwitch3 received command ON
then
Thread::sleep(1000)
sendCommand(MySwitch3, OFF)
Vorota.state = NULL
end
Тут написано, что если пришла команда ON на реле MySwitch3, то нужно подождать 1000 микросекунд и после этого перевести реле в положение OFF, ну и заодно сбросить состояние ворот в нулевое. Это делается для того что бы на телефоне кнопка «калитка» была серенькой одну секунду индицируя что команда прошла. То есть если команда не пройдёт, то кнопка «калитка» в приложении или не станет серой или не вернётся к чёрному цвету. Cамо управление реле у меня рабоатет вовсе через HTTP, так что, описание элемента MySwitch3 выглядит очень длинно:
Switch MySwitch3 "1-3 Закр. ворота" <door> (Sw,Keys) {http=">[ON:GET:http://192.168.51.14/pwr/relays/3?ac= XXXXX&value=1] >[OFF:GET:http://192.168.51.14/pwr/relays/3?ac=XXXXX&value=0] <[http://192.168.51.14/pwr/relays/3?ac=XXXXX:30000:JSONPATH($.v)]"}
Про угловые скобки я уже писал, в а в круглых скобках группы. В фигурных скобках находится описание действий. Кроме ON/OFF там есть считывание состояния (то есть ответ на HTTP запрос анализируется) и выделение значения из JSON. В данном случае ip-аддрес платы с реле прибит гвоздями, равно как и пароль в явном виде просто заменён XXXXX. Платы очень простые, так что, вот такая вот циничная адаптация к китайским реалиям. Тут так же важно уточнить, что это я писал примерно 5 лет назад, во времена версии 1.2 или 1.3 OpenHAB а не в нынешней 2.5
В свете перехода OpenHAB с текстовых файлов конфигураций на JSON я уже часть устройств описал через PaperUI, то есть не в виде текста, а в интерфейсе который работает с JSON. Тут важно сказать, что OpenHAB сейчас находится в переходном состоянии поддерживая совсем старые конструкции и внедряя новые подходы. Так как проект «любительский», то есть некоммерческий и полностью открытый, то развитие его идёт очень неравномерно в зависимости от интересов конкретных людей. Отчасти, помогает, что они объединились с Eclipce SmartHome, но развитие последнего явно оставляет желать лучшего. По сути это действо позволило увлечь больше разработчиков в OpenHAB. Так как у меня не складывается полностью переписать старую часть на новые «рельсы», то часть всё что мне пришлось переделывать, например, из-за того что IBM купила WeatherUnderground и Weather Conpany не только поменяла сервера (включая API), но и саму политику доступа к API полностью убрав бесплатную часть, но сохранив пока бесплатный доступ для тех владельцев АМС, которые делятся своими данными.
Прелесть нового интерфейса, конечно, в автоматическом добавлении всех известных объектов (Things) из обнаруживаемых устройств. Дальше на основе автоматически генерированных каналов можно как раз создавать востребованные элементы (Items). Несмотря на сложное описание в словах, на практике, это много проще, чем писать слова в конфигурационных файлах. Попробую продемонстрировать.
Сначала из каталога (бесплатный магазин) я установил Add-On Weather Company то есть интеграцию с конкретным API.
Посмотрел какие Things искать дальше.
Добавил Thing под названием Local Weather где указал ключ для доступа к API и код своей метеостанции (PWS Satation ID) что бы данные использовались именно её. Насколько я понимаю указание типа геокодирования и сами координаты нужны для прогноза ну или вовсе не обязательны при указании конкретной метеостанции.
В результате я получил объект (Thing) под названием Local Weather у которой есть уйма каналов и к некоторым (где стоят точки в центре) я привязал элементы.
В частности в Channel Current Temperature мной создан элемент LocalWeather_PwsObservations_CurrentTemperature (название автоматически сформировано я только выбирал привязывать к существующему элементу или новый создать).
И вот тут оказывается, что в PaperUI нет места куда указать тэг!!! И это не самая тривиальная проблема. Однако, так как у OpenHAB очень большое сообщество, то я нашёл два варианта решения проблемы.
Первый путь — использование REST API. Для него есть интерактивная документация выглядящая как API (это Add-On который надо установить в разделе UI)
В ней нахожу раздел Items.
Выбираю запрос PUT /items/{itemname}/tags/{tag} и открыв его указываю в полях для ввода название элемнтена и тэг, который хочу установить для него и жму кнопку «Try it out!» понимая, что попытка может быть неудачной. Не самый очевидный, конечно, путь.
Второй путь требует большего нажатия кнопок, но намного более понятен. Это использование интерфейса HABmin, который выглядит явно недоделанным как и интерфейс Paper. Однако, в нём полей намного больше чем в Paper. Но путь тоже не самый тривиальный ибо непосредственно элементы Items он не даёт редактировать в отличии от REST API.
Тут нужно выбрать объекты (Things) найти (можно поиском) Local Weather и пролистав до конца список каналов (в данном случае листать долго ибо API даёт 406!!! каналов) увидеть, что есть 22 активных канала и эта надпись при нажатии открывает страницу каналов. Под активностью подразумевается наличие связанного с каналом элемента.
Среди каналов нужно найти интересующий нас (Current Temperature) и сдева от его названия есть синяя кнопка редактирования, открывающаа вясплывающее окно. Тут внимательный читать должен воскликнуть, что кругом обман и подлог ибо в PaperUI канал Current Temperature внятно был описан как «Current observations from Personal Weather Station», а вовсе не как прогнозируемая температура («Forecast Temperature») в HABmin. Однако, по моим наблюдениям конкретное значение меняется намного чаще, чем прогшноз что позволяет полагать, что в PaperUI написана правда а в NABmin закралась ошибка.
Тут есть поле «Теги» и в него можно писать что-угодно. В данном случае я написал «A1» для примера, а до этого вдумчова написал «TemperatureSensor» хотя, конечно, я не писал, а мышкой из документации по Add-On копировал просто. Важно после ввода текста нажать на синюю полоску, которая создаст новую метку и после этого сохранить элемент.
Ну и сразу после того как у элемента появляется тег который признаёт своим интеграция HomeKit Add-On он становится виден в приложении Дом на компьютере и гаджетах Apple.
Сама интеграция требует небольшой настройки. Нужно выбрать: Сервисы — Настройки — IO и там уже выбрать HomeKit, предварительно установив его, конечно.
В документации есть рекомендации по формированию PIN.
Если телефон и OpenHAB находятся в одной локальной сети, то после этой настройки в приложении «Дом» можно добавить аксессуар.
Сначала нужно нажать плюсик в верхнем правом углу (это с телефона скриншот) а в появившемся окне нажать последний вариант где «нет возможности сканировать». Тогда запустится поиск по локальной сети и после обнаружения OpenHAB будет предложено ввести PIN.
После этого можно проверять что получилось. Я сначала проверил кнопками, а потом голосовыми командами.
Надеюсь это кому-нибудь пригодится.
PS: обнаружилась очень приятная возможность в использовании этой связки. В приложении «Дом» есть автоматизация, и первое же правило для замков — предлагать открыть при приближении. Сразу скажу, что я пытался это реализовать как только появился Add-On для iCloud где показываются локации устройств, однако, использовать данные из iHome не получилось так как задержка в обновлении локации устройств там весьма большая и не годится для открывания дверей совершенно! А тут, судя по всему, всё происходит на устройстве, а не в облаке, так что, работает вполне неплохо! Тут так же важно отметить, что появляется предложение в виде уведомдения от Siri «запустить автоматизацию», в моём случае я описал самое частое действие — открыть калитку. Реально удобно!