Commit graph

33 commits

Author SHA1 Message Date
bc0fe401bf feat: wire classic+ Status tab to live relay/uptime/IP data 2026-07-12 19:19:51 -07:00
72843b31e4 feat: reshape classic+ Home screen into quick-actions/dial/weather columns 2026-07-12 19:05:20 -07:00
5c948377d5 feat: scaffold classic+ variant as a baseline fork of the classic display 2026-07-12 18:56:52 -07:00
9e1a9ebe9f feat: add mode selector modal (Heat/Cool/Off) to classic Home screen
The thermostat had no way to actually set its operating mode: home_mode_label
was read-only, and no widget anywhere called climate.control with a mode.
Tapping the mode label now shows a modal (mirrors the existing
nav_menu_overlay pattern) with explicit Heat/Cool/Off choices.
2026-07-12 16:35:05 -07:00
c9df881066 revert: restore differing heat/cool arc radii, required for independent touch
Making both arcs 400px (same-size rings, requested for visual alignment)
broke independent dragging: LVGL's adv_hittest arc hit test only accepts
touches within an arc's own ring band (radius - arc_width to radius, within
its angular span), confirmed via lv_arc.c LV_EVENT_HIT_TEST. Two identical
rings occupy the same band, so only the topmost (cool_arc) ever won the
touch, confirmed on hardware. Reverting to 400px/360px nested rings restores
independent heat/cool dragging; same-size same-position arcs are not
achievable with LVGL's current hit-testing without a larger redesign.
2026-07-12 16:26:51 -07:00
6376c539ed fix: make heat/cool arcs the same size (concentric same-radius rings)
cool_arc was 360px against heat_arc's 400px, nested rather than aligned.
Touch disambiguation already comes entirely from adv_hittest, not radius
difference, so matching them to 400px doesn't affect touch targeting.
2026-07-12 14:46:36 -07:00
a0734891ad fix: display BME280 ambient temperature in Fahrenheit, not Celsius
sensors.yaml formatted the raw BME280 reading directly with no unit
conversion, inconsistent with the dial setpoints and weather widget, which
are already Fahrenheit. Converts at the only point this sensor's value
reaches the UI (shared by every display variant); climate.yaml's internal
Celsius values are untouched since ESPHome's climate component always
operates in Celsius regardless of display unit.
2026-07-12 14:26:27 -07:00
91f47be62a fix: clear default clickable flag on temp_view/status_view to unblock mode toggle
LVGL's base obj is clickable by default (lv_obj_create sets
LV_OBJ_FLAG_CLICKABLE unconditionally). As full-screen, topmost siblings of
mode_toggle, temp_view and status_view were silently capturing every tap
over the toggle bar via lv_obj_hit_test before the touch search could reach
mode_toggle underneath, even though they have no on_click of their own.
Confirmed via generated C++ (lv_obj_remove_flag ... LV_OBJ_FLAG_CLICKABLE)
and hardware testing.
2026-07-12 14:04:49 -07:00
4111f11b04 fix: make temp_view/status_view backgrounds transparent to unblock mode toggle 2026-07-12 13:12:34 -07:00
245bb79203 feat: add HA weather bindings, Status tab, and Temp/Status toggle wiring 2026-07-12 12:59:34 -07:00
434ceda91a fix: enable adv_hittest on dial arcs so touch respects each ring's own radius
Root cause of 'only the cool/blue knob drags, regardless of where you
tap': LVGL's default arc hit-testing just uses each widget's full
bounding square (whichever topmost widget's box contains the touch
point wins), not the precise ring geometry. Since cool_arc's 360x360
box is entirely contained within heat_arc's 400x400 box, cool_arc (on
top in z-order) claimed every touch inside its own square, including
touches physically on heat_arc's outer ring, which sits outside
cool_arc's box but still within heat_arc's simple bounding-box test.

Confirmed via lv_arc.c: LVGL has a precise ring-based hit test
(LV_EVENT_HIT_TEST, respects each widget's own radius and angular
span) but it's opt-in via the ADV_HITTEST flag; without it, LVGL
falls back to the simple bounding-box test. Verified the adv_hittest:
true YAML property generates lv_obj_add_flag(..., LV_OBJ_FLAG_ADV_HITTEST)
via an isolated test compile before applying to both arcs.

The differing radii (400/360) from the previous fix are still useful
for visual separation but were never sufficient on their own — this
flag is what actually makes hit-testing respect the radius difference.
2026-07-12 10:45:52 -07:00
60f133bfa3 fix: flatten arc widget main: style block to top-level properties
Root cause of the Home screen dial rendering tiny and pinned to the
top-left, confirmed via isolated test compile and direct inspection
of generated C++: an explicit main: sub-block on an LVGL arc widget
silently suppresses the implicit top-level MAIN-part style properties
(align, width, height, x, y) instead of merging with them. All three
arcs (dial_bg_arc, heat_arc, cool_arc) used a main: block for
arc_color/arc_width/arc_opa, which wiped out their align/width/height
in the exact same commit that set them (my earlier size/wrapper fix
never had a chance to take effect).

Verified via a standalone test config: an arc with main: nesting
generates zero lv_obj_set_style_width/height/align calls; the
identical arc with the same properties flattened to top-level
generates them correctly. indicator:/knob: are unaffected since those
are genuinely separate LVGL parts that require explicit nesting.
2026-07-12 10:21:51 -07:00
1f750ea779 fix: wrap classic Home screen in a sized container, separate dial arc radii
Two bugs found on first hardware test:

1. page_home placed all widgets directly on the page with no sized
   wrapper container, unlike every other page in this codebase (which
   all wrap content in an explicit width/height obj before using
   align:). The dial and its siblings rendered tiny and pinned to the
   top-left instead of filling/centering on the real 1024x600 screen.
   Wrapped all of page_home's content in a width:100%/height:100% obj,
   matching the established pattern.

2. heat_arc and cool_arc were both adjustable:true at the identical
   400x400 size, so their rings occupied the same physical pixels.
   LVGL hit-tests arcs by distance from center, so a shared radius is
   touch-ambiguous, and the topmost widget (cool_arc, declared last)
   won every touch regardless of where on the ring you tapped. Shrunk
   cool_arc to 360x360 so the two rings are physically distinguishable
   by touch position.
2026-07-12 10:02:56 -07:00
3d47e80de6 fix: convert dial Fahrenheit input to Celsius before climate.control
The dual-arc setpoint dial uses a Fahrenheit-range scale (60-90) to
match the Lennox reference UI, but climate.control expects Celsius
throughout this codebase. Dragging the dial was sending raw
Fahrenheit values straight into target_temperature_low/high, which
would have commanded wildly wrong setpoints on live hardware.
Also fixes a stale comment pointing at the wrong file after the
panel.yaml extraction.
2026-07-12 00:57:28 -07:00
0e99798143 feat: build classic Home screen with dual-arc setpoint dial and Away button 2026-07-12 00:48:49 -07:00
0a6f6ab2fa feat: scaffold classic variant with hamburger nav and reused Sensors/Settings/Schedule pages 2026-07-12 00:39:52 -07:00
2097779949 refactor: extract shared panel.yaml (RGB panel, touch, IO expander) from display.yaml 2026-07-12 00:26:29 -07:00
976410e0b0 Merge branch 'feat/phase2-lvgl-ui' 2026-07-11 23:08:12 -07:00
768caced54 docs: disambiguate 'Phase 2' terminology now that LVGL work claimed that name 2026-07-11 23:00:04 -07:00
3bcba89fba feat: build Schedule screen with Home/Away preset selection 2026-07-11 22:55:33 -07:00
1d3e537df4 feat: build Settings screen with device info and manual relay override 2026-07-11 22:52:31 -07:00
c362bbad34 feat: build Sensors screen with live temp/humidity/pressure readout 2026-07-11 22:45:46 -07:00
d051f0cab0 feat: build Home screen with live temp, mode, and setpoint controls 2026-07-11 22:42:34 -07:00
88042cf850 feat: add LVGL base config with persistent bottom nav bar 2026-07-11 22:35:26 -07:00
90d710e41c chore: add esphome-generated build gitignore 2026-07-11 22:29:19 -07:00
49d0396b57 docs: record Phase 1 hardware bring-up status and deferred items 2026-07-11 22:18:00 -07:00
12b56e3153 fix: route logger through UART0 instead of USB_SERIAL_JTAG
Waveshare's board wires log output through the same UART USB-C port
used for flashing. ESPHome's default hardware_uart for ESP32-S3 is
USB_SERIAL_JTAG, which is a separate physical port on this board,
so log output was going nowhere the flashing tool could see it.
2026-07-11 22:11:14 -07:00
3d2172317c feat: add thermostat climate entity wiring BME280 sensor to relay outputs 2026-07-11 20:08:59 -07:00
db096462be feat: add 5-channel relay GPIO outputs for HVAC control wiring 2026-07-11 20:07:30 -07:00
58798d5751 feat: add BME280 ambient temperature/humidity/pressure sensors 2026-07-11 20:06:21 -07:00
c4906da25a feat: add RGB panel display and GT911 touch config for Waveshare 7" 2026-07-11 20:02:49 -07:00
bb3249e166 feat: scaffold ESPHome project for Waveshare ESP32-S3 7" thermostat 2026-07-11 19:53:54 -07:00
d9478bd904 docs: add phase 1 hardware research notes and pin assignments 2026-07-11 19:50:18 -07:00