Да будет свет... умным? Наделяем настольную лампу свободной волей

Проект вырос просто из желания получить наконец удобную настольную лампу. Приятную в использовании, с широкими возможностями кастомизации освещения и интеграцией в умный дом. Еще хотелось быстро и без заморочи. Интересно, что получилось в итоге? Заглядывайте под кат.
В распоряжении у меня имелась неплохая китайская лампа бренда Uniel на 5V/1.5A или 8W.

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


Также подкупала полезная функция отображения времени, даты и температуры в комнате. Были и другие функции, вроде настраиваемого будильника и режима подсветки дисплея, но первое не очень-то нужно владельцу смартфона, а второе — выставил один раз и забыл (да в общем не сильно-то и надо выставлять).

В свое время (2020) лампа казалось достаточно продвинутой и удобной. В процессе эксплуатации, правда, вылезло пару недостатков. Например, крайне неудобное взаимодействие с настройками времени через панель на днище светильника (еще один укол в сторону использования как будильник). А как я задолбался включать свет тремя нажатиями по сенсору, словами не передать… Случайно включаешь лампу не полностью (один-два тыка из трех), потом тыкаешь выключить — она только разгорается ярче. Или думаешь, что включил не полностью, тапаешь быстро два-три раза — она заново включена. Протыкай еще n раз. Тот, кто придумал управление в духе дешевого фонарика на сенсоре прикосновений, должен гореть в аду!

Теперь, когда у меня появился локальный сервер умного дома, я говорю: «Довольно!». Да и давно хотел глянуть, что же у нее внутри. А если вам тоже стало интересно, присаживайтесь поудобнее и заваривайте чай — прогулка обещает быть интересной.
Итак, разбираем лампу. Для этого нужно окрутить 4 винта на днище, закрытых приклеенной антискользящей лентой.

Под ними находится плата с кнопками под 4 шурупами. Отвинтив и их, нам откроются два невидимых винта крепления задней крышки, которые надо что? Правильно.
Так же следует поступаем с двумя видимыми с задней стороны корпуса.
После этого лампа… не разберется. Да, аккуратно отщелкиваем защелки по бокам корпуса, а вы что подумали?

Внутри мы видим массивный утяжелитель, достаточно крупную основную плату, субплату с кнопками, разъем питания, дисплей. Ну и всякие проводки, конечно, видим.
Внимательно посмотрим на основную плату. Среди множества непропаянных с завода элементов можно заметить огромную черную кляксу компаунда с кучей выводов, которая очевидно отвечает за дисплей. К ней также ведут выводы термистора. Ее я в этом выпуске трогать почти не буду. Почти. Пробегаем глазами ниже и видим единственную восьминогую микросхемку с затертой маркировкой. Это контроллер светодиодов. Он отвечает за сенсоры спереди и сзади лампы и управляет теплой и холодной светодиодными лентами, а еще подсветкой дисплея. Это можно проследить по дорожкам к управляющим мосфетам и сенсорным падам, прозвонив их мультиметром. Тебя-то мне и нужно!
Теперь наконец-то можно обозначить конкретный ход проекта:

Поразмыслив над схемой, я решил также вывести управление дисплейной частью (4 кнопки на днище) в умный дом. Хотя обратной связи нет, это удобнее, чем переворачивать лампу и настраивать руками. Я думал вывести температуру с градусника в лампе в умный дом, но термистор оказался привязан к дисплею, так что в итоге я решил взять модуль AM2320 датчика температуры и влажности, и закинуть в умный дом его показания. Для сенсорых падов, которые нативно не поддерживаются выводами ESP-12, я использовал сенсорные модули TTP223, по 7 рублей штука. Cхема подключения к ESP получилась такая:

Это без учета стандартной обвязки ESP. Ее спаял навесом.

Схема обвязки

Питание взял на всякий случай со стабилизатора, на плате оно не выглядело мощным. На AM2320 я решил сэкономить пин и подключить его по интерфейсу OneWire, а не I2C. Для этого в даташите нарыл схему соединения выводов. Там было написано использовать сопротивление 5.1 кОм.

5.1 у меня не было, поставил 5.4. Да и пофиг! Оно заработало. В реальности вышло как-то так.

Все сделал навесом, а макетку с питающим стабилизатором я повесил на какой-то пустующий штырек под шуруп в корпусе. Удобно, спасибо китайцам! Пришло время поговорить о прошивке.


Теперь можно залить прошивку любым удобным способом, скомпилировав и скачав. Я просто использую ESPHome hub.

Для загрузки понадобится также цепь с UART-программатором.

Теперь, когда связь с контроллером установлена через API, прошивка заливается прямо по воздуху.
Все предварительные ласки мы завершили. Теперь ну… Собственно, самый сок.
Итак, по схеме мы управляем тремя источниками света (дисплей, теплая и холодная лента). Для этого устанавливаем соответствующие пины МК как output и привязываем к ним объекты lamp.

Далее ребуты уже не помогали. В общем, как-то странно работает режим авто-определения сенсора. Но после наобум выставленного DHT22 проблем не было.


А надо пресеты, как было изначально. Только лучше! Теперь-то я могу сделать настраиваемые пресеты, да и кастомные эффекты тоже.

Логика работы пресетов такая — пресет выбирается либо из умного дома, либо руками (зажатием кнопки включения). Если надо изменить пресет, необходимо из умного дома выбрать нужную яркость и нажать кнопку «сохранить». Всего я сделал 3 пресета, чтобы долго не выбирать их руками (да и этого достаточно).

Также я реализовал кастомный эффект огня, скомбинировав flicker и скрипт случайной яркости. Эффект огня я повесил на двойной клик кнопки переключения подсветки дисплея. На видео не так красиво выглядит, как на глаз.

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

Кроме того, выведем графики влажности и температуры.

Скрипт для мигания достаточно простой.

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

Что касается автовключения, у меня есть еще кое-какое умное устройство с микроволновым датчиком присутствия ld2420 (о нем, пожалуй расскажу в другой статье). В датчике есть параметр расстояния. Методом тыка я нашел комфортную дистанцию, на которой лампа срабатывает уверенно при нахождении за столом. Также из своих умных жалюзи (статья) я использовал параметр освещенности. Логика простая — если за столом кто-то есть и в комнате достаточно темно или включено верхнее освещение, лампа активируется.
Как это работает, можете увидеть на гифке.

Ну что же, кажется план был выполнен и даже немного перевыполнен. Проект получился достаточно простой в исполнении, но гибкий за счет использования EspHome. И в отличие от всяких покупных ламп он совсем не зависит от сторонних серверов и приложений. Бонусом ко всему идет нативное голосовое управление через моего локального голосового ассистента.

Но его настройка как-то идет мимо форматов статей на mysku. Так что просто скажу, что создать своего локального ассистента в HomeAssistant не так уж и сложно, а гибкая архитектура позволяет даже интегрировать голосовые модели…
Что касается затрат на проект, по деньгам вышло чуть меньше 200 рублей. По времени всего пару вечеров на выходных. А результат налицо! Ну а я с вами не прощаюсь. Увидимся в следующем выпуске!
В распоряжении у меня имелась неплохая китайская лампа бренда Uniel на 5V/1.5A или 8W.

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


Также подкупала полезная функция отображения времени, даты и температуры в комнате. Были и другие функции, вроде настраиваемого будильника и режима подсветки дисплея, но первое не очень-то нужно владельцу смартфона, а второе — выставил один раз и забыл (да в общем не сильно-то и надо выставлять).

В свое время (2020) лампа казалось достаточно продвинутой и удобной. В процессе эксплуатации, правда, вылезло пару недостатков. Например, крайне неудобное взаимодействие с настройками времени через панель на днище светильника (еще один укол в сторону использования как будильник). А как я задолбался включать свет тремя нажатиями по сенсору, словами не передать… Случайно включаешь лампу не полностью (один-два тыка из трех), потом тыкаешь выключить — она только разгорается ярче. Или думаешь, что включил не полностью, тапаешь быстро два-три раза — она заново включена. Протыкай еще n раз. Тот, кто придумал управление в духе дешевого фонарика на сенсоре прикосновений, должен гореть в аду!

Теперь, когда у меня появился локальный сервер умного дома, я говорю: «Довольно!». Да и давно хотел глянуть, что же у нее внутри. А если вам тоже стало интересно, присаживайтесь поудобнее и заваривайте чай — прогулка обещает быть интересной.
Аппаратная часть
Итак, разбираем лампу. Для этого нужно окрутить 4 винта на днище, закрытых приклеенной антискользящей лентой.

Под ними находится плата с кнопками под 4 шурупами. Отвинтив и их, нам откроются два невидимых винта крепления задней крышки, которые надо что? Правильно.
Так же следует поступаем с двумя видимыми с задней стороны корпуса.
После этого лампа… не разберется. Да, аккуратно отщелкиваем защелки по бокам корпуса, а вы что подумали?

Внутри мы видим массивный утяжелитель, достаточно крупную основную плату, субплату с кнопками, разъем питания, дисплей. Ну и всякие проводки, конечно, видим.
Внимательно посмотрим на основную плату. Среди множества непропаянных с завода элементов можно заметить огромную черную кляксу компаунда с кучей выводов, которая очевидно отвечает за дисплей. К ней также ведут выводы термистора. Ее я в этом выпуске трогать почти не буду. Почти. Пробегаем глазами ниже и видим единственную восьминогую микросхемку с затертой маркировкой. Это контроллер светодиодов. Он отвечает за сенсоры спереди и сзади лампы и управляет теплой и холодной светодиодными лентами, а еще подсветкой дисплея. Это можно проследить по дорожкам к управляющим мосфетам и сенсорным падам, прозвонив их мультиметром. Тебя-то мне и нужно!
Теперь наконец-то можно обозначить конкретный ход проекта:
- Заменить чип управления светом на умный
- Написать прошивку для нового чипа
- Интегрировать устройство в умный дом

Поразмыслив над схемой, я решил также вывести управление дисплейной частью (4 кнопки на днище) в умный дом. Хотя обратной связи нет, это удобнее, чем переворачивать лампу и настраивать руками. Я думал вывести температуру с градусника в лампе в умный дом, но термистор оказался привязан к дисплею, так что в итоге я решил взять модуль AM2320 датчика температуры и влажности, и закинуть в умный дом его показания. Для сенсорых падов, которые нативно не поддерживаются выводами ESP-12, я использовал сенсорные модули TTP223, по 7 рублей штука. Cхема подключения к ESP получилась такая:

Это без учета стандартной обвязки ESP. Ее спаял навесом.

Схема обвязки

Питание взял на всякий случай со стабилизатора, на плате оно не выглядело мощным. На AM2320 я решил сэкономить пин и подключить его по интерфейсу OneWire, а не I2C. Для этого в даташите нарыл схему соединения выводов. Там было написано использовать сопротивление 5.1 кОм.

5.1 у меня не было, поставил 5.4. Да и пофиг! Оно заработало. В реальности вышло как-то так.

Все сделал навесом, а макетку с питающим стабилизатором я повесил на какой-то пустующий штырек под шуруп в корпусе. Удобно, спасибо китайцам! Пришло время поговорить о прошивке.
Программная часть
Я использую ESPHome в паре с HomeAssistant. Для того, чтобы прошить, необходимо добавить новый девайс из интерфейса EspHome Builder, выбрав нужные параметры устройства. В моем случае это ESP8266.

Теперь можно залить прошивку любым удобным способом, скомпилировав и скачав. Я просто использую ESPHome hub.

Для загрузки понадобится также цепь с UART-программатором.

Теперь, когда связь с контроллером установлена через API, прошивка заливается прямо по воздуху.
Все предварительные ласки мы завершили. Теперь ну… Собственно, самый сок.
Итак, по схеме мы управляем тремя источниками света (дисплей, теплая и холодная лента). Для этого устанавливаем соответствующие пины МК как output и привязываем к ним объекты lamp.
output:
- platform: esp8266_pwm # Для ESP8266, замените на "ledc" для ESP32
id: pwm_backlight
pin: GPIO3 # Укажите свой пин
inverted: true
frequency: 1000 Hz # Частота ШИМ
- platform: esp8266_pwm # Для ESP8266, замените на "ledc" для ESP32
id: pwm_warm_light
pin: GPIO4 # Укажите свой пин
frequency: 1000 Hz # Частота ШИМ
- platform: esp8266_pwm # Для ESP8266, замените на "ledc" для ESP32
id: pwm_cold_light
pin: GPIO5 # Укажите свой пин
frequency: 1000 Hz # Частота ШИМ
light:
- platform: monochromatic
name: "Яркость подсветки дисплея"
output: pwm_backlight
id: backlight
restore_mode: RESTORE_DEFAULT_ON # Запоминает последнее состояние
- platform: monochromatic
name: "Яркость теплого света"
output: pwm_warm_light
id: warm_light
restore_mode: RESTORE_DEFAULT_ON # Запоминает последнее состояние
default_transition_length: 1s
- platform: monochromatic
name: "Яркость холодного света"
output: pwm_cold_light
id: cold_light
restore_mode: RESTORE_DEFAULT_ON # Запоминает последнее состояние
default_transition_length: 1s
Чтобы также получить управление над кнопками на днище лампы в блок output следует добавить соответствующие пины конфигурации, а еще добавить блок кнопок, которые «дергают» эти выводы.#продолжение output
- platform: gpio
id: button_up
pin: GPIO13
inverted: True
- platform: gpio
id: button_down
pin: GPIO01
inverted: True
- platform: gpio
id: button_s
pin: GPIO00
inverted: True
- platform: gpio
id: button_m
pin: GPIO02
inverted: True
button:
- platform: output
name: "M"
output: button_up
duration: 300ms
- platform: output
name: "S"
output: button_down
duration: 300ms
- platform: output
name: "Up"
output: button_s
duration: 300ms
- platform: output
name: "Down"
output: button_m
duration: 300ms
Чтобы сделать управление с сенсорных кнопок добавим template switch, который будет отвечать сразу за теплый и холодный свет. Также необходимо реализовать кнопку, которая его сможет переключать. Ничего не забыли?.. А, точно! Еще добавим логику управления подсветкой дисплея через заднюю кнопку.switch:
- platform: template
name: "Лампа Вкл/Выкл"
id: lamp_power
lambda: |-
// Если хотя бы одна лента включена, переключатель считается "ON"
return (id(warm_light).current_values.is_on() || id(cold_light).current_values.is_on());
turn_on_action:
- switch.turn_off: fire_switch
- script.execute: apply_preset
turn_off_action:
- switch.turn_off: fire_switch
- light.turn_off: warm_light
- light.turn_off: cold_light
binary_sensor:
- platform: gpio
pin:
number: GPIO12 # Физическая кнопка на этом пине
mode: INPUT_PULLUP
inverted: true # Используется PULLUP, значит логика инвертирована
name: "Кнопка управления светом"
filters:
- delayed_on: 50ms # Фильтр для устранения дребезга
on_click:
- switch.toggle: lamp_power
- platform: gpio
pin:
number: GPIO14 # Физическая кнопка на этом пине
mode: INPUT_PULLUP
inverted: true # Используется PULLUP, значит логика инвертирована
name: "Кнопка управления подсветкой"
filters:
- delayed_on: 50ms # Фильтр для устранения дребезга
on_click:
- light.toggle: backlight
Ну и последнее, сенсор температуры и влажности. Изначально я даже не выставлял model, и все прекрасно показывало в автоматическом режиме, но после одного прекрасного ребута я увидел, что в комнате похолодало до -12. 
Далее ребуты уже не помогали. В общем, как-то странно работает режим авто-определения сенсора. Но после наобум выставленного DHT22 проблем не было.
- platform: dht
model: DHT22
pin: GPIO16 # Подключите DATA к этому пину
temperature:
name: "Температура"
id: temp_sensor
accuracy_decimals: 1
humidity:
name: "Влажность"
id: hum_sensor
accuracy_decimals: 1
update_interval: 60s # Обновление данных раз в 60 секунд
Так, теперь свет у нас включается плавно, есть управление прямо из HomeAssistant, есть регулировка яркости с точностью до процента, можно смотреть температуру и влажность. Что еще надо?

А надо пресеты, как было изначально. Только лучше! Теперь-то я могу сделать настраиваемые пресеты, да и кастомные эффекты тоже.

Логика работы пресетов такая — пресет выбирается либо из умного дома, либо руками (зажатием кнопки включения). Если надо изменить пресет, необходимо из умного дома выбрать нужную яркость и нажать кнопку «сохранить». Всего я сделал 3 пресета, чтобы долго не выбирать их руками (да и этого достаточно).

Также я реализовал кастомный эффект огня, скомбинировав flicker и скрипт случайной яркости. Эффект огня я повесил на двойной клик кнопки переключения подсветки дисплея. На видео не так красиво выглядит, как на глаз.

В общем и целом код получился довольно объемным (если yaml можно назвать кодом). С первого раза может быть не совсем понятно, что здесь и зачем, но разобраться довольно легко, если вы знакомы с программированием.
Полный код проекта
substitutions:
name: smart-desk-lamp
friendly_name: Smart Desk Lamp
esphome:
name: ${name}
friendly_name: ${friendly_name}
esp8266:
board: esp01_1m
# Enable logging
logger:
# Enable Home Assistant API
api:
encryption:
key: !your_key
ota:
- platform: esphome
password: !your_pass
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "Smart-Desk-Lamp Fallback Hotspot"
password: !your_pass_hotspot
captive_portal:
globals:
- id: warm_current_brightness
type: float
restore_value: no
initial_value: "0.2" # стартовое значение для теплой ленты (20%)
- id: warm_target_brightness
type: float
restore_value: no
initial_value: "0.2"
- id: cold_current_brightness
type: float
restore_value: no
initial_value: "0.15" # стартовое значение для холодной ленты (15%)
- id: cold_target_brightness
type: float
restore_value: no
initial_value: "0.15"
- id: preset1_warm
type: float
restore_value: no
initial_value: "0.5" # Пресет 1: 50% тёплая
- id: preset1_cold
type: float
restore_value: no
initial_value: "0.5" # Пресет 1: 50% холодная
- id: preset2_warm
type: float
restore_value: no
initial_value: "0.8" # Пресет 2: 80% тёплая
- id: preset2_cold
type: float
restore_value: no
initial_value: "0.3" # Пресет 2: 30% холодная
- id: preset3_warm
type: float
restore_value: no
initial_value: "0.3" # Пресет 3: 30% тёплая
- id: preset3_cold
type: float
restore_value: no
initial_value: "0.8" # Пресет 3: 80% холодная
- id: current_preset
type: int
restore_value: no
initial_value: "1" # Текущий пресет (1, 2 или 3)
- id: is_effect_on
type: bool
restore_value: yes
initial_value: "false" # Световой эффект (вкл/выкл)
output:
- platform: esp8266_pwm # Для ESP8266, замените на "ledc" для ESP32
id: pwm_backlight
pin: GPIO3 # Укажите свой пин
inverted: true
frequency: 1000 Hz # Частота ШИМ
- platform: esp8266_pwm # Для ESP8266, замените на "ledc" для ESP32
id: pwm_warm_light
pin: GPIO4 # Укажите свой пин
frequency: 1000 Hz # Частота ШИМ
- platform: esp8266_pwm # Для ESP8266, замените на "ledc" для ESP32
id: pwm_cold_light
pin: GPIO5 # Укажите свой пин
frequency: 1000 Hz # Частота ШИМ
- platform: gpio
id: button_up
pin: GPIO13
inverted: True
- platform: gpio
id: button_down
pin: GPIO01
inverted: True
- platform: gpio
id: button_s
pin: GPIO00
inverted: True
- platform: gpio
id: button_m
pin: GPIO02
inverted: True
sensor:
- platform: uptime
name: ${name}_uptime
id: uptime_sec
internal: true
- platform: wifi_signal
name: ${name}_WiFi_Signal"
update_interval: 60s
- platform: dht
model: DHT22
pin: GPIO16 # Подключите DATA к этому пину
temperature:
name: "Температура"
id: temp_sensor
accuracy_decimals: 1
humidity:
name: "Влажность"
id: hum_sensor
accuracy_decimals: 1
update_interval: 60s # Обновление данных раз в 60 секунд
light:
- platform: monochromatic
name: "Яркость подсветки дисплея"
output: pwm_backlight
id: backlight
restore_mode: RESTORE_DEFAULT_ON # Запоминает последнее состояние
- platform: monochromatic
name: "Яркость теплого света"
output: pwm_warm_light
id: warm_light
restore_mode: RESTORE_DEFAULT_ON # Запоминает последнее состояние
default_transition_length: 1s
effects:
- flicker:
name: Flicker Effect
- platform: monochromatic
name: "Яркость холодного света"
output: pwm_cold_light
id: cold_light
restore_mode: RESTORE_DEFAULT_ON # Запоминает последнее состояние
default_transition_length: 1s
switch:
- platform: template
name: "Лампа Вкл/Выкл"
id: lamp_power
lambda: |-
// Если хотя бы одна лента включена, переключатель считается "ON"
return (id(warm_light).current_values.is_on() || id(cold_light).current_values.is_on());
turn_on_action:
- switch.turn_off: fire_switch
- script.execute: apply_preset
turn_off_action:
- switch.turn_off: fire_switch
- light.turn_off: warm_light
- light.turn_off: cold_light
- platform: template
name: "Эффект огня"
id: fire_switch
restore_mode: ALWAYS_OFF
turn_on_action:
- lambda: |-
id(is_effect_on) = true;
- light.turn_on:
id: warm_light
effect: "Flicker Effect"
- script.execute: fire_effect
turn_off_action:
- lambda: |-
id(is_effect_on) = false;
- script.stop: fire_effect
- light.turn_on:
id: warm_light
effect: none
- script.execute: apply_preset
optimistic: true
button:
- platform: output
name: "M"
output: button_up
duration: 300ms
- platform: output
name: "S"
output: button_down
duration: 300ms
- platform: output
name: "Up"
output: button_s
duration: 300ms
- platform: output
name: "Down"
output: button_m
duration: 300ms
- platform: template
name: "Сохранить пресет яркости"
on_press:
then:
- lambda: |-
if (id(current_preset) == 1) {
id(preset1_warm) = id(warm_light).current_values.get_brightness();
id(preset1_cold) = id(cold_light).current_values.get_brightness();
} else if (id(current_preset) == 2) {
id(preset2_warm) = id(warm_light).current_values.get_brightness();
id(preset2_cold) = id(cold_light).current_values.get_brightness();
} else if (id(current_preset) == 3) {
id(preset3_warm) = id(warm_light).current_values.get_brightness();
id(preset3_cold) = id(cold_light).current_values.get_brightness();
}
select:
- platform: template
name: "Пресет лампы"
id: lamp_preset
options:
- "Preset 1"
- "Preset 2"
- "Preset 3"
optimistic: true
set_action:
- lambda: |-
if (x == "Preset 1") {
id(current_preset) = 1;
} else if (x == "Preset 2") {
id(current_preset) = 2;
} else if (x == "Preset 3") {
id(current_preset) = 3;
}
id(apply_preset).execute();
update_interval: 1s
binary_sensor:
- platform: gpio
pin:
number: GPIO12 # Физическая кнопка на этом пине
mode: INPUT_PULLUP
inverted: true # Используется PULLUP, значит логика инвертирована
name: "Кнопка управления светом"
filters:
- delayed_on: 50ms # Фильтр для устранения дребезга
on_click:
- switch.toggle: lamp_power
on_multi_click:
- timing:
- on for at least 1s
then:
- select.next: lamp_preset
- platform: gpio
pin:
number: GPIO14 # Физическая кнопка на этом пине
mode: INPUT_PULLUP
inverted: true # Используется PULLUP, значит логика инвертирована
name: "Кнопка управления подсветкой"
filters:
- delayed_on: 50ms # Фильтр для устранения дребезга
on_click:
- light.toggle: backlight
on_double_click:
then:
- switch.toggle: fire_switch
text_sensor:
- platform: template
name: ${friendly_name}_uptime
lambda: |-
int seconds = (id(uptime_sec).state);
int days = seconds / (24 * 3600);
seconds = seconds % (24 * 3600);
int hours = seconds / 3600;
seconds = seconds % 3600;
int minutes = seconds / 60;
seconds = seconds % 60;
return { (String(days) +" д. " + String(hours) +" ч. " + String(minutes) +" мин.").c_str() };
icon: mdi:clock
update_interval: 113s
script:
- id: fire_effect
mode: restart
then:
- repeat:
count: 10000 # Бесконечный цикл (либо можно указать большое число)
then:
- light.turn_on:
id: warm_light
brightness: !lambda 'return 0.2 + ((float) random(50) / 100.0);' # 20-70%
transition_length: 1s
- light.turn_on:
id: cold_light
brightness: !lambda 'return ((float) random(30) / 100.0);' # 0-30%
transition_length: 1s
- delay: !lambda 'return (float)(50 + random(200));' # Задержка от 50 до 250 мс
- id: apply_preset
then:
- if:
condition:
lambda: 'return id(current_preset) == 1;'
then:
- light.turn_on:
id: warm_light
brightness: !lambda 'return id(preset1_warm);'
- light.turn_on:
id: cold_light
brightness: !lambda 'return id(preset1_cold);'
- if:
condition:
lambda: 'return id(current_preset) == 2;'
then:
- light.turn_on:
id: warm_light
brightness: !lambda 'return id(preset2_warm);'
- light.turn_on:
id: cold_light
brightness: !lambda 'return id(preset2_cold);'
- if:
condition:
lambda: 'return id(current_preset) == 3;'
then:
- light.turn_on:
id: warm_light
brightness: !lambda 'return id(preset3_warm);'
- light.turn_on:
id: cold_light
brightness: !lambda 'return id(preset3_cold);'
Собственно, в то время как лампа стала максимально удобной в использовании, пора творить настоящую магию. Сделаем, чтобы лампа включалась сама, когда садишься за стол вечером. А еще добавим уведомления о всяких событиях через ее мигание. Настало время…
Интеграции с умным домом
Во-первых, выведем управление яркостью и пресетами на главную страницу.
Кроме того, выведем графики влажности и температуры.

Скрипт для мигания достаточно простой.

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

Что касается автовключения, у меня есть еще кое-какое умное устройство с микроволновым датчиком присутствия ld2420 (о нем, пожалуй расскажу в другой статье). В датчике есть параметр расстояния. Методом тыка я нашел комфортную дистанцию, на которой лампа срабатывает уверенно при нахождении за столом. Также из своих умных жалюзи (статья) я использовал параметр освещенности. Логика простая — если за столом кто-то есть и в комнате достаточно темно или включено верхнее освещение, лампа активируется.
alias: Включение света по присутствию
description: ""
triggers:
- trigger: numeric_state
entity_id:
- sensor.esphome_web_97f3af_moving_distance
below: 170
conditions:
- condition: or
conditions:
- type: is_value
condition: device
device_id: 6f308921f943e7d1ea97c9ce587d60d9
entity_id: ed17ecded4455a307b5dc24e0aeddb88
domain: sensor
below: 1100
- type: is_value
condition: device
device_id: 6f308921f943e7d1ea97c9ce587d60d9
entity_id: ed17ecded4455a307b5dc24e0aeddb88
domain: sensor
above: 2500
actions:
- type: turn_on
device_id: 1c3fdf6ccde0e04e0d3c9638a102eb53
entity_id: e3b0ea862766945de042cc6ccc838f88
domain: switch
mode: single
И выключается по присутствию.alias: Выключение света по присутствию
description: ""
triggers:
- trigger: numeric_state
entity_id:
- sensor.esphome_web_97f3af_moving_distance
above: 170
actions:
- type: turn_off
device_id: 1c3fdf6ccde0e04e0d3c9638a102eb53
entity_id: e3b0ea862766945de042cc6ccc838f88
domain: switch
mode: single
Как это работает, можете увидеть на гифке.

Ну что же, кажется план был выполнен и даже немного перевыполнен. Проект получился достаточно простой в исполнении, но гибкий за счет использования EspHome. И в отличие от всяких покупных ламп он совсем не зависит от сторонних серверов и приложений. Бонусом ко всему идет нативное голосовое управление через моего локального голосового ассистента.

Но его настройка как-то идет мимо форматов статей на mysku. Так что просто скажу, что создать своего локального ассистента в HomeAssistant не так уж и сложно, а гибкая архитектура позволяет даже интегрировать голосовые модели…
Что касается затрат на проект, по деньгам вышло чуть меньше 200 рублей. По времени всего пару вечеров на выходных. А результат налицо! Ну а я с вами не прощаюсь. Увидимся в следующем выпуске!
Самые обсуждаемые обзоры
+19 |
1225
44
|
+32 |
626
35
|
Зачем нужны все эти извращения с прошивками и ESP8266, если в лампу на производстве забыли свет положить?
Разным работам разная освещённость. И ещё у людей разное зрение.
Главное не забыть пройти ластиком по обратной стороне копии ;)
Лампу самому починить очень сложно здесь помощник нужен. Котика в ленту.
А самое главное — это один раз настроится и потом никто это трогать не будет больше никогда.
Ну и наличие вывода показаний на экран лампы тоже вызывает массу вопросов.
Показания отдельно, лампа отдельно.
И управление не со смарта, а с тача — больше ничего не надо.
А я бы (по опыту) вместо тача поставил энкодер — быстрее и удобней.
Вообще не понимаю, для чего здесь стоит «не». И с тача, и со смарта, и сценарием, и чёртом лысым. Трудозатраты +- одинаковы, тогда пуркуа бы и нет?
WiFi можно прикрутить куда угодно и для чего угодно. Хороший инженер понимает куда нужно это сделать, а куда нет, даже если это сделать элементарно.
Вот и весь поинт.
Умным хотелось бы видеть разработчика.
Умных ламп не бывает.
И даже умных комментаторов не бывает.
И вообще Вселенная — голограмма!