Portrait UI redesign + HA wire-ups for bedroom fan/light

- Rotate display to portrait (rotation: 0°), 4-row LVGL grid
- Fix touchscreen calibration/transform for portrait orientation
- Wire buttons to alpha_bedroom_{light,ceiling_fan,color_temp}
- Sync button checked state from HA (light/fan on-off + fan percentage)
- Document new orientation and Windows venv path in CLAUDE.md

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Christopher Wiebe
2026-05-10 18:00:10 -07:00
parent a2fbb7ad6a
commit 80378b1d95
2 changed files with 139 additions and 36 deletions
+130 -33
View File
@@ -76,7 +76,7 @@ display:
model: 2.90inv2-r2-2bpp
# model: 2.90inv2-r2
full_update_every: 30
rotation: 270°
rotation: 0°
auto_clear_enabled: false
update_interval: never
@@ -96,12 +96,12 @@ touchscreen:
update_interval: 50ms
calibration:
x_min: 0
x_max: 295
x_max: 127
y_min: 0
y_max: 127
y_max: 295
transform:
swap_xy: true
mirror_x: true
mirror_y: true
### Okay, now the Good Stuff ###
@@ -146,6 +146,8 @@ image:
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
@@ -183,8 +185,8 @@ binary_sensor:
- component.update: display0
# List the actual home entitites that we want this panel to control here
- platform: homeassistant
id: goat_summit_light
entity_id: light.goat_summit_light
id: alpha_bedroom_light
entity_id: light.alpha_bedroom_light
publish_initial_state: true
on_state:
then:
@@ -192,6 +194,38 @@ binary_sensor:
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:
@@ -234,50 +268,74 @@ lvgl:
bg_color: 0xFFFFFF
layout:
type: GRID
grid_rows: [fr(1), fr(1)]
grid_columns: [fr(1), fr(1), fr(1), fr(1)]
grid_rows: [fr(1), fr(1), fr(1), fr(1)]
grid_columns: [fr(1), fr(1)]
widgets:
- button:
id: button_ceiling_fan
grid_cell_row_pos: 0
grid_cell_column_pos: 0
on_click:
- logger.log: "ceiling_fan"
widgets:
- image:
src: ceiling_fan
align: CENTER
# Row 1: Light on/off (full width)
- button:
id: button_ceiling_fan_light
grid_cell_row_pos: 0
grid_cell_column_pos: 1
grid_cell_column_pos: 0
grid_cell_column_span: 2
grid_cell_x_align: STRETCH
width: 124
on_click:
- logger.log: "ceiling_fan_light"
- homeassistant.action:
action: light.toggle
data:
entity_id: light.goat_summit_light
entity_id: light.alpha_bedroom_light
checkable: true
widgets:
- image:
src: ceiling_fan_light
align: CENTER
# Row 2: Fan on/off (full width)
- button:
id: button_fan_off
grid_cell_row_pos: 0
grid_cell_column_pos: 2
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
on_click:
- logger.log: "fan_off"
- logger.log: "ceiling_fan"
- homeassistant.action:
action: fan.toggle
data:
entity_id: fan.alpha_bedroom_ceiling_fan
checkable: true
widgets:
- image:
src: fan_off
src: ceiling_fan
align: CENTER
# Row 3: Light temperature | Fan low
- button:
id: button_light_temp
grid_cell_row_pos: 2
grid_cell_column_pos: 0
on_click:
- logger.log: "light_temp"
- homeassistant.action:
action: button.press
data:
entity_id: button.alpha_bedroom_color_temp
widgets:
- image:
src: light_temp
align: CENTER
- button:
id: button_fan_1
grid_cell_row_pos: 0
grid_cell_column_pos: 3
grid_cell_row_pos: 2
grid_cell_column_pos: 1
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'
- lvgl.widget.update:
id: button_fan_2
state:
@@ -289,30 +347,71 @@ lvgl:
widgets:
- image:
src: fan_speed_1
# Row 4: Fan medium | Fan high
- button:
id: button_fan_2
grid_cell_row_pos: 1
grid_cell_row_pos: 3
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
checkable: true
widgets:
- image:
src: fan_speed_2
- button:
id: button_fan_3
grid_cell_row_pos: 1
grid_cell_row_pos: 3
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
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
- button:
id: button_floor_lamp
grid_cell_row_pos: 1
grid_cell_column_pos: 2
on_click:
- logger.log: "floor_lamp"
checkable: true
@@ -321,8 +420,6 @@ lvgl:
src: floor_lamp
- button:
id: button_away
grid_cell_row_pos: 1
grid_cell_column_pos: 3
on_click:
- logger.log: "away_button"
checkable: true