Умный дом из пыльного планшета

4d97fea83be763c50df1be1d372bcdfe.png

Наверное, каждый из нас задумывался о том, как было бы классно, если бы кондиционер сам включался, когда мы приходим домой. Однако для управления всеми устройствами либо используют готовое решение из облака, либо приходится заморачиваться с покупкой микрокомпьютера, чтобы умный дом не стал глупым без интернета :) Но нужен ли для этого микрокомпьютер, если наверняка в шкафу лежит запылившийся планшет или смартфон, который когда-то работал и с более требовательными приложениями?…

С чего всё началось?

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

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

И всё классно, все работает от приложения (стандартная Tuya), есть настройка расписания… но:

  • Хочется добавить немного интеграции со смартфоном, например, включение света по будильнику или в стандартное время. И с этого момента появилось желание разнообразить себе вечера настройкой и конфигурированием системы автоматизации.

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

Устройство

Наверное, самое простое — это купить Raspberry Pi и дальше можно без ограничения фантазии творить, ибо руководств и различных пошаговых инструкций полно. Но, покопавшись в шкафу, я нашёл прекрасный планшет Samsung GT-P3110. Отличный кандидат на замену Raspberry, да ещё и экран с сенсорным вводом — можно совместить с панелью управления.

Характеристики планшета

Samsung GT-P3110 Samsung GT-P3110

Постоянная память

8 ГБ

Оперативная память

1 ГБ

Чипсет

Texas Instruments — OMAP 4430

Частота

1 ГГц

Последний официальный ROM

Android 4.1.1

Последний неофициальный ROM

Android 7.0.1

Осталось лишь узнать, можно ли каким-то образом запустить тот самый Linux, на основе которого работает Android, и добавить в него нужное ПО. И именно такую возможность предоставляет приложение Termux. Из критических ограничений: для работоспособности необходим минимум Android 5 (API 21), а последние версии вообще работают только с Android 7 (API 24). Первое, что приходит в голову в этой ситуации — неофициальные прошивки (со всеми вытекающими). И именно для этой модели последняя неофициальная версия ПО была тем самым Android 7. До последнего не верил, что мне может так повезти… и как выяснилось, был прав.

Обновлённая до этой версии ОС работала крайне медленно. Мне планшет напоминал чем-то ноутбук 2005 года, пытающийся работать на современной ОС: всегда после включения надо сходить попить чаёк минут 30, пока он запускается. Здесь всё было так же. Спустя 30 минут на планшете можно было не спеша настраивать все параметры, ни о каких выходах в браузер речи не шло, две вкладки — и отклик на нажатие составляет около 5 секунд. Но всё же Termux был установлен, а также добавлен доступ по SSH, с помощью которого работа пошла значительно быстрее.

Система автоматизации

Далее нужно выбрать систему автоматизации. Поиск выдаёт в большинстве случаев лишь одну систему — Home Assistant. Ради справедливости, я нашёл альтернативы в виде Domoticz и ioBrocker. И, честно говоря, не стал углубляться в подробности, поскольку взглянув на интерфейс всё стало понятно. Да, возможно, в ioBrocker более обширная поддержка редких датчиков и прочее, но все эти достоинства меркнут, когда речь заходит о просто приятном внешнем виде, на который вы будете обращать внимание больше всего при работе с системой.

Внешний вид HA, Domoticz, ioBrocker

Home AssistantHome AssistantDomoticzDomoticzioBrockerioBrocker

Итак, решено, системой автоматизации будет Home Assistant (сокр. HA). Недолго думая, я попробовал найти на просторах сети первопроходцев, которые пытались подружить Home Assistant и Termux, поскольку я был уверен в том, что не могу быть первым гениусом, задумавшим использовать Android-устройство, а не Raspberry или любой другой микрокомпьютер. И оказался совершенно прав, нашлись целых два счастливчика, кто не постеснялся написать статью по установке в далёком 2020 году.

Какие возникли трудности и опасения:

  • все взаимодействия происходили с аппаратами на официальных прошивках, что гарантировало их полную работоспособность;

  • в одной статье говорилось о необходимости 16 Гб памяти устройства, что вдвое больше, чем на моём планшете;

  • документация морально устарела и пришлось проделать множество дополнительных действий.

Действия по установке HA в Termux

Минимальные требования:

  1. Android 7.0 +.

  2. Память 8 Гб (влезет и на 6, но совсем без плагинов).

  3. Стальные нервы =)

Для начала установим всё необходимое окружение:

# Проверяем обновления
pkg update
apt-get update
pkg upgrade

Также рекомендую все манипуляции проделывать через SSH, либо подключить аппаратную клавиатуру. Для включения SSH нужно выполнить следующие команды (можно почитать в официальной документации):

pkg install openssh
passwd # Необходимо установить пароль, так как пароль по умолчанию неизвестен

Теперь можно запустить SSH командой sshd, при подключении используем порт 8022.

# Установим все необходимы для работы библиотеки
pkg install python nano make rust libcrypt libffi libjpeg-turbo # Обязательные
pkg install mosquitto termux-api # Рекомендую

Далее очень рекомендую все манипуляции проделывать в виртуальном окружении Python, чтобы библиотеки и всё прочее от HA установилось корректно. Для этого:

# Создаём виртуальное окружение
python -m venv hass
# Активируем виртуальное окружение
source hass/bin/activate

# Если среда более не нужна - можно её деактивировать с помощью:
# deactivate

Активируем среду и запускаем установку HA:

pip install --upgrade pip # Обновляем менеджер пакетов
pip install wheel # Обязательная библиотека

# Некоторые константы перед установкой
export CARGO_BUILD_TARGET="$(rustc -Vv | grep "host" | awk '{print $2}')"
export CRYPTOGRAPHY_DONT_BUILD_RUST=1

pip install homeassistant # Устанавливаем HA

И было бы всё хорошо, но далее нас могут встретить различные ошибки при установке, которые абсолютно индивидуальны и зависят от устройства.
У меня появилась проблема с orjson==3.7.5 из-за ошибки установки maturin==0.12.20, а также с установкой numpy. Последняя устанавливается в Termux специфичный образом, который описан у них в вики, а решить проблему с corjson помогло это обсуждение.

pkg install binutils # Доустанавливаем пакет
# Пытаемся поставить проблемные библиотеки
pip install  maturin==0.12.20
MATHLIB=m pip install numpy

После успешной установки пакета homeassistant (которая заняла несколько часов) мы преодолели только половину пути. Теперь надо запустить HA и снова исправлять различные появляющиеся ошибки. Для этого используем запуск с подробными логами: hass -v. Ошибки опять индивидуальны, и, к счастью, у меня они не возникли.

После того, как всё исправлено и Home Assistant запустился, мы можем войти в него и завести аккаунт. На этом этапе я столкнулся с ошибкой, связанной с часовым поясом, из-за которой регистрация всегда обрывалась. В качестве решения необходимо было установить пакетpip install tzdata.

Итоговый скрипт по установке можно посмотреть здесь.

Мне стало интересно, почему так мало статей на эту тему, хотя, казалось бы, очевидное решение — взять старый смартфон или планшет и реализовать на нём функции управления умным домом. Бонусом получаем всевозможные наборы датчиков с устройства, а также стационарную панель управления.

Итак, спустя несколько вечеров и попыток запуска я смог подключиться к HA в локальной сети! Радости не было предела!

Настраиваем Home Assistant

По настройке НА настолько много статей, что я просто приведу перечень того, что было сделано:

  • Установил HACS для возможности установки пользовательских интеграций.

  • Добавил системный монитор (systemmonitor) для отслеживания параметров системы (особенно памяти).

  • Изучил установку устройств Tuya в локальный контур. Установил LocalTuya и настроил розетку.

  • Скачал на смартфон приложение HA и добавил его интеграцию в систему. Не забыл внутри приложения настроить, какую информацию необходимо передавать в систему (информация о будильниках выключена по умолчанию).

  • Настроил автоматизацию.

Ура! Наша задача выполнена, теперь есть розетка с синхронизацей по будильнику, и всё это в локальном контуре. Но… где датчики планшета? Этот вопрос поставил в тупик. Хочется узнавать заряд батареи, информацию о WiFi-соединении (особенно учитывая стабильность ОС). Я нашёл два решения:

  1. Самое логичное — установить приложение на планшет и подключить его к самому себе, разрешив доступ ко всем необходимым датчикам, а также подключиться по WebSocket, что позволит мгновенно получать обновления.

  2. У Termux есть прекрасное расширение Termux: API, которое предоставляет доступ к дополнительным возможностям устройства. О них вам лучше всего расскажет документация.

Конечно, хотя первый способ и был самым удобным, но он реализовывал не все функции, которые есть в Termux: API, да и по опыту использования обнаружилась нестабильность работы из-за прошивки устройства (вот здесь она и подвела). Поэтому решил использовать оба способа вместе.

Подключаем Termux: API к Home Assistant. Простое решение

Для начала составим план, что мы хотим добавить:

  • Получение информации о батарее устройства с помощью команды termux-battery-status.

  • Получение информации о WiFi-соединении устройства с помощью команды termux-wifi-connectioninfo.

Для начала я подумал, что раз есть пошаговые инструкции о том, как подружить Termux и HA, то наверняка есть и инструкции по работе с Termux: API и HA. Поиск не дал каких-то конкретных результатов, после чего я наивно пошёл посмотреть интеграции в HACS, где тоже ничего не нашёл.

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

Для начала возьмём ответ команды termux-battery-status:

{
"health": "GOOD",
"percentage": 76,
"plugged": "PLUGGED_AC",
"status": "CHARGING",
"temperature": 32.900001525878906,
"current": -9223372036854775808
}

При реализации компонентов возникают следующие проблемы:

  1. На входе получаем JSON, но в документации компонента нет ни слова, как его распарсить.

  2. Мы получаем с нескольких датчиков информацию о батарее, которую нужно записать на разные платформы. Было бы очень расточительно вызывать эту функцию несколько раз, и поэтому нужна какая-то единая сущность для обновления.

  3. Исходя из документации, необходимо перечислять все датчики в файле configuration.yaml, и при этом сортировать их по платформам, что неудобно, так как потом теряешься между зависимыми компонентами.

О решении проблем по порядку:

  1. Оказывается, есть переменная json_attributes, в которой можно перечислить все имена наших JSON-полей. Данные будут храниться в атрибутах сенсора, который одновременно решит и вторую проблему с множественными вызовами. Но теперь появляется новая: как забрать значение атрибута?

  2. Чтобы забрать значение атрибута, при указании значения нужно вызывать функцию state_attr('sensor name', 'attr name'), в которой необходимо указать датчик, из которого мы пытаемся взять атрибут, а также имя атрибута.

  3. Последнюю проблему можно решить, добавив в файл конфигурации параметр, который указывает папку, где хранятся все ваши дополнительные конфигурации (я назвал её как и компонент — packages):

homeassistant:
packages: !include_dir_merge_named packages/

После этого вы можете создавать внутри объявленной папки YAML-файлы с вашими датчиками, но не забывайте в первой строке объявить название:

# Файл packages/battery.yaml
battery:
  binary_sensor:
    # ...
  sensor:
    # ...

С получением информации о WiFi всё аналогично. Итоговые файлы всех реализаций вы можете посмотреть в Github (включая файл конфигурации, если с ним возникли трудности).

После реализации базовых компонентов я добавил взаимодействие с Text-To-Speech для озвучивания некоторых событий. В HA есть встроенный TTS от Google, с которым первым делом поэкспериментировал и сделал выводы:

  1. Для работы требуется доступ в Интернет, да ещё и очень стабильный.

  2. Кеширует все записи в папке TTS, но не может их переиспользовать (а мы помним про память).

  3. Низкое качество озвучивания.

В то же время, команды Termux: API предоставляли доступ к системным TTS, которые можно установить или использовать существующие. Для этого необходимо было добавить действие с помощью компонента shell_command, а также поля ввода текста, который нужно произнести.

Начнём с системного. Для просмотра всех предустановленных TTS я использовал команду termux-tts-engines. В текущей ОС был предустановлен единственный движок: PicoTTS. При попытке воспроизвести любой текст Termux: API зависал и не реагировал в дальнейшем ни на одну команду, после чего был сразу отключён на уровне системы. И появилась необходимость установить любой другой, который мог бы работать без сетевого соединения. Поискав и посмотрев примеры озвучивания, я установил RHVoice, у которого небольшой размер и приемлемое качество произношения коротких фраз. Далее осталось всего лишь настроить компонент и автоматизации. Готово!

Но спустя пару дней опытным путем обнаружился недостаток: событие может произойти поздней ночью и разбудить всех. И если автоматизацию можно настроить на определённое время, то вот события ОС — нельзя;, а поскольку громкость всегда максимальна, с её помощью проблему не решить. Так возникла задача регулировки громкости устройства с помощью HA, для чего у нас есть команда termux-volume. И именно здесь у нас заканчиваются возможности работы со стандартным взаимодействием, поскольку HA не поддерживает работу с массивом, с помощью которого можно получить актуальную громкость устройства. Точнее, поддерживает только для установления значения, но не записи в атрибуты, чтобы можно было воспользоваться хаком, применённым для получения информации о состоянии батареи.

Настало время разобраться, как писать свои плагины, в частности для Termux: API.

Подключаем Termux: API к Home Assistant. Пишем интеграцию

И вот здесь начинается самая интересная часть — взгляд мобильного разработчика на Python-разработку интеграции для HA. Статей по разработке своих интеграций множество, и в том числе на Хабре. Если вы не знаете, как устроена стандартная разработка, то предлагаю прочитать предложенную ссылку, поскольку ничего нового я добавить не смогу.

Стандартная архитектура, предлагаемая HA.Стандартная архитектура, предлагаемая HA.

Разберём каждый элемент отдельно:

  • API: обычно один огромный файл, в котором происходит взаимодействие с «внешним миром».

  • Coordinator: компонент для того, чтобы с помощью одного API-запроса получить данные для нескольких компонентов. То есть некое хранилище, которое также управляет обновлением набора привязанных к нему датчиков, не вызывая лишний раз запрос на обновление. Этому элементу посвящена всего лишь одна глава раздела документации, и я подозреваю, что именно поэтому новички не пользуются этой функциональностью, хотя добавить её совсем не трудно.

  • Platform: это заранее известный файл интеграции, в котором HA вызывает основные методы инициализации компонентов. Файлы должны быть точно такого же названия, как в перечислении из исходного кода.

Что не так в стандартной архитектуре решения?

  • Вся ответственность за выполнение команд и обработку ошибок ложиться на слой API. По сути, API становится God-object, который нужен всем для нормальной работы.

  • Опять мы видим разделение по платформам, а не по их логическим сущностям (например, в sensors у меня может быть информации и о сети, и о батарее).

  • Необходимо в API и Coordinator дублировать данные со всеми вытекающими.

Как выглядит пример связи элементов в интеграции.Как выглядит пример связи элементов в интеграции.

И все эти проблемы можно решить, добавив немного архитектуры из разработки Android-приложений:

  1. Разделим ответственность не по платформам системы, а по сущностям (entities). Каждая сущность будет представлять любой компонент системы HA. Внутри себя сущность не хранит никаких дополнительных данных.

  2. Все данные хранятся в Coordinator’е, который может общаться уже с API. Именно он обеспечивает единое состояние данных для каждого датчика.

  3. API всё также общается с внешним источником и автоматически преобразует данные в нужные объекты. Также API обрабатывает некорректные запросы, например, таймаут или ошибки.

Также стоит прояснить некоторые особенности работы с HA:

  1. Поскольку платформ у одной сущности может быть нескольких типов, то каждую такую группу необходимо инициализировать с помощью заранее известной функции, например, async_setup__entitites. Тем самым реализация инициализации будет лежать в том месте, где идёт работа с этими датчиками.

  2. Для корректной работы при инициализации интеграции необходимо сохранить как объект API, так и все Coordinator’ы, таким образом они будут представлены в виде единой реализации.

Итоговая архитектура.Итоговая архитектура.Файловая структура интеграции.Файловая структура интеграции.

Как можно заметить, изменилось совсем немного, просто немного упорядочили и привели в порядок связи. Но такие небольшие (и вроде бы очевидные) изменения очень сильно помогли в дальнейшем не путаться в связях между слоями и легче отлаживать, уменьшили количество ошибок при разработке.

Итоговый код можно посмотреть здесь и интегрировать его к себе.

Результат

Наша простая задачка превратилась в интереснейший путь изучения HA для работы на Android-устройстве:

  1. Установили HA в Termux.

  2. Написали YAML-конфигурацию для подключения базовых сведений об Android-устройстве и изучили работу с TTS.

  3. Написали интеграцию, которая позволяет сделать всё, что описано в YAML, но:

    1. Динамически менять иконки для наглядности.

    2. Сделать рабочей кнопку обновления сенсоров (в любой момент получить актуальные данные).

    3. Добавить возможность получения фотографий с камеры устройства и всего того, что недоступно с помощью YAML.

Итоговый экран при работе с планшетом.Итоговый экран при работе с планшетом.

Что дальше?

Пока реализована лишь основа, которую отлично можно и нужно развивать, а именно:

  1. Перенести все остальные возможности Termux в HA.

  2. Добавить возможность подключать Zigbee-стик через OTG-кабель, чтобы добиться независимости датчиков от электричества (поскольку не будет привязки к энергозависимому хабу). Для этого требуется подменить стандартные команды к USB через termux-usb.

  3. Добавить возможность подключения удалённых устройств к Termux.

Это не говоря о таких мелочах, как публикация в HACS.

© Habrahabr.ru