Sitelet https://github.com/akomakom/esp32-spa-controller/commit/fc233c7368c2a2fb0a6dfa496a1b8094f8e72537
Skip to content

Commit fc233c7

Browse files
akomakomclaude
andcommitted
Display: modern dark-card theme
Apply LVGL dark theme + slate background; restyle control cards as rounded, state-coloured tiles (OFF dark / ON red / pump LOW amber, HIGH orange / heater dark with warm setpoint) with name top-left, large value bottom-left, override chip bottom-right. Value (ON/OFF) now shown for off-on controls too. Recolour the top banner: muted name + cyan water temperature. Matches the approved mockup. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 0cc0edb commit fc233c7

1 file changed

Lines changed: 69 additions & 51 deletions

File tree

‎display/display.ino‎

Lines changed: 69 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@
1212
#endif
1313
#include <vector>
1414
#include "ESPNowUtils.h"
15+
16+
// Card colours for the dark theme (0xRRGGBB): background, border, name/value text.
17+
struct CardColors { uint32_t bg; uint32_t border; uint32_t nameC; uint32_t valueC; };
1518
/*******************************************************************************
1619
* Please configure the touch panel in touch.h
1720
******************************************************************************/
@@ -121,6 +124,18 @@ void initUI() {
121124

122125
lv_scr_load(mainScreen);
123126

127+
// ---- Dark theme ----
128+
lv_disp_t *dispp = lv_disp_get_default();
129+
lv_theme_t *th = lv_theme_default_init(dispp,
130+
lv_color_hex(0x33bdef) /* primary (cyan) */, lv_color_hex(0xc23a30) /* secondary (red) */,
131+
true /* dark */, LV_FONT_DEFAULT);
132+
lv_disp_set_theme(dispp, th);
133+
// Slate page background on both screens
134+
lv_obj_set_style_bg_color(mainScreen, lv_color_hex(0x0f1620), LV_PART_MAIN);
135+
lv_obj_set_style_bg_opa(mainScreen, LV_OPA_COVER, LV_PART_MAIN);
136+
lv_obj_set_style_bg_color(sensorBasedControlPanel, lv_color_hex(0x0f1620), LV_PART_MAIN);
137+
lv_obj_set_style_bg_opa(sensorBasedControlPanel, LV_OPA_COVER, LV_PART_MAIN);
138+
124139
// style for button panel
125140
lv_style_init(&style);
126141
lv_style_set_flex_flow(&style, LV_FLEX_FLOW_ROW_WRAP);
@@ -143,8 +158,12 @@ void initUI() {
143158
lv_style_set_pad_bottom(&styleNoPadding, 0);
144159
lv_style_set_pad_left(&styleNoPadding, 0);
145160
lv_style_set_pad_right(&styleNoPadding, 0);
146-
lv_style_set_pad_row(&styleNoPadding, 0);
147-
lv_style_set_pad_column(&styleNoPadding, 0);
161+
lv_style_set_pad_row(&styleNoPadding, 6);
162+
lv_style_set_pad_column(&styleNoPadding, 6);
163+
// transparent, borderless containers (let the slate page show through)
164+
lv_style_set_bg_opa(&styleNoPadding, LV_OPA_TRANSP);
165+
lv_style_set_border_width(&styleNoPadding, 0);
166+
lv_style_set_radius(&styleNoPadding, 0);
148167
// requires enabling this font in lv_conf.h
149168
lv_style_set_text_font(&styleNoPadding, &lv_font_montserrat_24);
150169

@@ -187,6 +206,8 @@ void initUI() {
187206
TRACE("UI 2");
188207
bannerLabel = lv_label_create(top_thing);
189208
lv_label_set_long_mode(bannerLabel, LV_LABEL_LONG_WRAP); /*Break the long lines*/
209+
lv_label_set_recolor(bannerLabel, true); /*allow #RRGGBB inline colour*/
210+
lv_obj_set_style_text_font(bannerLabel, &lv_font_montserrat_24, LV_PART_MAIN);
190211
TRACE("UI 2.1");
191212
lv_label_set_text(bannerLabel, "Connecting");
192213
TRACE("UI 2.2");
@@ -482,8 +503,8 @@ void updateStatusBar(unsigned long frequency) {
482503

483504
// LVGL's printf has float formatting disabled (LV_SPRINTF_USE_FLOAT 0), so build
484505
// the string with the standard library's snprintf (which supports %f) instead.
485-
char banner[48];
486-
snprintf(banner, sizeof(banner), "%s @%.1f%c ", lastServerStatus->server_name,
506+
char banner[72];
507+
snprintf(banner, sizeof(banner), "#8fa6b6 %s# #33bdef %.1f%c#", lastServerStatus->server_name,
487508
toDisplayTemp(lastServerStatus->water_temp), displayUnitChar());
488509
lv_label_set_text(bannerLabel, banner);
489510

@@ -543,6 +564,23 @@ void dataReceivedControlStatus(struct_status_control *status) {
543564

544565
}
545566

567+
// Card colours by control state (dark theme). e_value = getOnState (0/1/2).
568+
static CardColors cardColorsFor(struct_status_control *s) {
569+
const uint32_t OFF_BG = 0x1a2431, OFF_BD = 0x2c3a4d, OFF_NAME = 0xc7d5e2, OFF_VAL = 0x5f7183;
570+
if (strcmp(s->type, "sensor-based") == 0) {
571+
bool heating = s->e_value > 0;
572+
return { 0x1a2431, (uint32_t)(heating ? 0x5a3420 : 0x3a2a1e), 0xc7d5e2, 0xff7a45 };
573+
}
574+
if (strcmp(s->type, "off-low-high") == 0) {
575+
if (s->e_value == 1) return { 0xe0952b, 0xe0952b, 0xffffff, 0xffffff }; // LOW (amber)
576+
if (s->e_value >= 2) return { 0xe0652b, 0xe0652b, 0xffffff, 0xffffff }; // HIGH (orange)
577+
return { OFF_BG, OFF_BD, OFF_NAME, OFF_VAL };
578+
}
579+
// off-on
580+
if (s->e_value > 0) return { 0xc23a30, 0xc23a30, 0xffffff, 0xffffff }; // ON (red)
581+
return { OFF_BG, OFF_BD, OFF_NAME, OFF_VAL }; // OFF
582+
}
583+
546584
void updateButtons(unsigned long frequency) {
547585
static unsigned long last_update = 0;
548586
if ((millis() - last_update) > frequency) {
@@ -563,41 +601,30 @@ void updateButtons(unsigned long frequency) {
563601
//TRACE("Update Buttons 2.04");
564602

565603
lv_obj_t *btn = lv_btn_create(singleControlContainer);
566-
//TRACE("Update Buttons 2.1");
567-
lv_obj_set_size(btn, 220, 68);
604+
lv_obj_set_size(btn, 150, 82);
568605
lv_obj_align(btn, LV_ALIGN_BOTTOM_MID, 0, 0);
569-
//TRACE("Update Buttons 2.2");
570-
lv_obj_add_event_cb(btn, btn_event_cb, LV_EVENT_CLICKED,
571-
controlStatuses[i]);
572-
lv_obj_set_style_border_width(btn, 3, LV_PART_MAIN | LV_STATE_DEFAULT);
573-
// TRACE("Update Buttons 2.3");
574-
606+
lv_obj_add_event_cb(btn, btn_event_cb, LV_EVENT_CLICKED, controlStatuses[i]);
607+
lv_obj_set_style_radius(btn, 14, LV_PART_MAIN);
608+
lv_obj_set_style_border_width(btn, 1, LV_PART_MAIN | LV_STATE_DEFAULT);
609+
lv_obj_set_style_shadow_width(btn, 0, LV_PART_MAIN);
610+
lv_obj_set_style_pad_all(btn, 11, LV_PART_MAIN);
575611

612+
// child 0: name (top-left)
576613
lv_obj_t *label = lv_label_create(btn);
577-
lv_obj_align(label, LV_ALIGN_TOP_MID, 0, 0);
578-
//TRACE("Update Buttons 2.4");
579-
lv_label_set_text_fmt(label, "%s", controlStatuses[i]->name);
580-
//TRACE("Update Buttons 2.5");
581-
lv_obj_center(label);
582-
// TRACE("Update Buttons 3");
614+
lv_obj_add_style(label, &styleSmallFont, LV_PART_MAIN);
615+
lv_obj_align(label, LV_ALIGN_TOP_LEFT, 0, 0);
616+
lv_label_set_text(label, controlStatuses[i]->name);
583617

618+
// child 1: override-remaining chip (bottom-right, small)
584619
lv_obj_t *labelORT = lv_label_create(btn);
585-
lv_obj_align(labelORT, LV_ALIGN_BOTTOM_LEFT, -10, 5);
586620
lv_obj_add_style(labelORT, &styleSmallFont, LV_PART_MAIN);
587-
// lv_obj_set_style_border_color(labelORT, lv_palette_main(LV_PALETTE_GREY), LV_PART_MAIN);
588-
// lv_obj_set_style_border_width(labelORT, 1, LV_PART_MAIN | LV_STATE_DEFAULT);
589-
lv_obj_set_style_text_color(labelORT, lv_palette_main(LV_PALETTE_ORANGE), LV_PART_MAIN);
590-
lv_obj_set_style_bg_color(labelORT, lv_color_white(), 0);
591-
lv_obj_set_style_bg_opa(labelORT, LV_OPA_50, 0);
592-
// TRACE("Update Buttons 3");
621+
lv_obj_align(labelORT, LV_ALIGN_BOTTOM_RIGHT, 0, 2);
593622

623+
// child 2: value (bottom-left, large)
594624
lv_obj_t *labelValue = lv_label_create(btn);
595-
lv_obj_align(labelValue, LV_ALIGN_TOP_RIGHT, 10, -5);
596-
lv_obj_add_style(labelValue, &styleSmallFont, LV_PART_MAIN);
625+
lv_obj_set_style_text_font(labelValue, &lv_font_montserrat_24, LV_PART_MAIN);
626+
lv_obj_align(labelValue, LV_ALIGN_BOTTOM_LEFT, 0, 0);
597627
lv_label_set_text(labelValue, "");
598-
// lv_obj_set_style_border_color(labelValue, lv_palette_main(LV_PALETTE_GREY), LV_PART_MAIN);
599-
// lv_obj_set_style_border_width(labelValue, 1, LV_PART_MAIN | LV_STATE_DEFAULT);
600-
lv_obj_set_style_text_color(labelValue, lv_palette_main(LV_PALETTE_AMBER), LV_PART_MAIN);
601628

602629
controlButtons.push_back(singleControlContainer);
603630
}
@@ -647,35 +674,26 @@ void updateButtons(unsigned long frequency) {
647674
showStatusMessage("No response for %s", status->name);
648675
}
649676
}
650-
lv_obj_set_style_border_color(
651-
btn,
652-
pending ? lv_color_white() : lv_palette_main(MODE_COLORS[status->e_value]),
653-
LV_PART_MAIN | LV_STATE_DEFAULT
654-
);
677+
CardColors cc = cardColorsFor(status);
678+
lv_obj_set_style_bg_color(btn, lv_color_hex(cc.bg), LV_PART_MAIN);
679+
lv_obj_set_style_bg_opa(btn, LV_OPA_COVER, LV_PART_MAIN);
680+
lv_obj_set_style_border_color(btn, pending ? lv_color_white() : lv_color_hex(cc.border), LV_PART_MAIN);
681+
lv_obj_set_style_border_width(btn, pending ? 3 : 1, LV_PART_MAIN);
682+
lv_obj_set_style_text_color(label, lv_color_hex(cc.nameC), LV_PART_MAIN);
683+
lv_obj_set_style_text_color(labelValue, lv_color_hex(cc.valueC), LV_PART_MAIN);
684+
lv_obj_set_style_text_color(labelORT, lv_color_hex(cc.valueC), LV_PART_MAIN);
655685
//TRACE("Update Buttons 5.2");
656686

657687

658688
if (strcmp(status->type, "off-low-high") == 0) {
659-
if (status->e_value > 0) {
660-
// TRACE("Update Buttons 5.4");
661-
// lv_label_set_text_fmt(label, "%s (%s)", status->name, status->e_value == 1 ? "LOW" : "HIGH");
662-
lv_label_set_text(labelValue, status->e_value == 1 ? "LOW" : "HIGH");
663-
lv_obj_clear_flag(labelValue, LV_OBJ_FLAG_HIDDEN);
664-
} else {
665-
lv_label_set_text(labelValue, "OFF");
666-
if (status->ORT <= 0) { // if we're in override, show "OFF"
667-
lv_obj_add_flag(labelValue, LV_OBJ_FLAG_HIDDEN);
668-
}
669-
}
670-
// TRACE("Update Buttons 5.5");
671-
// lv_led_set_color(led, lv_palette_main(status->e_value == 1 ? LV_PALETTE_RED : LV_PALETTE_YELLOW));
672-
689+
lv_label_set_text(labelValue, status->e_value == 0 ? "OFF" : (status->e_value == 1 ? "LOW" : "HIGH"));
673690
} else if (strcmp(status->type, "sensor-based") == 0) {
674-
// lv_label_set_text_fmt(label, "%s (%d)", status->name, status->value);
675691
lv_label_set_text_fmt(labelValue, "%d%c", (int)lroundf(toDisplayTemp((float)status->value)), displayUnitChar());
676692
} else {
677-
lv_label_set_text(label, status->name);
693+
// off-on
694+
lv_label_set_text(labelValue, status->e_value > 0 ? "ON" : "OFF");
678695
}
696+
lv_obj_clear_flag(labelValue, LV_OBJ_FLAG_HIDDEN);
679697
}
680698
// TRACE("Update Buttons 6");
681699
}

0 commit comments

Comments
 (0)