2026-05-06 13:53:55 -07:00
|
|
|
# Andrew Villeneuve 2026/05
|
|
|
|
|
# Waveshare 2.9inch Touch ePaper HAT integration demo
|
|
|
|
|
#
|
|
|
|
|
# Platform: https://www.waveshare.com/2.9inch-Touch-e-Paper-HAT.htm
|
|
|
|
|
#
|
|
|
|
|
# Pin mappings
|
|
|
|
|
# ---
|
|
|
|
|
# |Function |ESP Pin |HAT Pin |Wire |
|
|
|
|
|
# |--- |--- |--- |--- |
|
|
|
|
|
# |5V |VIN |Pin2/5V |Red |
|
|
|
|
|
# |GND |GND |Pin6/GND |Blk |
|
2026-05-06 15:35:01 -07:00
|
|
|
# |Display SCLK |GPIO18 |Pin23/GPIO11/SPI0_SCLK |Blue |
|
|
|
|
|
# |Display MOSI |GPIO23 |Pin19/GPIO10/SPI0_MOSI |Green |
|
2026-05-06 13:53:55 -07:00
|
|
|
# |Display CS |GPIO19 |Pin24/GPIO8/SPI0_CE0 |Mgnta |
|
2026-05-06 15:35:01 -07:00
|
|
|
# |Display DC |GPIO17 |Pin22/GPIO25 |White |
|
2026-05-10 23:42:15 -07:00
|
|
|
# |Display Busy |GPIO4 |Pin18/GPIO24 |Brown |
|
2026-05-06 13:53:55 -07:00
|
|
|
# |Display RST |GPIO5 |Pin11/GPIO17/SPI1_CE1 |Orange |
|
2026-05-06 15:35:01 -07:00
|
|
|
# |Touch SDA |GPIO21 |Pin3/GPIO2/I2C1_SDA |Gray |
|
|
|
|
|
# |Touch SCL |GPIO22 |Pin5/GPIO3/I2C1_SCL |Purple |
|
2026-05-07 16:28:08 -07:00
|
|
|
# |Touch RST |GPIO15 |Pin13/GPIO27 |Blue |
|
|
|
|
|
# |Touch INT |GPIO16 |Pin15/GPIO22 |White |
|
2026-05-06 13:53:55 -07:00
|
|
|
#
|
2026-05-10 23:42:15 -07:00
|
|
|
# DISP_RST Moves from GPIO5 -> GPIO25 on PCB to avoid potential
|
|
|
|
|
# strapping issue
|
|
|
|
|
# TOUCH_IRQ Moves from GPIO16 -> GPIO14 on PCB to avoid potential
|
|
|
|
|
# strapping issue
|
|
|
|
|
#
|
2026-05-06 13:53:55 -07:00
|
|
|
# Exposed Entities
|
|
|
|
|
# ---
|
|
|
|
|
#
|
|
|
|
|
|
|
|
|
|
### Boilerplate ###
|
|
|
|
|
|
|
|
|
|
esphome:
|
|
|
|
|
name: waveshare-epaper-test
|
|
|
|
|
|
|
|
|
|
esp32:
|
|
|
|
|
board: nodemcu-32s
|
|
|
|
|
framework:
|
|
|
|
|
type: esp-idf
|
|
|
|
|
|
|
|
|
|
# Enable logging
|
|
|
|
|
logger:
|
|
|
|
|
level: DEBUG
|
|
|
|
|
|
|
|
|
|
# Enable Home Assistant API
|
|
|
|
|
api:
|
|
|
|
|
encryption:
|
|
|
|
|
key: !secret enckey
|
|
|
|
|
|
|
|
|
|
ota:
|
|
|
|
|
- platform: esphome
|
|
|
|
|
password: !secret apipw
|
|
|
|
|
|
|
|
|
|
wifi:
|
|
|
|
|
ssid: !secret wifi_ssid
|
|
|
|
|
password: !secret wappw
|
|
|
|
|
# Enable fallback hotspot (captive portal) in case wifi connection fails
|
|
|
|
|
ap:
|
|
|
|
|
ssid: ${fallbackssid}
|
|
|
|
|
password: !secret hotspotpw
|
|
|
|
|
|
|
|
|
|
captive_portal:
|
|
|
|
|
|
|
|
|
|
### Setup Interfaces ###
|
|
|
|
|
|
2026-05-09 10:16:59 -07:00
|
|
|
# Display
|
2026-05-06 13:53:55 -07:00
|
|
|
spi:
|
2026-05-06 15:35:01 -07:00
|
|
|
clk_pin: GPIO18
|
|
|
|
|
mosi_pin: GPIO23
|
2026-05-06 13:53:55 -07:00
|
|
|
|
2026-05-09 10:16:59 -07:00
|
|
|
display:
|
|
|
|
|
# This platform is a custom_component forked from upstream waveshare_epaper
|
|
|
|
|
# but modified by Claude to support 2bpp greyscale
|
|
|
|
|
- platform: waveshare_epaper_2bit
|
|
|
|
|
id: display0
|
|
|
|
|
cs_pin: GPIO19
|
|
|
|
|
dc_pin: GPIO17
|
|
|
|
|
busy_pin: GPIO4
|
|
|
|
|
reset_pin: GPIO5
|
|
|
|
|
model: 2.90inv2-r2-2bpp
|
|
|
|
|
# model: 2.90inv2-r2
|
|
|
|
|
full_update_every: 30
|
2026-05-10 18:00:10 -07:00
|
|
|
rotation: 0°
|
2026-05-09 10:16:59 -07:00
|
|
|
auto_clear_enabled: false
|
|
|
|
|
update_interval: never
|
|
|
|
|
|
|
|
|
|
# Touchscreen
|
2026-05-06 15:35:01 -07:00
|
|
|
i2c:
|
2026-05-07 16:28:08 -07:00
|
|
|
id: i2c_bus
|
2026-05-06 15:35:01 -07:00
|
|
|
sda: GPIO21
|
|
|
|
|
scl: GPIO22
|
|
|
|
|
scan: false
|
2026-05-07 16:28:08 -07:00
|
|
|
|
|
|
|
|
touchscreen:
|
2026-05-09 10:16:59 -07:00
|
|
|
# This platform is a custom_component written from scratch by Claude
|
2026-05-07 16:28:08 -07:00
|
|
|
platform: icnt86x
|
|
|
|
|
id: touchscreen0
|
|
|
|
|
address: 0x48
|
|
|
|
|
reset_pin: GPIO15
|
|
|
|
|
update_interval: 50ms
|
|
|
|
|
calibration:
|
|
|
|
|
x_min: 0
|
2026-05-10 18:00:10 -07:00
|
|
|
x_max: 127
|
2026-05-07 16:28:08 -07:00
|
|
|
y_min: 0
|
2026-05-10 18:00:10 -07:00
|
|
|
y_max: 295
|
2026-05-07 16:28:08 -07:00
|
|
|
transform:
|
2026-05-10 18:00:10 -07:00
|
|
|
swap_xy: true
|
2026-05-07 16:28:08 -07:00
|
|
|
mirror_x: true
|
|
|
|
|
|
2026-05-06 13:53:55 -07:00
|
|
|
### Okay, now the Good Stuff ###
|
|
|
|
|
|
2026-05-09 10:16:59 -07:00
|
|
|
# Load some fonts for the display renderer
|
2026-05-06 13:53:55 -07:00
|
|
|
font:
|
|
|
|
|
- file: "FreeSans.ttf"
|
|
|
|
|
id: font1
|
|
|
|
|
size: 26
|
|
|
|
|
bpp: 2
|
|
|
|
|
- file: "FreeSans.ttf"
|
|
|
|
|
id: headerfont
|
|
|
|
|
size: 80
|
|
|
|
|
- file: "FreeSans.ttf"
|
|
|
|
|
id: console
|
|
|
|
|
size: 30
|
|
|
|
|
|
|
|
|
|
# Pull in some icons from the material design library
|
2026-05-09 10:16:59 -07:00
|
|
|
# https://pictogrammers.com/library/mdi/
|
2026-05-06 13:53:55 -07:00
|
|
|
image:
|
2026-05-06 15:35:01 -07:00
|
|
|
defaults:
|
|
|
|
|
transparency: chroma_key
|
|
|
|
|
invert_alpha: false
|
|
|
|
|
resize: 54x54
|
|
|
|
|
binary:
|
2026-05-06 13:53:55 -07:00
|
|
|
- file: "mdi:home-lock-open"
|
|
|
|
|
id: home_lock_open
|
2026-05-06 15:35:01 -07:00
|
|
|
- file: "mdi:home-lock"
|
|
|
|
|
id: home_lock
|
2026-05-08 14:59:13 -07:00
|
|
|
- file: "mdi:ceiling-fan"
|
|
|
|
|
id: ceiling_fan
|
|
|
|
|
- file: "mdi:ceiling-fan-light"
|
|
|
|
|
id: ceiling_fan_light
|
|
|
|
|
- file: "mdi:fan-off"
|
|
|
|
|
id: fan_off
|
|
|
|
|
- file: "mdi:fan-speed-1"
|
|
|
|
|
id: fan_speed_1
|
|
|
|
|
- file: "mdi:fan-speed-2"
|
|
|
|
|
id: fan_speed_2
|
|
|
|
|
- file: "mdi:fan-speed-3"
|
|
|
|
|
id: fan_speed_3
|
|
|
|
|
- file: "mdi:floor-lamp-torchiere"
|
|
|
|
|
id: floor_lamp
|
|
|
|
|
- file: "mdi:home-off"
|
|
|
|
|
id: away_button
|
2026-05-10 18:00:10 -07:00
|
|
|
- file: "mdi:thermometer"
|
|
|
|
|
id: light_temp
|
2026-05-06 13:53:55 -07:00
|
|
|
|
2026-05-09 10:16:59 -07:00
|
|
|
# When the user taps the screen, introduce a small delay for the LVGL framebuffer
|
|
|
|
|
# to stabilize, then do a quick, 1-bit B/W selective update to visually indicate
|
|
|
|
|
# that a button was pushed.
|
|
|
|
|
#
|
|
|
|
|
# When the user is done interacting with the screen and several seconds have
|
|
|
|
|
# passed, do a slow, full-screen redraw at 2-bit grayscale.
|
|
|
|
|
script:
|
|
|
|
|
- id: refresh_display
|
|
|
|
|
mode: restart
|
|
|
|
|
then:
|
2026-05-10 18:52:34 -07:00
|
|
|
- delay: 80ms
|
|
|
|
|
- lambda: 'id(display0).display_partial();'
|
|
|
|
|
# Retry once the e-paper's busy window has cleared, to catch HA-synced
|
|
|
|
|
# widget updates that landed while the first partial refresh was in flight
|
|
|
|
|
# (display_partial drops calls when busy).
|
|
|
|
|
- delay: 350ms
|
2026-05-09 10:16:59 -07:00
|
|
|
- lambda: 'id(display0).display_partial();'
|
|
|
|
|
- id: full_refresh_display
|
|
|
|
|
mode: restart
|
|
|
|
|
then:
|
|
|
|
|
- delay: 10s
|
|
|
|
|
- component.update: display0
|
|
|
|
|
|
2026-05-06 13:53:55 -07:00
|
|
|
binary_sensor:
|
2026-05-09 10:16:59 -07:00
|
|
|
# Force a full display refresh when we press the "boot" button on the devboard
|
2026-05-06 13:53:55 -07:00
|
|
|
- platform: gpio
|
|
|
|
|
pin:
|
|
|
|
|
number: GPIO0
|
|
|
|
|
mode:
|
|
|
|
|
input: true
|
|
|
|
|
pullup: true
|
|
|
|
|
inverted: true
|
|
|
|
|
id: boot_button
|
|
|
|
|
internal: true
|
2026-05-07 16:28:08 -07:00
|
|
|
on_click:
|
2026-05-06 13:53:55 -07:00
|
|
|
then:
|
|
|
|
|
- component.update: lvgl0
|
|
|
|
|
- delay: 1s
|
|
|
|
|
- component.update: display0
|
2026-05-09 10:16:59 -07:00
|
|
|
# List the actual home entitites that we want this panel to control here
|
|
|
|
|
- platform: homeassistant
|
2026-05-10 18:00:10 -07:00
|
|
|
id: alpha_bedroom_light
|
|
|
|
|
entity_id: light.alpha_bedroom_light
|
2026-05-09 10:16:59 -07:00
|
|
|
publish_initial_state: true
|
|
|
|
|
on_state:
|
|
|
|
|
then:
|
|
|
|
|
- lvgl.widget.update:
|
|
|
|
|
id: button_ceiling_fan_light
|
|
|
|
|
state:
|
|
|
|
|
checked: !lambda return x;
|
2026-05-10 18:00:10 -07:00
|
|
|
- platform: homeassistant
|
|
|
|
|
id: alpha_bedroom_ceiling_fan
|
|
|
|
|
entity_id: fan.alpha_bedroom_ceiling_fan
|
|
|
|
|
publish_initial_state: true
|
|
|
|
|
on_state:
|
|
|
|
|
then:
|
|
|
|
|
- lvgl.widget.update:
|
|
|
|
|
id: button_ceiling_fan
|
|
|
|
|
state:
|
|
|
|
|
checked: !lambda return x;
|
|
|
|
|
|
|
|
|
|
sensor:
|
|
|
|
|
# Track the fan's current percentage so the speed buttons reflect the
|
|
|
|
|
# actual HA state (including changes made via other controls).
|
|
|
|
|
- platform: homeassistant
|
|
|
|
|
id: alpha_bedroom_ceiling_fan_pct
|
|
|
|
|
entity_id: fan.alpha_bedroom_ceiling_fan
|
|
|
|
|
attribute: percentage
|
|
|
|
|
on_value:
|
|
|
|
|
then:
|
|
|
|
|
- lvgl.widget.update:
|
|
|
|
|
id: button_fan_1
|
|
|
|
|
state:
|
|
|
|
|
checked: !lambda 'return x >= 1 && x < 50;'
|
|
|
|
|
- lvgl.widget.update:
|
|
|
|
|
id: button_fan_2
|
|
|
|
|
state:
|
|
|
|
|
checked: !lambda 'return x >= 50 && x < 84;'
|
|
|
|
|
- lvgl.widget.update:
|
|
|
|
|
id: button_fan_3
|
|
|
|
|
state:
|
|
|
|
|
checked: !lambda 'return x >= 84;'
|
2026-05-06 13:53:55 -07:00
|
|
|
|
2026-05-09 10:16:59 -07:00
|
|
|
# Here's where we put the actual GUI layout
|
2026-05-06 13:53:55 -07:00
|
|
|
lvgl:
|
|
|
|
|
- id: lvgl0
|
|
|
|
|
displays:
|
|
|
|
|
- display0
|
2026-05-07 16:28:08 -07:00
|
|
|
touchscreens:
|
|
|
|
|
- touchscreen0
|
2026-05-09 10:16:59 -07:00
|
|
|
on_draw_end:
|
|
|
|
|
- script.execute: refresh_display
|
|
|
|
|
- script.execute: full_refresh_display
|
2026-05-06 13:53:55 -07:00
|
|
|
# Black: 0x000000
|
|
|
|
|
# Dark Grey: 0x555555
|
|
|
|
|
# Light Grey: 0xAAAAAA
|
|
|
|
|
# White: 0xFFFFFF
|
2026-05-09 10:16:59 -07:00
|
|
|
bg_color: 0x000000
|
2026-05-06 13:53:55 -07:00
|
|
|
theme:
|
2026-05-06 15:35:01 -07:00
|
|
|
button:
|
2026-05-08 14:59:13 -07:00
|
|
|
bg_color: 0xFFFFFF
|
|
|
|
|
text_color: 0x000000
|
2026-05-09 10:16:59 -07:00
|
|
|
height: 60
|
2026-05-06 15:35:01 -07:00
|
|
|
width: 64
|
|
|
|
|
pad_all: 0
|
2026-05-08 14:59:13 -07:00
|
|
|
border_width: 2
|
|
|
|
|
border_color: 0x000000
|
|
|
|
|
checked:
|
2026-05-09 10:16:59 -07:00
|
|
|
bg_color: 0x888888
|
|
|
|
|
align: CENTER
|
2026-05-06 13:53:55 -07:00
|
|
|
obj:
|
|
|
|
|
bg_color: 0xFFFFFF
|
|
|
|
|
widgets:
|
2026-05-08 14:59:13 -07:00
|
|
|
- obj:
|
|
|
|
|
width: 100%
|
|
|
|
|
height: 100%
|
2026-05-09 10:16:59 -07:00
|
|
|
scrollable: false
|
2026-05-08 14:59:13 -07:00
|
|
|
pad_all: 0
|
|
|
|
|
# pad_row: 0
|
|
|
|
|
# pad_column: 0
|
|
|
|
|
border_width: 0
|
|
|
|
|
bg_color: 0xFFFFFF
|
|
|
|
|
layout:
|
|
|
|
|
type: GRID
|
2026-05-10 18:00:10 -07:00
|
|
|
grid_rows: [fr(1), fr(1), fr(1), fr(1)]
|
|
|
|
|
grid_columns: [fr(1), fr(1)]
|
2026-05-06 15:35:01 -07:00
|
|
|
widgets:
|
2026-05-10 18:00:10 -07:00
|
|
|
# Row 1: Light on/off (full width)
|
2026-05-08 14:59:13 -07:00
|
|
|
- button:
|
2026-05-10 18:00:10 -07:00
|
|
|
id: button_ceiling_fan_light
|
2026-05-08 14:59:13 -07:00
|
|
|
grid_cell_row_pos: 0
|
|
|
|
|
grid_cell_column_pos: 0
|
2026-05-10 18:00:10 -07:00
|
|
|
grid_cell_column_span: 2
|
|
|
|
|
grid_cell_x_align: STRETCH
|
|
|
|
|
width: 124
|
2026-05-08 14:59:13 -07:00
|
|
|
on_click:
|
2026-05-10 18:00:10 -07:00
|
|
|
- logger.log: "ceiling_fan_light"
|
|
|
|
|
- homeassistant.action:
|
|
|
|
|
action: light.toggle
|
|
|
|
|
data:
|
|
|
|
|
entity_id: light.alpha_bedroom_light
|
|
|
|
|
checkable: true
|
2026-05-08 14:59:13 -07:00
|
|
|
widgets:
|
|
|
|
|
- image:
|
2026-05-10 18:00:10 -07:00
|
|
|
src: ceiling_fan_light
|
2026-05-09 10:16:59 -07:00
|
|
|
align: CENTER
|
2026-05-10 18:00:10 -07:00
|
|
|
# Row 2: Fan on/off (full width)
|
2026-05-08 14:59:13 -07:00
|
|
|
- button:
|
2026-05-10 18:00:10 -07:00
|
|
|
id: button_ceiling_fan
|
|
|
|
|
grid_cell_row_pos: 1
|
|
|
|
|
grid_cell_column_pos: 0
|
|
|
|
|
grid_cell_column_span: 2
|
|
|
|
|
grid_cell_x_align: STRETCH
|
|
|
|
|
width: 124
|
2026-05-08 14:59:13 -07:00
|
|
|
on_click:
|
2026-05-10 18:00:10 -07:00
|
|
|
- logger.log: "ceiling_fan"
|
2026-05-09 10:16:59 -07:00
|
|
|
- homeassistant.action:
|
2026-05-10 18:00:10 -07:00
|
|
|
action: fan.toggle
|
2026-05-09 10:16:59 -07:00
|
|
|
data:
|
2026-05-10 18:00:10 -07:00
|
|
|
entity_id: fan.alpha_bedroom_ceiling_fan
|
2026-05-08 14:59:13 -07:00
|
|
|
checkable: true
|
|
|
|
|
widgets:
|
|
|
|
|
- image:
|
2026-05-10 18:00:10 -07:00
|
|
|
src: ceiling_fan
|
|
|
|
|
align: CENTER
|
|
|
|
|
# Row 3: Light temperature | Fan low
|
2026-05-08 14:59:13 -07:00
|
|
|
- button:
|
2026-05-10 18:00:10 -07:00
|
|
|
id: button_light_temp
|
|
|
|
|
grid_cell_row_pos: 2
|
|
|
|
|
grid_cell_column_pos: 0
|
2026-05-08 14:59:13 -07:00
|
|
|
on_click:
|
2026-05-10 18:00:10 -07:00
|
|
|
- logger.log: "light_temp"
|
|
|
|
|
- homeassistant.action:
|
|
|
|
|
action: button.press
|
|
|
|
|
data:
|
|
|
|
|
entity_id: button.alpha_bedroom_color_temp
|
2026-05-08 14:59:13 -07:00
|
|
|
widgets:
|
|
|
|
|
- image:
|
2026-05-10 18:00:10 -07:00
|
|
|
src: light_temp
|
|
|
|
|
align: CENTER
|
2026-05-08 14:59:13 -07:00
|
|
|
- button:
|
2026-05-09 10:16:59 -07:00
|
|
|
id: button_fan_1
|
2026-05-10 18:00:10 -07:00
|
|
|
grid_cell_row_pos: 2
|
|
|
|
|
grid_cell_column_pos: 1
|
2026-05-08 14:59:13 -07:00
|
|
|
checkable: true
|
|
|
|
|
on_click:
|
|
|
|
|
- logger.log: "fan_speed_1"
|
2026-05-10 18:00:10 -07:00
|
|
|
- homeassistant.action:
|
|
|
|
|
action: fan.set_percentage
|
|
|
|
|
data:
|
|
|
|
|
entity_id: fan.alpha_bedroom_ceiling_fan
|
|
|
|
|
percentage: '33'
|
2026-05-08 14:59:13 -07:00
|
|
|
- lvgl.widget.update:
|
2026-05-09 10:16:59 -07:00
|
|
|
id: button_fan_2
|
2026-05-08 14:59:13 -07:00
|
|
|
state:
|
|
|
|
|
checked: false
|
|
|
|
|
- lvgl.widget.update:
|
2026-05-09 10:16:59 -07:00
|
|
|
id: button_fan_3
|
2026-05-08 14:59:13 -07:00
|
|
|
state:
|
|
|
|
|
checked: false
|
|
|
|
|
widgets:
|
|
|
|
|
- image:
|
|
|
|
|
src: fan_speed_1
|
2026-05-10 18:00:10 -07:00
|
|
|
# Row 4: Fan medium | Fan high
|
2026-05-08 14:59:13 -07:00
|
|
|
- button:
|
2026-05-09 10:16:59 -07:00
|
|
|
id: button_fan_2
|
2026-05-10 18:00:10 -07:00
|
|
|
grid_cell_row_pos: 3
|
2026-05-08 14:59:13 -07:00
|
|
|
grid_cell_column_pos: 0
|
|
|
|
|
on_click:
|
|
|
|
|
- logger.log: "fan_speed_2"
|
2026-05-10 18:00:10 -07:00
|
|
|
- homeassistant.action:
|
|
|
|
|
action: fan.set_percentage
|
|
|
|
|
data:
|
|
|
|
|
entity_id: fan.alpha_bedroom_ceiling_fan
|
|
|
|
|
percentage: '66'
|
|
|
|
|
- lvgl.widget.update:
|
|
|
|
|
id: button_fan_1
|
|
|
|
|
state:
|
|
|
|
|
checked: false
|
|
|
|
|
- lvgl.widget.update:
|
|
|
|
|
id: button_fan_3
|
|
|
|
|
state:
|
|
|
|
|
checked: false
|
2026-05-08 14:59:13 -07:00
|
|
|
checkable: true
|
|
|
|
|
widgets:
|
|
|
|
|
- image:
|
|
|
|
|
src: fan_speed_2
|
|
|
|
|
- button:
|
2026-05-09 10:16:59 -07:00
|
|
|
id: button_fan_3
|
2026-05-10 18:00:10 -07:00
|
|
|
grid_cell_row_pos: 3
|
2026-05-08 14:59:13 -07:00
|
|
|
grid_cell_column_pos: 1
|
|
|
|
|
on_click:
|
|
|
|
|
- logger.log: "fan_speed_3"
|
2026-05-10 18:00:10 -07:00
|
|
|
- homeassistant.action:
|
|
|
|
|
action: fan.set_percentage
|
|
|
|
|
data:
|
|
|
|
|
entity_id: fan.alpha_bedroom_ceiling_fan
|
|
|
|
|
percentage: '100'
|
|
|
|
|
- lvgl.widget.update:
|
|
|
|
|
id: button_fan_1
|
|
|
|
|
state:
|
|
|
|
|
checked: false
|
|
|
|
|
- lvgl.widget.update:
|
|
|
|
|
id: button_fan_2
|
|
|
|
|
state:
|
|
|
|
|
checked: false
|
2026-05-08 14:59:13 -07:00
|
|
|
checkable: true
|
|
|
|
|
widgets:
|
|
|
|
|
- image:
|
|
|
|
|
src: fan_speed_3
|
2026-05-10 18:00:10 -07:00
|
|
|
# Unused buttons — kept defined but hidden for future use
|
|
|
|
|
- obj:
|
|
|
|
|
hidden: true
|
|
|
|
|
width: 1
|
|
|
|
|
height: 1
|
|
|
|
|
border_width: 0
|
|
|
|
|
pad_all: 0
|
|
|
|
|
widgets:
|
|
|
|
|
- button:
|
|
|
|
|
id: button_fan_off
|
|
|
|
|
on_click:
|
|
|
|
|
- logger.log: "fan_off"
|
|
|
|
|
checkable: true
|
|
|
|
|
widgets:
|
|
|
|
|
- image:
|
|
|
|
|
src: fan_off
|
2026-05-08 14:59:13 -07:00
|
|
|
- button:
|
2026-05-09 10:16:59 -07:00
|
|
|
id: button_floor_lamp
|
2026-05-08 14:59:13 -07:00
|
|
|
on_click:
|
|
|
|
|
- logger.log: "floor_lamp"
|
|
|
|
|
checkable: true
|
|
|
|
|
widgets:
|
|
|
|
|
- image:
|
|
|
|
|
src: floor_lamp
|
|
|
|
|
- button:
|
2026-05-09 10:16:59 -07:00
|
|
|
id: button_away
|
2026-05-08 14:59:13 -07:00
|
|
|
on_click:
|
|
|
|
|
- logger.log: "away_button"
|
|
|
|
|
checkable: true
|
|
|
|
|
widgets:
|
|
|
|
|
- image:
|
|
|
|
|
src: away_button
|