From 88042cf850819e64c8fa721bfb770774102f980c Mon Sep 17 00:00:00 2001 From: pyr0ball Date: Sat, 11 Jul 2026 22:35:26 -0700 Subject: [PATCH 1/5] feat: add LVGL base config with persistent bottom nav bar --- firmware/components/display.yaml | 81 +++++++++++++++++++++++++++++--- 1 file changed, 74 insertions(+), 7 deletions(-) diff --git a/firmware/components/display.yaml b/firmware/components/display.yaml index 604e5c5..6c3bb04 100644 --- a/firmware/components/display.yaml +++ b/firmware/components/display.yaml @@ -37,11 +37,78 @@ display: number: 6 # EXIO6 = LCD_VDD_EN (VCOM enable) — the built-in preset doesn't set # this, but the Waveshare wiki confirms VCOM must be driven high on # this board or the panel won't display correctly. Added explicitly. - lambda: |- - it.fill(Color::BLACK); - it.print(512, 300, id(font_label), TextAlign::CENTER, "Thermostat — Phase 1 OK"); -font: - - file: "gfonts://Roboto" - id: font_label - size: 32 +lvgl: + id: lvgl_comp + displays: + - lcd_display + touchscreens: + - touch_gt911 + pages: + - id: page_home + widgets: [] + - id: page_sensors + widgets: [] + - id: page_settings + widgets: [] + - id: page_schedule + widgets: [] + top_layer: + widgets: + - obj: + id: nav_bar + align: bottom_mid + width: 100% + height: 90px + pad_all: 4 + radius: 0 + border_width: 0 + outline_width: 0 + scrollable: false + layout: + type: flex + flex_flow: row + flex_align_cross: center + flex_align_track: center + flex_align_main: space_evenly + widgets: + - button: + id: nav_btn_home + width: 220px + height: 78px + on_click: + lvgl.page.show: page_home + widgets: + - label: + text: "Home" + text_font: montserrat_20 + - button: + id: nav_btn_sensors + width: 220px + height: 78px + on_click: + lvgl.page.show: page_sensors + widgets: + - label: + text: "Sensors" + text_font: montserrat_20 + - button: + id: nav_btn_settings + width: 220px + height: 78px + on_click: + lvgl.page.show: page_settings + widgets: + - label: + text: "Settings" + text_font: montserrat_20 + - button: + id: nav_btn_schedule + width: 220px + height: 78px + on_click: + lvgl.page.show: page_schedule + widgets: + - label: + text: "Schedule" + text_font: montserrat_20 From d051f0cab017c08c7d1554d7bbdef27034ea5b5a Mon Sep 17 00:00:00 2001 From: pyr0ball Date: Sat, 11 Jul 2026 22:42:34 -0700 Subject: [PATCH 2/5] feat: build Home screen with live temp, mode, and setpoint controls --- firmware/components/climate.yaml | 11 ++++++ firmware/components/display.yaml | 61 +++++++++++++++++++++++++++++++- firmware/components/sensors.yaml | 7 ++++ 3 files changed, 78 insertions(+), 1 deletion(-) diff --git a/firmware/components/climate.yaml b/firmware/components/climate.yaml index 9638e99..0439893 100644 --- a/firmware/components/climate.yaml +++ b/firmware/components/climate.yaml @@ -42,3 +42,14 @@ climate: - switch.turn_off: relay_heat2 - switch.turn_off: relay_cool1 - switch.turn_off: relay_cool2 + on_state: + then: + - lvgl.label.update: + id: home_mode_label + text: !lambda |- + switch (id(main_thermostat).mode) { + case climate::CLIMATE_MODE_HEAT: return "Mode: Heat"; + case climate::CLIMATE_MODE_COOL: return "Mode: Cool"; + case climate::CLIMATE_MODE_OFF: return "Mode: Off"; + default: return "Mode: Idle"; + } diff --git a/firmware/components/display.yaml b/firmware/components/display.yaml index 6c3bb04..6f0f285 100644 --- a/firmware/components/display.yaml +++ b/firmware/components/display.yaml @@ -46,7 +46,66 @@ lvgl: - touch_gt911 pages: - id: page_home - widgets: [] + widgets: + - obj: + width: 100% + height: 510px + pad_all: 16 + border_width: 0 + outline_width: 0 + scrollable: false + layout: + type: flex + flex_flow: column + flex_align_cross: center + flex_align_track: center + flex_align_main: space_evenly + widgets: + - label: + id: home_temp_label + text: "-- °C" + text_font: montserrat_48 + - label: + id: home_mode_label + text: "Mode: --" + text_font: montserrat_28 + - obj: + width: 100% + height: size_content + border_width: 0 + outline_width: 0 + scrollable: false + layout: + type: flex + flex_flow: row + flex_align_cross: center + flex_align_track: center + flex_align_main: space_evenly + widgets: + - button: + width: 140px + height: 100px + on_click: + climate.control: + id: main_thermostat + target_temperature_low: !lambda "return id(main_thermostat).target_temperature_low - 0.5f;" + target_temperature_high: !lambda "return id(main_thermostat).target_temperature_high - 0.5f;" + widgets: + - label: + text: "-" + text_font: montserrat_40 + - button: + width: 140px + height: 100px + on_click: + climate.control: + id: main_thermostat + target_temperature_low: !lambda "return id(main_thermostat).target_temperature_low + 0.5f;" + target_temperature_high: !lambda "return id(main_thermostat).target_temperature_high + 0.5f;" + widgets: + - label: + text: "+" + text_font: montserrat_40 - id: page_sensors widgets: [] - id: page_settings diff --git a/firmware/components/sensors.yaml b/firmware/components/sensors.yaml index 54e3e96..23fb8c5 100644 --- a/firmware/components/sensors.yaml +++ b/firmware/components/sensors.yaml @@ -6,6 +6,13 @@ sensor: temperature: name: "Ambient Temperature" id: bme280_temperature + on_value: + then: + - lvgl.label.update: + id: home_temp_label + text: + format: "%.1f °C" + args: ["x"] humidity: name: "Ambient Humidity" id: bme280_humidity From c362bbad34bb4b41b38de641b05369eeac86e233 Mon Sep 17 00:00:00 2001 From: pyr0ball Date: Sat, 11 Jul 2026 22:45:46 -0700 Subject: [PATCH 3/5] feat: build Sensors screen with live temp/humidity/pressure readout --- firmware/components/display.yaml | 28 +++++++++++++++++++++++++++- firmware/components/sensors.yaml | 19 +++++++++++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/firmware/components/display.yaml b/firmware/components/display.yaml index 6f0f285..7025f64 100644 --- a/firmware/components/display.yaml +++ b/firmware/components/display.yaml @@ -107,7 +107,33 @@ lvgl: text: "+" text_font: montserrat_40 - id: page_sensors - widgets: [] + widgets: + - obj: + width: 100% + height: 510px + pad_all: 16 + border_width: 0 + outline_width: 0 + scrollable: false + layout: + type: flex + flex_flow: column + flex_align_cross: center + flex_align_track: center + flex_align_main: space_evenly + widgets: + - label: + id: sensors_temp_label + text: "Temperature: -- °C" + text_font: montserrat_28 + - label: + id: sensors_humidity_label + text: "Humidity: -- %" + text_font: montserrat_28 + - label: + id: sensors_pressure_label + text: "Pressure: -- hPa" + text_font: montserrat_28 - id: page_settings widgets: [] - id: page_schedule diff --git a/firmware/components/sensors.yaml b/firmware/components/sensors.yaml index 23fb8c5..a78a4d3 100644 --- a/firmware/components/sensors.yaml +++ b/firmware/components/sensors.yaml @@ -13,9 +13,28 @@ sensor: text: format: "%.1f °C" args: ["x"] + - lvgl.label.update: + id: sensors_temp_label + text: + format: "Temperature: %.1f °C" + args: ["x"] humidity: name: "Ambient Humidity" id: bme280_humidity + on_value: + then: + - lvgl.label.update: + id: sensors_humidity_label + text: + format: "Humidity: %.1f %%" + args: ["x"] pressure: name: "Ambient Pressure" id: bme280_pressure + on_value: + then: + - lvgl.label.update: + id: sensors_pressure_label + text: + format: "Pressure: %.1f hPa" + args: ["x"] From 1d3e537df4e7c99240255223c4db24e2d42db2ce Mon Sep 17 00:00:00 2001 From: pyr0ball Date: Sat, 11 Jul 2026 22:52:31 -0700 Subject: [PATCH 4/5] feat: build Settings screen with device info and manual relay override --- firmware/components/diagnostics.yaml | 25 ++++++++++++ firmware/components/display.yaml | 60 +++++++++++++++++++++++++++- firmware/waveshare-thermostat.yaml | 1 + 3 files changed, 85 insertions(+), 1 deletion(-) create mode 100644 firmware/components/diagnostics.yaml diff --git a/firmware/components/diagnostics.yaml b/firmware/components/diagnostics.yaml new file mode 100644 index 0000000..8a91790 --- /dev/null +++ b/firmware/components/diagnostics.yaml @@ -0,0 +1,25 @@ +text_sensor: + - platform: wifi_info + ip_address: + name: "IP Address" + id: wifi_ip_text + on_value: + then: + - lvgl.label.update: + id: settings_ip_label + text: + format: "IP: %s" + args: ["x.c_str()"] + +sensor: + - platform: uptime + name: "Uptime" + id: uptime_sensor + update_interval: 60s + on_value: + then: + - lvgl.label.update: + id: settings_uptime_label + text: + format: "Uptime: %.0f min" + args: ["x / 60.0f"] diff --git a/firmware/components/display.yaml b/firmware/components/display.yaml index 7025f64..cf5d716 100644 --- a/firmware/components/display.yaml +++ b/firmware/components/display.yaml @@ -135,7 +135,65 @@ lvgl: text: "Pressure: -- hPa" text_font: montserrat_28 - id: page_settings - widgets: [] + widgets: + - obj: + width: 100% + height: 510px + pad_all: 16 + border_width: 0 + outline_width: 0 + scrollable: false + layout: + type: flex + flex_flow: column + flex_align_cross: center + flex_align_track: start + flex_align_main: start + widgets: + - label: + id: settings_ip_label + text: "IP: --" + text_font: montserrat_20 + - label: + id: settings_uptime_label + text: "Uptime: -- min" + text_font: montserrat_20 + - label: + text: "Manual relay override (bypasses thermostat):" + text_font: montserrat_16 + - obj: + width: 100% + height: size_content + border_width: 0 + outline_width: 0 + scrollable: false + layout: + type: flex + flex_flow: row_wrap + flex_align_cross: start + flex_align_track: start + flex_align_main: start + widgets: + - checkbox: + text: "Fan" + on_click: + switch.toggle: relay_fan + - checkbox: + text: "Cool 1" + on_click: + switch.toggle: relay_cool1 + - checkbox: + text: "Cool 2" + on_click: + switch.toggle: relay_cool2 + - checkbox: + text: "Heat 1" + on_click: + switch.toggle: relay_heat1 + - checkbox: + text: "Heat 2" + on_click: + switch.toggle: relay_heat2 - id: page_schedule widgets: [] top_layer: diff --git a/firmware/waveshare-thermostat.yaml b/firmware/waveshare-thermostat.yaml index f1d9d69..37301d8 100644 --- a/firmware/waveshare-thermostat.yaml +++ b/firmware/waveshare-thermostat.yaml @@ -48,3 +48,4 @@ packages: sensors: !include components/sensors.yaml relays: !include components/relays.yaml climate: !include components/climate.yaml + diagnostics: !include components/diagnostics.yaml From 3bcba89fba4ab5944c6a4903910bb33816326236 Mon Sep 17 00:00:00 2001 From: pyr0ball Date: Sat, 11 Jul 2026 22:55:33 -0700 Subject: [PATCH 5/5] feat: build Schedule screen with Home/Away preset selection --- firmware/components/display.yaml | 57 +++++++++++++++++++++++++++++++- 1 file changed, 56 insertions(+), 1 deletion(-) diff --git a/firmware/components/display.yaml b/firmware/components/display.yaml index cf5d716..57d4e0f 100644 --- a/firmware/components/display.yaml +++ b/firmware/components/display.yaml @@ -195,7 +195,62 @@ lvgl: on_click: switch.toggle: relay_heat2 - id: page_schedule - widgets: [] + widgets: + - obj: + width: 100% + height: 510px + pad_all: 16 + border_width: 0 + outline_width: 0 + scrollable: false + layout: + type: flex + flex_flow: column + flex_align_cross: center + flex_align_track: center + flex_align_main: space_evenly + widgets: + - label: + text: "Preset" + text_font: montserrat_28 + - obj: + width: 100% + height: size_content + border_width: 0 + outline_width: 0 + scrollable: false + layout: + type: flex + flex_flow: row + flex_align_cross: center + flex_align_track: center + flex_align_main: space_evenly + widgets: + - button: + width: 300px + height: 100px + on_click: + climate.control: + id: main_thermostat + preset: home + widgets: + - label: + text: "Home" + text_font: montserrat_28 + - button: + width: 300px + height: 100px + on_click: + climate.control: + id: main_thermostat + preset: away + widgets: + - label: + text: "Away" + text_font: montserrat_28 + - label: + text: "Time-based scheduling runs in Home Assistant, not on this device." + text_font: montserrat_16 top_layer: widgets: - obj: