Привет, Habr! Продолжаем развивать интерфейс дисплея Guition на ESPHome с использованием LVGL. Изначально планировалось просто добавить пару виджетов, но в процессе работы появилась идея кардинально изменить структуру проекта: сделать виджеты подключаемыми, вынести сущности в переменные для шаблонизации и максимально упростить использование прошивки для конечного пользователя.
Реализованный функционал
Основные возможности:
Главный экран: время, дата, погодные условия и температура
Системная информация: блокировка экрана, отображение 3 сенсоров (можно добавить больше)
Виджет освещения: управление 4 сущностями света с дополнительными настройками при длительном нажатии (3 режима, управление яркостью)
Медиаплеер: полноценное управление воспроизведением
Пылесос: управление роботом-пылесосом
Термостат: управление отоплением (используется реле устройства)
Кондиционер/вентиляция: климат-контроль (используется реле устройства)
Рольставни: управление (легко адаптируется для ворот или штор)

Настройки:
Мультиязычность: автоматические переводы из Home Assistant для состояний погоды, пылесоса, термостата, кондиционера/вентиляции, рольставней
Подсветка экрана: настройка яркости
Энергосбережение: таймер отключения экрана
Необходимые компоненты
Для работы прошивки требуется установка кастомного компонента, который обеспечивает:
Получение переводов
Отображение обложек для медиаплеера
Есть также кастомный компонент для получения фронтенд-переводов при разработке собственных интерфейсов для Home Assistant (например, на Vue), если кому интересно.
Основные ограничения и проблемы
Аппаратные ограничения
Главная проблема заключается в том, что возможности железа этого устройства крайне ограничены. Текущие микроконтроллеры (ESP32-P4 уже значительно лучше) не очень подходят для тяжелых графических задач. Несмотря на все первоначальные амбиции, приходится сталкиваться с ограничениями как по железу, так и по самому ESPHome, который изначально не задумывался для подобных задач, хотя в последнее время активно расширяет свой функционал.
Проблема динамических сущностей
Изначально хотелось сделать сущности выбираемыми из экранного меню, чтобы пользователю не приходилось править код. Удалось даже реализовать список с получением сущностей из ESPHome и вызов служб (например, включение/выключение света).
Однако проблема поджидала в сенсорах: ESPHome не умеет динамически подписываться на сущности и вообще не может отписываться от них, поскольку такой функционал не предполагался концепцией. Можно написать кастомный компонент, но, как сказал разработчик ESPHome, это потребует изменений в ядре ESPHome и ядре Home Assistant. В итоге от этой идеи пришлось отказаться.
Ограничения памяти
Следующая проблема — память. Несмотря на наличие почти 8 МБ PSRAM помимо SRAM, всё равно приходится ограничивать и оптимизировать ресурсы.
Пример: пришлось убрать красивые картинки рольставней и заменить их на глифы, поскольку одна картинка занимает около 200 КБ памяти (300×300×2 + накладные расходы на прозрачность). При необходимости использовать 11 таких картинок общий объем превысил бы 2 МБ из доступных 8. Сильно уменьшить разрешение нельзя, так как картинки используются в виде слайдера.
Синхронность vs асинхронность
ESP32 в ESPHome работает в синхронном потоке ("main loop"). Если что-то не позволяет обработать цикл за 5 секунд, ESP32 считает устройство "зависшим", срабатывает watchdog, происходит перезагрузка и так по кругу.
Проблемная ситуация: множество сенсоров (sensor, text_sensor для различных атрибутов) при загрузке начинают получать данные по API от Home Assistant. В большинство сенсоров добавляются действия при получении данных — это могут быть сложные скрипты (парсинг, вычисления). Да, сами скрипты работают асинхронно, но в этом тоже есть свои плюсы и минусы. Большое количество асинхронно выполняющихся скриптов может вызывать переполнение памяти, а при синхронной обработке нам просто не хватит времени до срабатывания watchdog.
Проблема "задвоенности" скриптов
Еще одна проблема — дублирование выполнения скриптов при восстановлении процессов после отключения питания:
on_boot
(при загрузке ESP32)on_client_connected
(при подключении к API)
Особенность: при перезагрузке устройства срабатывают оба события, но при прошивке — только on_boot
(API при перепрошивке не теряется!). И если в скриптах прописывается изменение состояния, то наличие скрипта и в on_boot
и в on_client_connected
приведет к совершенно другому результату, чем ожидалось.
Оптимальное решение — использовать только on_client_connected
для готовой прошивки, но на этапе тестирования приходится использовать on_boot
или каждый раз перезагружать устройство после прошивки.
Планы на будущее
В ближайшее время планируется работа с новым устройством, которое уже получено, но инструментарий для ESPHome пока не готов. Характеристики самого устройства отличные:
ESP32-P4 — мощный микроконтроллер
32 МБ PSRAM
RGB888 (наконец-то нормальные градиенты и тени!)
Микрофон и динамик
Ethernet
Хотелось бы видеть PoE или питание 220В вместо RS485 и DC, но пока довольствуемся тем, что есть.
Заключение
⚠️ Важно: Прошивка находится в стадии беты. Присутствуют некоторые баги, а отдельные виджеты тестировались на демо-сущностях из-за отсутствия реальных устройств.
Буду рад получить обратную связь от сообщества! Если проект окажется полезным, буду благодарен за звездочку на GitHub.
Ссылка на проект