Files
waveshare-panel/waveshare-test.yaml
T

429 lines
12 KiB
YAML
Raw Normal View History

# 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 |
# |Display CS |GPIO19 |Pin24/GPIO8/SPI0_CE0 |Mgnta |
2026-05-06 15:35:01 -07:00
# |Display DC |GPIO17 |Pin22/GPIO25 |White |
# |Display Busy |GPIO4 |Pin24/GPIO24 |Brown |
# |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 |
#
# 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 ###
# Display
spi:
2026-05-06 15:35:01 -07:00
clk_pin: GPIO18
mosi_pin: GPIO23
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
rotation: 0°
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:
# 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
x_max: 127
2026-05-07 16:28:08 -07:00
y_min: 0
y_max: 295
2026-05-07 16:28:08 -07:00
transform:
swap_xy: true
2026-05-07 16:28:08 -07:00
mirror_x: true
### Okay, now the Good Stuff ###
# Load some fonts for the display renderer
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
# https://pictogrammers.com/library/mdi/
image:
2026-05-06 15:35:01 -07:00
defaults:
transparency: chroma_key
invert_alpha: false
resize: 54x54
binary:
- 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
- file: "mdi:thermometer"
id: light_temp
# 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:
- delay: 60ms
- lambda: 'id(display0).display_partial();'
- id: full_refresh_display
mode: restart
then:
- delay: 10s
- component.update: display0
binary_sensor:
# Force a full display refresh when we press the "boot" button on the devboard
- 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:
then:
- component.update: lvgl0
- delay: 1s
- component.update: display0
# List the actual home entitites that we want this panel to control here
- platform: homeassistant
id: alpha_bedroom_light
entity_id: light.alpha_bedroom_light
publish_initial_state: true
on_state:
then:
- lvgl.widget.update:
id: button_ceiling_fan_light
state:
checked: !lambda return x;
- 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;'
# Here's where we put the actual GUI layout
lvgl:
- id: lvgl0
displays:
- display0
2026-05-07 16:28:08 -07:00
touchscreens:
- touchscreen0
on_draw_end:
- script.execute: refresh_display
- script.execute: full_refresh_display
# Black: 0x000000
# Dark Grey: 0x555555
# Light Grey: 0xAAAAAA
# White: 0xFFFFFF
bg_color: 0x000000
theme:
2026-05-06 15:35:01 -07:00
button:
2026-05-08 14:59:13 -07:00
bg_color: 0xFFFFFF
text_color: 0x000000
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:
bg_color: 0x888888
align: CENTER
obj:
bg_color: 0xFFFFFF
widgets:
2026-05-08 14:59:13 -07:00
- obj:
width: 100%
height: 100%
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
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:
# Row 1: Light on/off (full width)
2026-05-08 14:59:13 -07:00
- button:
id: button_ceiling_fan_light
2026-05-08 14:59:13 -07:00
grid_cell_row_pos: 0
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:
- 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:
src: ceiling_fan_light
align: CENTER
# Row 2: Fan on/off (full width)
2026-05-08 14:59:13 -07:00
- button:
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:
- logger.log: "ceiling_fan"
- homeassistant.action:
action: fan.toggle
data:
entity_id: fan.alpha_bedroom_ceiling_fan
2026-05-08 14:59:13 -07:00
checkable: true
widgets:
- image:
src: ceiling_fan
align: CENTER
# Row 3: Light temperature | Fan low
2026-05-08 14:59:13 -07:00
- button:
id: button_light_temp
grid_cell_row_pos: 2
grid_cell_column_pos: 0
2026-05-08 14:59:13 -07:00
on_click:
- 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:
src: light_temp
align: CENTER
2026-05-08 14:59:13 -07:00
- button:
id: button_fan_1
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"
- 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:
id: button_fan_2
2026-05-08 14:59:13 -07:00
state:
checked: false
- lvgl.widget.update:
id: button_fan_3
2026-05-08 14:59:13 -07:00
state:
checked: false
widgets:
- image:
src: fan_speed_1
# Row 4: Fan medium | Fan high
2026-05-08 14:59:13 -07:00
- button:
id: button_fan_2
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"
- 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:
id: button_fan_3
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"
- 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
# 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:
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:
id: button_away
2026-05-08 14:59:13 -07:00
on_click:
- logger.log: "away_button"
checkable: true
widgets:
- image:
src: away_button