feat(P4): Vier neue Dashboard-Darstellungen (1.8.0)
Ersetzt die bisherigen fünf (Klassisch, Instrumente, Minimal, Soft-3D, Thermometer) durch vier, die nicht nur den Temperaturbereich anders zeichnen, sondern die Fläche unterschiedlich nutzen: - Gewichtet: Wasser mit flex-grow 2, Dampf mit 1. - Verlauf: lv_chart-Sparkline je Kessel, gespeist aus der bestehenden Sekundenabtastung; Ausschnitt am Sollwert ausgerichtet. - Flächen: ohne Kartenkanten, zwei Felder mit leicht verschiedenem Grund. - Band: Zustandsband über volle Breite (bereit / heizt / Bezug / Cold Extraction / Standby). Neue Vorgabe. Zwei neue Schriftgrade (96 und 140 px), erzeugt mit lv_font_conv aus MavenPro-Regular.ttf, beschränkt auf Ziffern, Komma, Punkt, Minus und Gradzeichen - die größte Textschrift hatte 48 px und reichte für die großen Zahlen nicht. Ein gespeicherter Wert außerhalb des neuen Bereichs fällt auf die Vorgabe zurück. Die fünf alten Builder sind entfernt. Beide Panel-Varianten mit arduino-cli gegengebaut. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
bcd9ecf0c8
commit
ca3a9c1264
@@ -1,3 +1,25 @@
|
||||
Version 1.8.0:
|
||||
- Das Dashboard hat vier neue Darstellungen, die die bisherigen fünf ersetzen. Sie sind
|
||||
keine Varianten desselben Bildes, sondern vier Antworten auf die Frage, was die große
|
||||
Fläche des 7-Zöllers leisten soll:
|
||||
* Gewichtet - Wasser bekommt zwei Drittel der Fläche, Dampf ein Drittel. Beim Espresso
|
||||
zählt die Wassertemperatur; die Asymmetrie ist die Aussage.
|
||||
* Verlauf - unter jeder Temperatur eine flache Kurve der letzten Minute. Die eigentliche
|
||||
Frage an eine PID-Regelung ist nicht „wie warm", sondern „hält sie" - und das kann eine
|
||||
Zahl grundsätzlich nicht zeigen. Der Ausschnitt hängt am Sollwert, damit die Abweichung
|
||||
sichtbar wird statt in der Skala unterzugehen.
|
||||
* Flächen - keine Kartenkanten, zwei Felder mit einem Hauch Helligkeitsunterschied.
|
||||
* Band - ein farbiges Band über die volle Breite sagt den Zustand, bevor eine Zahl
|
||||
gelesen wird: bereit, heizt, Bezug, Cold Extraction oder Standby. Neue Vorgabe.
|
||||
- Dafür gibt es zwei neue Schriftgrade (96 und 140 Pixel). Sie enthalten nur Ziffern,
|
||||
Komma, Punkt, Minus und Gradzeichen - mit vollem Zeichensatz wären sie um ein Vielfaches
|
||||
größer, ohne etwas beizutragen. Die größte Textschrift hatte bisher 48 Pixel, was für die
|
||||
großen Zahlen nicht reichte.
|
||||
- Ältere Stände haben in den Einstellungen noch die Nummer einer der früheren Darstellungen
|
||||
gespeichert; liegt sie außerhalb, fällt sie auf die Vorgabe zurück.
|
||||
- Der Aufbau der Bezugsanzeige - untere Zeile wechselt während eines Bezugs auf große
|
||||
Timer- und Gewichtsanzeige - folgt als nächster Schritt.
|
||||
|
||||
Version 1.7.3:
|
||||
- Die Schriftgröße steht jetzt auf der Info-Seite im Abschnitt „Darstellung", zusammen mit
|
||||
der Wahl der Temperaturanzeige und dem Live-Bezugsschirm. Dort gehört sie hin: Es ist
|
||||
|
||||
@@ -567,6 +567,8 @@
|
||||
LV_FONT_DECLARE(lv_font_maven_pro_28) \
|
||||
LV_FONT_DECLARE(lv_font_maven_pro_40) \
|
||||
LV_FONT_DECLARE(lv_font_maven_pro_48) \
|
||||
LV_FONT_DECLARE(lv_font_maven_pro_96) \
|
||||
LV_FONT_DECLARE(lv_font_maven_pro_140) \
|
||||
LV_FONT_DECLARE(lv_font_clock_240)
|
||||
|
||||
/*Always set a default font*/
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
+200
-303
@@ -166,8 +166,15 @@ static void label_set_if_changed(lv_obj_t* lbl, const char* txt); // Definitio
|
||||
// TD_MINIMAL - rahmenlos, nur grosse Werte mit duenner Ist/Soll-Linie
|
||||
// TD_NEO - Soft-3D/Neumorph: Flaeche wirkt aus dem Hintergrund herausgedrueckt
|
||||
// TD_THERMO - vertikale Thermometer-Saeulen mit Kolben und Glanzstreifen
|
||||
enum TempDesign { TD_CARDS = 0, TD_GAUGE, TD_MINIMAL, TD_NEO, TD_THERMO, TD_DESIGN_COUNT };
|
||||
static uint8_t g_tempDesign = TD_GAUGE;
|
||||
enum TempDesign { TD_GEWICHTET = 0, TD_VERLAUF, TD_FLAECHEN, TD_BAND, TD_DESIGN_COUNT };
|
||||
static uint8_t g_tempDesign = TD_BAND;
|
||||
#define DASH_SPARK_POINTS 60 // eine Minute Verlauf, ein Punkt je Sekunde
|
||||
static lv_obj_t* g_sparkW = nullptr; // Verlaufskurven der Darstellung TD_VERLAUF
|
||||
static lv_obj_t* g_sparkD = nullptr;
|
||||
static lv_chart_series_t* g_sparkSerW = nullptr;
|
||||
static lv_chart_series_t* g_sparkSerD = nullptr;
|
||||
static lv_obj_t* g_readyBand = nullptr; // Zustandsband der Darstellung TD_BAND
|
||||
static lv_obj_t* g_readyBandLbl = nullptr;
|
||||
static lv_obj_t* g_tempRow = nullptr; // Container; Inhalt wird je Design (neu) aufgebaut
|
||||
static lv_obj_t* lblTempW; static lv_obj_t* lblSetW; static lv_obj_t* barDutyW; // barDuty*: lv_bar (Karten/Minimal/Neo/Thermo-Saeule)
|
||||
static lv_obj_t* lblTempD; static lv_obj_t* lblSetD; static lv_obj_t* barDutyD;
|
||||
@@ -798,7 +805,7 @@ static void temp_progress_set(lv_obj_t* bar, lv_obj_t* arc, lv_obj_t* bulb, int
|
||||
if (pct > 100) pct = 100; else if (pct < 0) pct = 0;
|
||||
if (bar) {
|
||||
lv_bar_set_value(bar, pct, LV_ANIM_OFF);
|
||||
if (g_tempDesign != TD_CARDS) lv_obj_set_style_bg_color(bar, col, LV_PART_INDICATOR);
|
||||
lv_obj_set_style_bg_color(bar, col, LV_PART_INDICATOR);
|
||||
}
|
||||
if (arc) {
|
||||
lv_arc_set_value(arc, pct);
|
||||
@@ -806,298 +813,91 @@ static void temp_progress_set(lv_obj_t* bar, lv_obj_t* arc, lv_obj_t* bulb, int
|
||||
}
|
||||
if (bulb) lv_obj_set_style_bg_color(bulb, col, 0);
|
||||
}
|
||||
static void tempCard(lv_obj_t* parent, const char* title, lv_color_t accent,
|
||||
lv_obj_t** big, lv_obj_t** setp, lv_obj_t** bar) {
|
||||
lv_obj_t* card = th_card(parent);
|
||||
lv_obj_set_size(card, LV_PCT(49), LV_PCT(100));
|
||||
lv_obj_set_flex_flow(card, LV_FLEX_FLOW_COLUMN);
|
||||
lv_obj_set_flex_align(card, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
|
||||
lv_obj_clear_flag(card, LV_OBJ_FLAG_SCROLLABLE);
|
||||
lv_obj_add_flag(card, LV_OBJ_FLAG_CLICKABLE); // antippbar -> Temperatur-Seite
|
||||
lv_obj_add_event_cb(card, temp_card_cb, LV_EVENT_CLICKED, nullptr);
|
||||
lv_obj_t* t = lv_label_create(card);
|
||||
lv_label_set_text(t, title);
|
||||
lv_obj_set_style_text_color(t, accent, 0);
|
||||
lv_obj_set_style_text_font(t, font_text(), 0);
|
||||
*big = lv_label_create(card);
|
||||
lv_label_set_text(*big, "--.-");
|
||||
lv_obj_set_style_text_color(*big, COL_TEXT, 0);
|
||||
lv_obj_set_style_text_font(*big, &lv_font_maven_pro_48, 0);
|
||||
*setp = lv_label_create(card);
|
||||
lv_label_set_text(*setp, "Soll --.-");
|
||||
lv_obj_set_style_text_color(*setp, COL_TEXT_DIM, 0);
|
||||
lv_obj_set_style_text_font(*setp, font_text(), 0);
|
||||
*bar = lv_bar_create(card);
|
||||
lv_obj_set_size(*bar, LV_PCT(92), 12);
|
||||
lv_obj_set_style_bg_color(*bar, lv_color_hex(0x3a3a3a), 0); // sichtbarer Track (auch bei 0 %)
|
||||
lv_obj_set_style_bg_opa(*bar, LV_OPA_COVER, 0);
|
||||
lv_obj_set_style_border_color(*bar, COL_BORDER, 0);
|
||||
lv_obj_set_style_border_width(*bar, 1, 0);
|
||||
lv_obj_set_style_radius(*bar, 6, 0);
|
||||
lv_obj_set_style_bg_color(*bar, accent, LV_PART_INDICATOR);
|
||||
lv_obj_set_style_radius(*bar, 6, LV_PART_INDICATOR);
|
||||
lv_bar_set_range(*bar, 0, 100);
|
||||
lv_bar_set_value(*bar, 0, LV_ANIM_OFF);
|
||||
}
|
||||
// Rundinstrument im Manometer-Look (Design TD_GAUGE): freistehend ohne Kartenrahmen.
|
||||
// Leichte 3D-Wirkung ueber einen "Metall"-Bezel (vertikaler Verlauf hell -> dunkel) mit
|
||||
// weichem Schlagschatten und ein leicht aufgehelltes Zifferblatt darunter. Der 270-Grad-
|
||||
// Bogen zeigt Ist/Soll in % und faerbt sich mit der Zustandsfarbe des Ist-Werts.
|
||||
static void tempGauge(lv_obj_t* parent, const char* title, lv_color_t accent,
|
||||
lv_obj_t** big, lv_obj_t** setp, lv_obj_t** arc) {
|
||||
lv_obj_t* holder = lv_obj_create(parent);
|
||||
lv_obj_set_size(holder, LV_PCT(49), LV_PCT(100));
|
||||
lv_obj_set_style_bg_opa(holder, LV_OPA_TRANSP, 0);
|
||||
lv_obj_set_style_border_width(holder, 0, 0);
|
||||
lv_obj_set_style_pad_all(holder, 0, 0);
|
||||
lv_obj_clear_flag(holder, LV_OBJ_FLAG_SCROLLABLE);
|
||||
lv_obj_add_flag(holder, LV_OBJ_FLAG_CLICKABLE); // antippbar -> Temperatur-Seite
|
||||
lv_obj_add_event_cb(holder, temp_card_cb, LV_EVENT_CLICKED, nullptr);
|
||||
// ------------------------------------------------------------------------------------
|
||||
// Temperaturbereich des Dashboards - vier Darstellungen
|
||||
//
|
||||
// Gemeinsam ist allen: zwei Kessel, die Zahl ist das Erste, was man sieht. Unterschiedlich
|
||||
// ist, was die Flaeche zusaetzlich leistet.
|
||||
//
|
||||
// Die grossen Zahlen brauchen Schriftgrade, die es vorher nicht gab (96 und 140 Pixel).
|
||||
// Diese beiden Schriften enthalten nur Ziffern, Komma, Punkt, Minus und Gradzeichen - mit
|
||||
// vollem Zeichensatz waeren sie um ein Vielfaches groesser, ohne etwas beizutragen.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
// Bezel-Ring: Verlauf von hell (oben) nach dunkel (unten) + Schatten = Metall-Optik
|
||||
lv_obj_t* bezel = lv_obj_create(holder);
|
||||
lv_obj_set_size(bezel, 188, 188);
|
||||
lv_obj_center(bezel);
|
||||
lv_obj_set_style_radius(bezel, LV_RADIUS_CIRCLE, 0);
|
||||
lv_obj_set_style_bg_color(bezel, lv_color_hex(0x5c5c5c), 0);
|
||||
lv_obj_set_style_bg_grad_color(bezel, lv_color_hex(0x141414), 0);
|
||||
lv_obj_set_style_bg_grad_dir(bezel, LV_GRAD_DIR_VER, 0);
|
||||
lv_obj_set_style_border_width(bezel, 0, 0);
|
||||
lv_obj_set_style_pad_all(bezel, 0, 0);
|
||||
lv_obj_set_style_shadow_width(bezel, 16, 0);
|
||||
lv_obj_set_style_shadow_offset_y(bezel, 5, 0);
|
||||
lv_obj_set_style_shadow_color(bezel, lv_color_hex(0x000000), 0);
|
||||
lv_obj_set_style_shadow_opa(bezel, LV_OPA_60, 0);
|
||||
lv_obj_clear_flag(bezel, LV_OBJ_FLAG_SCROLLABLE);
|
||||
lv_obj_clear_flag(bezel, LV_OBJ_FLAG_CLICKABLE); // Tipp faellt zum Holder durch
|
||||
// Ein Kesselfeld. 'grow' verteilt die Breite zwischen den beiden, 'valueFont' bestimmt die
|
||||
// Groesse der Zahl, 'flat' laesst den Kartenrahmen weg und faerbt stattdessen die Flaeche.
|
||||
static lv_obj_t* tempField(lv_obj_t* parent, const char* title, lv_color_t accent,
|
||||
lv_obj_t** big, lv_obj_t** setp, lv_obj_t** bar,
|
||||
uint8_t grow, const lv_font_t* valueFont,
|
||||
bool flat, uint32_t flatBg) {
|
||||
lv_obj_t* c;
|
||||
if (flat) {
|
||||
c = lv_obj_create(parent);
|
||||
lv_obj_set_style_bg_color(c, lv_color_hex(flatBg), 0);
|
||||
lv_obj_set_style_bg_opa(c, LV_OPA_COVER, 0);
|
||||
lv_obj_set_style_border_width(c, 0, 0);
|
||||
lv_obj_set_style_radius(c, 0, 0);
|
||||
lv_obj_set_style_pad_all(c, 14, 0);
|
||||
} else {
|
||||
c = th_card(parent);
|
||||
lv_obj_set_style_pad_all(c, 12, 0);
|
||||
}
|
||||
lv_obj_set_height(c, LV_PCT(100));
|
||||
lv_obj_set_flex_grow(c, grow);
|
||||
lv_obj_set_flex_flow(c, LV_FLEX_FLOW_COLUMN);
|
||||
lv_obj_set_flex_align(c, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
|
||||
lv_obj_clear_flag(c, LV_OBJ_FLAG_SCROLLABLE);
|
||||
lv_obj_add_flag(c, LV_OBJ_FLAG_CLICKABLE); // antippbar -> Temperatur-Seite
|
||||
lv_obj_add_event_cb(c, temp_card_cb, LV_EVENT_CLICKED, nullptr);
|
||||
|
||||
// Zifferblatt: leicht "vertieft" (Verlauf dunkel oben -> etwas heller unten)
|
||||
lv_obj_t* face = lv_obj_create(bezel);
|
||||
lv_obj_set_size(face, 174, 174);
|
||||
lv_obj_center(face);
|
||||
lv_obj_set_style_radius(face, LV_RADIUS_CIRCLE, 0);
|
||||
lv_obj_set_style_bg_color(face, lv_color_hex(0x0c0c0c), 0);
|
||||
lv_obj_set_style_bg_grad_color(face, lv_color_hex(0x232323), 0);
|
||||
lv_obj_set_style_bg_grad_dir(face, LV_GRAD_DIR_VER, 0);
|
||||
lv_obj_set_style_border_width(face, 0, 0);
|
||||
lv_obj_set_style_pad_all(face, 0, 0);
|
||||
lv_obj_clear_flag(face, LV_OBJ_FLAG_SCROLLABLE);
|
||||
lv_obj_clear_flag(face, LV_OBJ_FLAG_CLICKABLE);
|
||||
|
||||
// 270-Grad-Bogen (Luecke unten): reine Anzeige, kein Griff, nicht bedienbar
|
||||
*arc = lv_arc_create(face);
|
||||
lv_obj_set_size(*arc, 158, 158);
|
||||
lv_obj_center(*arc);
|
||||
lv_arc_set_rotation(*arc, 135);
|
||||
lv_arc_set_bg_angles(*arc, 0, 270);
|
||||
lv_arc_set_range(*arc, 0, 100);
|
||||
lv_arc_set_value(*arc, 0);
|
||||
lv_obj_remove_style(*arc, nullptr, LV_PART_KNOB);
|
||||
lv_obj_clear_flag(*arc, LV_OBJ_FLAG_CLICKABLE);
|
||||
lv_obj_set_style_arc_width(*arc, 12, LV_PART_MAIN);
|
||||
lv_obj_set_style_arc_color(*arc, lv_color_hex(0x2e2e2e), LV_PART_MAIN);
|
||||
lv_obj_set_style_arc_width(*arc, 12, LV_PART_INDICATOR);
|
||||
lv_obj_set_style_arc_color(*arc, accent, LV_PART_INDICATOR);
|
||||
lv_obj_set_style_arc_rounded(*arc, true, LV_PART_INDICATOR);
|
||||
|
||||
lv_obj_t* t = lv_label_create(face);
|
||||
lv_obj_t* t = lv_label_create(c);
|
||||
lv_label_set_text(t, title);
|
||||
lv_obj_set_style_text_color(t, accent, 0);
|
||||
lv_obj_set_style_text_font(t, font_small(), 0);
|
||||
lv_obj_align(t, LV_ALIGN_CENTER, 0, -48);
|
||||
*big = lv_label_create(face);
|
||||
|
||||
*big = lv_label_create(c);
|
||||
lv_label_set_text(*big, "--.-");
|
||||
lv_obj_set_style_text_color(*big, COL_TEXT, 0);
|
||||
lv_obj_set_style_text_font(*big, &lv_font_maven_pro_40, 0);
|
||||
lv_obj_align(*big, LV_ALIGN_CENTER, 0, -2);
|
||||
// Soll-Wert sitzt in der Bogen-Luecke unten (dort ist die volle Breite frei)
|
||||
*setp = lv_label_create(face);
|
||||
lv_label_set_text(*setp, "Soll --.-");
|
||||
lv_obj_set_style_text_color(*setp, COL_TEXT_DIM, 0);
|
||||
lv_obj_set_style_text_font(*setp, font_small(), 0);
|
||||
lv_obj_align(*setp, LV_ALIGN_CENTER, 0, 62);
|
||||
}
|
||||
// Minimal-Design (TD_MINIMAL): komplett rahmenlos - nur grosser Ist-Wert in der
|
||||
// Zustandsfarbe, darunter eine duenne Ist/Soll-Linie und der Soll-Wert. Sehr ruhig.
|
||||
static void tempMinimal(lv_obj_t* parent, const char* title, lv_color_t accent,
|
||||
lv_obj_t** big, lv_obj_t** setp, lv_obj_t** bar) {
|
||||
lv_obj_t* holder = lv_obj_create(parent);
|
||||
lv_obj_set_size(holder, LV_PCT(49), LV_PCT(100));
|
||||
lv_obj_set_style_bg_opa(holder, LV_OPA_TRANSP, 0);
|
||||
lv_obj_set_style_border_width(holder, 0, 0);
|
||||
lv_obj_set_style_pad_all(holder, 0, 0);
|
||||
lv_obj_set_style_pad_row(holder, 10, 0);
|
||||
lv_obj_set_flex_flow(holder, LV_FLEX_FLOW_COLUMN);
|
||||
lv_obj_set_flex_align(holder, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
|
||||
lv_obj_clear_flag(holder, LV_OBJ_FLAG_SCROLLABLE);
|
||||
lv_obj_add_flag(holder, LV_OBJ_FLAG_CLICKABLE); // antippbar -> Temperatur-Seite
|
||||
lv_obj_add_event_cb(holder, temp_card_cb, LV_EVENT_CLICKED, nullptr);
|
||||
lv_obj_t* t = lv_label_create(holder);
|
||||
lv_label_set_text(t, title);
|
||||
lv_obj_set_style_text_color(t, accent, 0);
|
||||
lv_obj_set_style_text_font(t, font_text(), 0);
|
||||
*big = lv_label_create(holder);
|
||||
lv_label_set_text(*big, "--.-");
|
||||
lv_obj_set_style_text_color(*big, COL_TEXT, 0);
|
||||
lv_obj_set_style_text_font(*big, &lv_font_maven_pro_48, 0);
|
||||
*bar = lv_bar_create(holder); // duenne Ist/Soll-Linie
|
||||
lv_obj_set_size(*bar, LV_PCT(64), 4);
|
||||
lv_obj_set_style_bg_color(*bar, lv_color_hex(0x2a2a2a), 0);
|
||||
lv_obj_set_style_bg_opa(*bar, LV_OPA_COVER, 0);
|
||||
lv_obj_set_style_border_width(*bar, 0, 0);
|
||||
lv_obj_set_style_radius(*bar, 2, 0);
|
||||
lv_obj_set_style_bg_color(*bar, accent, LV_PART_INDICATOR); // folgt spaeter der Zustandsfarbe
|
||||
lv_obj_set_style_radius(*bar, 2, LV_PART_INDICATOR);
|
||||
lv_bar_set_range(*bar, 0, 100);
|
||||
lv_bar_set_value(*bar, 0, LV_ANIM_OFF);
|
||||
*setp = lv_label_create(holder);
|
||||
lv_obj_set_style_text_font(*big, valueFont, 0);
|
||||
|
||||
*setp = lv_label_create(c);
|
||||
lv_label_set_text(*setp, "Soll --.-");
|
||||
lv_obj_set_style_text_color(*setp, COL_TEXT_DIM, 0);
|
||||
lv_obj_set_style_text_font(*setp, font_text(), 0);
|
||||
}
|
||||
// Soft-3D/Neumorph (TD_NEO): Flaeche fast im Hintergrundton, wirkt herausgedrueckt.
|
||||
// LVGL kann nur einen Schatten je Objekt, daher zwei verschachtelte Objekte:
|
||||
// aussen dunkler Schatten unten rechts, innen heller "Lichtschein" oben links.
|
||||
static void tempNeo(lv_obj_t* parent, const char* title, lv_color_t accent,
|
||||
lv_obj_t** big, lv_obj_t** setp, lv_obj_t** bar) {
|
||||
lv_obj_t* shell = lv_obj_create(parent);
|
||||
lv_obj_set_size(shell, LV_PCT(48), LV_PCT(100));
|
||||
lv_obj_set_style_radius(shell, 20, 0);
|
||||
lv_obj_set_style_bg_color(shell, lv_color_hex(0x171717), 0);
|
||||
lv_obj_set_style_bg_opa(shell, LV_OPA_COVER, 0);
|
||||
lv_obj_set_style_border_width(shell, 0, 0);
|
||||
lv_obj_set_style_pad_all(shell, 0, 0);
|
||||
lv_obj_set_style_shadow_width(shell, 14, 0);
|
||||
lv_obj_set_style_shadow_offset_x(shell, 6, 0);
|
||||
lv_obj_set_style_shadow_offset_y(shell, 6, 0);
|
||||
lv_obj_set_style_shadow_color(shell, lv_color_hex(0x000000), 0);
|
||||
lv_obj_set_style_shadow_opa(shell, LV_OPA_70, 0);
|
||||
lv_obj_clear_flag(shell, LV_OBJ_FLAG_SCROLLABLE);
|
||||
lv_obj_add_flag(shell, LV_OBJ_FLAG_CLICKABLE); // antippbar -> Temperatur-Seite
|
||||
lv_obj_add_event_cb(shell, temp_card_cb, LV_EVENT_CLICKED, nullptr);
|
||||
|
||||
lv_obj_t* inner = lv_obj_create(shell);
|
||||
lv_obj_set_size(inner, LV_PCT(100), LV_PCT(100));
|
||||
lv_obj_set_style_radius(inner, 20, 0);
|
||||
lv_obj_set_style_bg_color(inner, lv_color_hex(0x1e1e1e), 0); // leicht gewoelbt: oben etwas heller
|
||||
lv_obj_set_style_bg_grad_color(inner, lv_color_hex(0x121212), 0);
|
||||
lv_obj_set_style_bg_grad_dir(inner, LV_GRAD_DIR_VER, 0);
|
||||
lv_obj_set_style_border_width(inner, 0, 0);
|
||||
lv_obj_set_style_shadow_width(inner, 14, 0);
|
||||
lv_obj_set_style_shadow_offset_x(inner, -6, 0);
|
||||
lv_obj_set_style_shadow_offset_y(inner, -6, 0);
|
||||
lv_obj_set_style_shadow_color(inner, lv_color_hex(0x3c3c3c), 0);
|
||||
lv_obj_set_style_shadow_opa(inner, LV_OPA_50, 0);
|
||||
lv_obj_set_style_pad_row(inner, 8, 0);
|
||||
lv_obj_set_flex_flow(inner, LV_FLEX_FLOW_COLUMN);
|
||||
lv_obj_set_flex_align(inner, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
|
||||
lv_obj_clear_flag(inner, LV_OBJ_FLAG_SCROLLABLE);
|
||||
lv_obj_clear_flag(inner, LV_OBJ_FLAG_CLICKABLE); // Tipp faellt zur Shell durch
|
||||
|
||||
lv_obj_t* t = lv_label_create(inner);
|
||||
lv_label_set_text(t, title);
|
||||
lv_obj_set_style_text_color(t, accent, 0);
|
||||
lv_obj_set_style_text_font(t, font_text(), 0);
|
||||
*big = lv_label_create(inner);
|
||||
lv_label_set_text(*big, "--.-");
|
||||
lv_obj_set_style_text_color(*big, COL_TEXT, 0);
|
||||
lv_obj_set_style_text_font(*big, &lv_font_maven_pro_48, 0);
|
||||
*setp = lv_label_create(inner);
|
||||
lv_label_set_text(*setp, "Soll --.-");
|
||||
lv_obj_set_style_text_color(*setp, COL_TEXT_DIM, 0);
|
||||
lv_obj_set_style_text_font(*setp, font_text(), 0);
|
||||
*bar = lv_bar_create(inner); // "eingelassener" Balken: Track dunkler als Flaeche
|
||||
lv_obj_set_size(*bar, LV_PCT(78), 10);
|
||||
lv_obj_set_style_bg_color(*bar, lv_color_hex(0x0a0a0a), 0);
|
||||
*bar = lv_bar_create(c);
|
||||
lv_obj_set_size(*bar, LV_PCT(92), 8);
|
||||
lv_obj_set_style_bg_color(*bar, lv_color_hex(0x2c2c2c), 0);
|
||||
lv_obj_set_style_bg_opa(*bar, LV_OPA_COVER, 0);
|
||||
lv_obj_set_style_border_width(*bar, 0, 0);
|
||||
lv_obj_set_style_radius(*bar, 5, 0);
|
||||
lv_obj_set_style_bg_color(*bar, accent, LV_PART_INDICATOR); // folgt spaeter der Zustandsfarbe
|
||||
lv_obj_set_style_radius(*bar, 5, LV_PART_INDICATOR);
|
||||
lv_obj_set_style_radius(*bar, 4, 0);
|
||||
lv_obj_set_style_bg_color(*bar, accent, LV_PART_INDICATOR);
|
||||
lv_obj_set_style_radius(*bar, 4, LV_PART_INDICATOR);
|
||||
lv_bar_set_range(*bar, 0, 100);
|
||||
lv_bar_set_value(*bar, 0, LV_ANIM_OFF);
|
||||
return c;
|
||||
}
|
||||
// Thermometer-Saeulen (TD_THERMO): vertikale Saeule (lv_bar waechst bei Hochformat von
|
||||
// unten), Glanzstreifen als Glas-Effekt, runder Kolben unten - alles rahmenlos.
|
||||
static void tempThermo(lv_obj_t* parent, const char* title, lv_color_t accent,
|
||||
lv_obj_t** big, lv_obj_t** setp, lv_obj_t** bar, lv_obj_t** bulb) {
|
||||
lv_obj_t* holder = lv_obj_create(parent);
|
||||
lv_obj_set_size(holder, LV_PCT(49), LV_PCT(100));
|
||||
lv_obj_set_style_bg_opa(holder, LV_OPA_TRANSP, 0);
|
||||
lv_obj_set_style_border_width(holder, 0, 0);
|
||||
lv_obj_set_style_pad_all(holder, 0, 0);
|
||||
lv_obj_set_style_pad_column(holder, 14, 0);
|
||||
lv_obj_set_flex_flow(holder, LV_FLEX_FLOW_ROW);
|
||||
lv_obj_set_flex_align(holder, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
|
||||
lv_obj_clear_flag(holder, LV_OBJ_FLAG_SCROLLABLE);
|
||||
lv_obj_add_flag(holder, LV_OBJ_FLAG_CLICKABLE); // antippbar -> Temperatur-Seite
|
||||
lv_obj_add_event_cb(holder, temp_card_cb, LV_EVENT_CLICKED, nullptr);
|
||||
|
||||
lv_obj_t* th = lv_obj_create(holder); // Saeule + Kolben (feste Groesse)
|
||||
lv_obj_set_size(th, 48, 190);
|
||||
lv_obj_set_style_bg_opa(th, LV_OPA_TRANSP, 0);
|
||||
lv_obj_set_style_border_width(th, 0, 0);
|
||||
lv_obj_set_style_pad_all(th, 0, 0);
|
||||
lv_obj_clear_flag(th, LV_OBJ_FLAG_SCROLLABLE);
|
||||
lv_obj_clear_flag(th, LV_OBJ_FLAG_CLICKABLE);
|
||||
*bar = lv_bar_create(th); // hochkant -> fuellt sich von unten
|
||||
lv_obj_set_size(*bar, 20, 158);
|
||||
lv_obj_align(*bar, LV_ALIGN_TOP_MID, 0, 0);
|
||||
lv_obj_set_style_bg_color(*bar, lv_color_hex(0x262626), 0);
|
||||
lv_obj_set_style_bg_opa(*bar, LV_OPA_COVER, 0);
|
||||
lv_obj_set_style_border_width(*bar, 0, 0);
|
||||
lv_obj_set_style_radius(*bar, 10, 0);
|
||||
lv_obj_set_style_bg_color(*bar, accent, LV_PART_INDICATOR); // folgt spaeter der Zustandsfarbe
|
||||
lv_obj_set_style_radius(*bar, 10, LV_PART_INDICATOR);
|
||||
lv_bar_set_range(*bar, 0, 100);
|
||||
lv_bar_set_value(*bar, 0, LV_ANIM_OFF);
|
||||
lv_obj_t* gloss = lv_obj_create(th); // Glanzstreifen (Glas-Effekt)
|
||||
lv_obj_set_size(gloss, 4, 138);
|
||||
lv_obj_align(gloss, LV_ALIGN_TOP_MID, -5, 8);
|
||||
lv_obj_set_style_bg_color(gloss, lv_color_hex(0xffffff), 0);
|
||||
lv_obj_set_style_bg_opa(gloss, LV_OPA_20, 0);
|
||||
lv_obj_set_style_border_width(gloss, 0, 0);
|
||||
lv_obj_set_style_radius(gloss, 2, 0);
|
||||
lv_obj_clear_flag(gloss, LV_OBJ_FLAG_SCROLLABLE);
|
||||
lv_obj_clear_flag(gloss, LV_OBJ_FLAG_CLICKABLE);
|
||||
*bulb = lv_obj_create(th); // Kolben (ueberlappt die Saeule leicht)
|
||||
lv_obj_set_size(*bulb, 36, 36);
|
||||
lv_obj_align(*bulb, LV_ALIGN_BOTTOM_MID, 0, 0);
|
||||
lv_obj_set_style_radius(*bulb, LV_RADIUS_CIRCLE, 0);
|
||||
lv_obj_set_style_bg_color(*bulb, accent, 0); // folgt spaeter der Zustandsfarbe
|
||||
lv_obj_set_style_bg_opa(*bulb, LV_OPA_COVER, 0);
|
||||
lv_obj_set_style_border_width(*bulb, 0, 0);
|
||||
lv_obj_set_style_shadow_width(*bulb, 10, 0);
|
||||
lv_obj_set_style_shadow_offset_y(*bulb, 3, 0);
|
||||
lv_obj_set_style_shadow_color(*bulb, lv_color_hex(0x000000), 0);
|
||||
lv_obj_set_style_shadow_opa(*bulb, LV_OPA_40, 0);
|
||||
lv_obj_clear_flag(*bulb, LV_OBJ_FLAG_SCROLLABLE);
|
||||
lv_obj_clear_flag(*bulb, LV_OBJ_FLAG_CLICKABLE);
|
||||
|
||||
lv_obj_t* col = lv_obj_create(holder); // Textspalte neben der Saeule
|
||||
lv_obj_set_size(col, LV_SIZE_CONTENT, LV_SIZE_CONTENT);
|
||||
lv_obj_set_style_bg_opa(col, LV_OPA_TRANSP, 0);
|
||||
lv_obj_set_style_border_width(col, 0, 0);
|
||||
lv_obj_set_style_pad_all(col, 0, 0);
|
||||
lv_obj_set_style_pad_row(col, 6, 0);
|
||||
lv_obj_set_flex_flow(col, LV_FLEX_FLOW_COLUMN);
|
||||
lv_obj_set_flex_align(col, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_CENTER);
|
||||
lv_obj_clear_flag(col, LV_OBJ_FLAG_SCROLLABLE);
|
||||
lv_obj_clear_flag(col, LV_OBJ_FLAG_CLICKABLE);
|
||||
lv_obj_t* t = lv_label_create(col);
|
||||
lv_label_set_text(t, title);
|
||||
lv_obj_set_style_text_color(t, accent, 0);
|
||||
lv_obj_set_style_text_font(t, font_text(), 0);
|
||||
*big = lv_label_create(col);
|
||||
lv_label_set_text(*big, "--.-");
|
||||
lv_obj_set_style_text_color(*big, COL_TEXT, 0);
|
||||
lv_obj_set_style_text_font(*big, &lv_font_maven_pro_48, 0);
|
||||
*setp = lv_label_create(col);
|
||||
lv_label_set_text(*setp, "Soll --.-");
|
||||
lv_obj_set_style_text_color(*setp, COL_TEXT_DIM, 0);
|
||||
lv_obj_set_style_text_font(*setp, font_text(), 0);
|
||||
// Flache Verlaufskurve unter einer Temperatur. Zeigt, ob die Regelung haelt - das ist die
|
||||
// eigentliche Frage an eine PID-Regelung, und eine Zahl kann sie grundsaetzlich nicht
|
||||
// beantworten. Gespeist wird sie aus derselben Sekundenabtastung wie die Verlaufsseite.
|
||||
static lv_obj_t* tempSpark(lv_obj_t* parent, lv_color_t col, lv_chart_series_t** ser) {
|
||||
lv_obj_t* ch = lv_chart_create(parent);
|
||||
lv_obj_set_size(ch, LV_PCT(96), 72);
|
||||
lv_chart_set_type(ch, LV_CHART_TYPE_LINE);
|
||||
lv_chart_set_point_count(ch, DASH_SPARK_POINTS);
|
||||
lv_chart_set_div_line_count(ch, 0, 0);
|
||||
lv_obj_set_style_bg_opa(ch, LV_OPA_TRANSP, 0);
|
||||
lv_obj_set_style_border_width(ch, 0, 0);
|
||||
lv_obj_set_style_pad_all(ch, 0, 0);
|
||||
lv_obj_set_style_size(ch, 0, 0, LV_PART_INDICATOR); // keine Punktmarkierungen
|
||||
lv_obj_set_style_line_width(ch, 3, LV_PART_ITEMS);
|
||||
lv_obj_clear_flag(ch, LV_OBJ_FLAG_SCROLLABLE);
|
||||
*ser = lv_chart_add_series(ch, col, LV_CHART_AXIS_PRIMARY_Y);
|
||||
return ch;
|
||||
}
|
||||
// Temperaturzeile gemaess aktivem Design (neu) befuellen - auch beim Umschalten zur Laufzeit
|
||||
|
||||
// Temperaturbereich gemaess aktiver Darstellung (neu) aufbauen - auch beim Umschalten
|
||||
static void build_temp_row_content() {
|
||||
if (!g_tempRow) return;
|
||||
lv_obj_clean(g_tempRow);
|
||||
@@ -1105,31 +905,81 @@ static void build_temp_row_content() {
|
||||
lblTempD = lblSetD = barDutyD = nullptr;
|
||||
arcTempW = arcTempD = nullptr;
|
||||
bulbTempW = bulbTempD = nullptr;
|
||||
// Nur Soft-3D braucht Innenabstand, damit die weichen Schatten nicht am Rand abgeschnitten werden
|
||||
lv_obj_set_style_pad_hor(g_tempRow, (g_tempDesign == TD_NEO) ? 12 : 0, 0);
|
||||
lv_obj_set_style_pad_ver(g_tempRow, (g_tempDesign == TD_NEO) ? 12 : 0, 0);
|
||||
g_sparkW = g_sparkD = nullptr;
|
||||
g_sparkSerW = g_sparkSerD = nullptr;
|
||||
g_readyBand = g_readyBandLbl = nullptr;
|
||||
|
||||
const lv_color_t teal = lv_color_hex(0x80cbc4);
|
||||
lv_obj_set_style_pad_all(g_tempRow, 0, 0);
|
||||
lv_obj_set_style_pad_column(g_tempRow, 12, 0);
|
||||
lv_obj_set_style_pad_row(g_tempRow, 10, 0);
|
||||
lv_obj_set_flex_flow(g_tempRow, LV_FLEX_FLOW_ROW);
|
||||
|
||||
switch (g_tempDesign) {
|
||||
case TD_GAUGE:
|
||||
tempGauge(g_tempRow, "WASSER", COL_ACCENT, &lblTempW, &lblSetW, &arcTempW);
|
||||
tempGauge(g_tempRow, "DAMPF", teal, &lblTempD, &lblSetD, &arcTempD);
|
||||
break;
|
||||
case TD_MINIMAL:
|
||||
tempMinimal(g_tempRow, "WASSER", COL_ACCENT, &lblTempW, &lblSetW, &barDutyW);
|
||||
tempMinimal(g_tempRow, "DAMPF", teal, &lblTempD, &lblSetD, &barDutyD);
|
||||
break;
|
||||
case TD_NEO:
|
||||
tempNeo(g_tempRow, "WASSER", COL_ACCENT, &lblTempW, &lblSetW, &barDutyW);
|
||||
tempNeo(g_tempRow, "DAMPF", teal, &lblTempD, &lblSetD, &barDutyD);
|
||||
break;
|
||||
case TD_THERMO:
|
||||
tempThermo(g_tempRow, "WASSER", COL_ACCENT, &lblTempW, &lblSetW, &barDutyW, &bulbTempW);
|
||||
tempThermo(g_tempRow, "DAMPF", teal, &lblTempD, &lblSetD, &barDutyD, &bulbTempD);
|
||||
break;
|
||||
default:
|
||||
tempCard(g_tempRow, "WASSER", COL_ACCENT, &lblTempW, &lblSetW, &barDutyW);
|
||||
tempCard(g_tempRow, "DAMPF", teal, &lblTempD, &lblSetD, &barDutyD);
|
||||
break;
|
||||
|
||||
case TD_GEWICHTET: {
|
||||
// Beim Espresso zaehlt die Wassertemperatur; der Dampfkessel ist Nebenwert. Also
|
||||
// zwei Drittel Flaeche fuer Wasser, ein Drittel fuer Dampf - die Asymmetrie ist die
|
||||
// Aussage, nicht ein Versehen.
|
||||
tempField(g_tempRow, "WASSER", COL_ACCENT, &lblTempW, &lblSetW, &barDutyW,
|
||||
2, &lv_font_maven_pro_140, false, 0);
|
||||
tempField(g_tempRow, "DAMPF", teal, &lblTempD, &lblSetD, &barDutyD,
|
||||
1, &lv_font_maven_pro_48, false, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
case TD_VERLAUF: {
|
||||
lv_obj_t* cw = tempField(g_tempRow, "WASSER", COL_ACCENT, &lblTempW, &lblSetW, &barDutyW,
|
||||
1, &lv_font_maven_pro_96, false, 0);
|
||||
g_sparkW = tempSpark(cw, COL_OK, &g_sparkSerW);
|
||||
lv_obj_t* cd = tempField(g_tempRow, "DAMPF", teal, &lblTempD, &lblSetD, &barDutyD,
|
||||
1, &lv_font_maven_pro_96, false, 0);
|
||||
g_sparkD = tempSpark(cd, COL_ACCENT, &g_sparkSerD);
|
||||
break;
|
||||
}
|
||||
|
||||
case TD_FLAECHEN: {
|
||||
// Keine Kartenkanten: Der Bereich ist in zwei Felder geteilt, getrennt nur durch
|
||||
// einen Hauch Helligkeitsunterschied.
|
||||
tempField(g_tempRow, "WASSER", COL_ACCENT, &lblTempW, &lblSetW, &barDutyW,
|
||||
1, &lv_font_maven_pro_140, true, 0x0d0d0d);
|
||||
tempField(g_tempRow, "DAMPF", teal, &lblTempD, &lblSetD, &barDutyD,
|
||||
1, &lv_font_maven_pro_140, true, 0x151515);
|
||||
lv_obj_set_style_pad_column(g_tempRow, 0, 0); // Felder stossen direkt aneinander
|
||||
break;
|
||||
}
|
||||
|
||||
default: { // TD_BAND
|
||||
// Ein farbiges Band ueber die volle Breite sagt den Zustand, bevor man eine Zahl
|
||||
// liest. Deshalb hier eine Spalte: Band oben, darunter die beiden Kessel.
|
||||
lv_obj_set_flex_flow(g_tempRow, LV_FLEX_FLOW_COLUMN);
|
||||
g_readyBand = lv_obj_create(g_tempRow);
|
||||
lv_obj_set_width(g_readyBand, LV_PCT(100));
|
||||
lv_obj_set_height(g_readyBand, 34);
|
||||
lv_obj_set_style_radius(g_readyBand, 8, 0);
|
||||
lv_obj_set_style_border_width(g_readyBand, 0, 0);
|
||||
lv_obj_set_style_pad_all(g_readyBand, 0, 0);
|
||||
lv_obj_clear_flag(g_readyBand, LV_OBJ_FLAG_SCROLLABLE);
|
||||
g_readyBandLbl = lv_label_create(g_readyBand);
|
||||
lv_obj_set_style_text_font(g_readyBandLbl, font_text(), 0);
|
||||
lv_label_set_text(g_readyBandLbl, "");
|
||||
lv_obj_center(g_readyBandLbl);
|
||||
|
||||
lv_obj_t* inner = lv_obj_create(g_tempRow);
|
||||
lv_obj_set_width(inner, LV_PCT(100));
|
||||
lv_obj_set_flex_grow(inner, 1);
|
||||
lv_obj_set_style_bg_opa(inner, LV_OPA_TRANSP, 0);
|
||||
lv_obj_set_style_border_width(inner, 0, 0);
|
||||
lv_obj_set_style_pad_all(inner, 0, 0);
|
||||
lv_obj_set_style_pad_column(inner, 12, 0);
|
||||
lv_obj_set_flex_flow(inner, LV_FLEX_FLOW_ROW);
|
||||
lv_obj_clear_flag(inner, LV_OBJ_FLAG_SCROLLABLE);
|
||||
tempField(inner, "WASSER", COL_ACCENT, &lblTempW, &lblSetW, &barDutyW,
|
||||
1, &lv_font_maven_pro_96, false, 0);
|
||||
tempField(inner, "DAMPF", teal, &lblTempD, &lblSetD, &barDutyD,
|
||||
1, &lv_font_maven_pro_96, false, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
static lv_obj_t* infoCell(lv_obj_t* parent, const char* title, lv_obj_t** val, lv_color_t accent, lv_obj_t** titleOut = nullptr) {
|
||||
@@ -1578,6 +1428,20 @@ static void chart_duty_btn_cb(lv_event_t*) {
|
||||
else lv_obj_add_flag(g_legDuty, LV_OBJ_FLAG_HIDDEN);
|
||||
}
|
||||
chart_redraw();
|
||||
|
||||
// Verlaufskurven des Dashboards (Darstellung "Verlauf") mitfuehren. Der Ausschnitt
|
||||
// haengt am Sollwert, damit die Abweichung sichtbar wird und nicht in der Skala
|
||||
// untergeht - eine feste Skala von 0 bis 130 Grad zeigte nur eine gerade Linie.
|
||||
if (g_sparkSerW && g_sparkW) {
|
||||
int32_t soll = (int32_t)(g_state.setW * 10.0f);
|
||||
lv_chart_set_range(g_sparkW, LV_CHART_AXIS_PRIMARY_Y, soll - 60, soll + 30);
|
||||
lv_chart_set_next_value(g_sparkW, g_sparkSerW, (int32_t)(g_state.tempW * 10.0f));
|
||||
}
|
||||
if (g_sparkSerD && g_sparkD) {
|
||||
int32_t soll = (int32_t)(g_state.setD * 10.0f);
|
||||
lv_chart_set_range(g_sparkD, LV_CHART_AXIS_PRIMARY_Y, soll - 120, soll + 60);
|
||||
lv_chart_set_next_value(g_sparkD, g_sparkSerD, (int32_t)(g_state.tempD * 10.0f));
|
||||
}
|
||||
}
|
||||
static void build_chart(lv_obj_t* p) {
|
||||
lv_obj_clear_flag(p, LV_OBJ_FLAG_SCROLLABLE);
|
||||
@@ -2961,7 +2825,7 @@ static void info_block(lv_obj_t* card, const char* title, lv_obj_t** valOut, con
|
||||
if (valOut) *valOut = v;
|
||||
}
|
||||
// --- Darstellung: Dashboard-Temperaturdesign umschalten (P4-lokal, in NVS gespeichert) ---
|
||||
static const char* TEMP_DESIGN_NAMES[TD_DESIGN_COUNT] = { "Klassisch", "Instrumente", "Minimal", "Soft-3D", "Thermometer" };
|
||||
static const char* TEMP_DESIGN_NAMES[TD_DESIGN_COUNT] = { "Gewichtet", "Verlauf", "Flächen", "Band" };
|
||||
static void design_btns_refresh() {
|
||||
for (int i = 0; i < TD_DESIGN_COUNT; i++) {
|
||||
if (!g_designBtn[i]) continue;
|
||||
@@ -3362,13 +3226,16 @@ void ui_init(ProtocolClient* client) {
|
||||
}
|
||||
|
||||
{ Preferences prefs; prefs.begin("ui", false);
|
||||
g_tempDesign = prefs.getUChar("tempdsgn", TD_GAUGE);
|
||||
// Vorgabe ist jetzt TD_BAND. Aeltere Staende haben hier Werte der frueheren fuenf
|
||||
// Darstellungen stehen - liegt der Wert ausserhalb, faellt er auf die Vorgabe zurueck.
|
||||
g_tempDesign = prefs.getUChar("tempdsgn", TD_BAND);
|
||||
if (g_tempDesign >= TD_DESIGN_COUNT) g_tempDesign = TD_BAND;
|
||||
g_brewLiveEnabled = prefs.getBool("brewlive", true);
|
||||
g_chartWin = prefs.getUChar("chartwin", 0);
|
||||
if (g_chartWin > 3) g_chartWin = 0;
|
||||
g_chartDuty = prefs.getBool("chartduty", false);
|
||||
prefs.end();
|
||||
if (g_tempDesign >= TD_DESIGN_COUNT) g_tempDesign = TD_GAUGE; }
|
||||
}
|
||||
|
||||
font_step_load(); // gewaehlte Schriftgroesse, bevor irgendetwas angelegt wird
|
||||
|
||||
@@ -3765,6 +3632,33 @@ static void appendTuneLive(String& out, const char* kreis, uint32_t elapsedMs,
|
||||
// =====================================================================================
|
||||
// Live-Aktualisierung
|
||||
// =====================================================================================
|
||||
|
||||
// Zustandsband der Darstellung TD_BAND. Es beantwortet die haeufigste Frage - ist sie
|
||||
// bereit? - ohne dass eine Zahl gelesen werden muss.
|
||||
static void ready_band_update(const MachineState& st) {
|
||||
if (!g_readyBand || !g_readyBandLbl) return;
|
||||
const char* txt;
|
||||
uint32_t bg;
|
||||
lv_color_t fg;
|
||||
if (st.standbyActive) {
|
||||
txt = "Standby"; bg = 0x1e1e1e; fg = COL_TEXT_MUT;
|
||||
} else if (st.shotActive) {
|
||||
txt = "Bezug läuft"; bg = 0x3a2a05; fg = COL_ACCENT;
|
||||
} else if (st.cxActive) {
|
||||
txt = "Cold Extraction"; bg = 0x0d2b33; fg = lv_color_hex(0x80cbc4);
|
||||
} else {
|
||||
bool wOk = fabsf(st.tempW - st.setW) <= 1.0f;
|
||||
bool dOk = st.steamHeatDisabled || fabsf(st.tempD - st.setD) <= 3.0f;
|
||||
if (wOk && dOk) { txt = "Bereit — beide Kessel auf Temperatur"; bg = 0x11301a; fg = COL_OK; }
|
||||
else if (wOk) { txt = "Wasser bereit — Dampf heizt"; bg = 0x3a2a05; fg = COL_ACCENT; }
|
||||
else { txt = "Heizt auf"; bg = 0x3a2a05; fg = COL_ACCENT; }
|
||||
}
|
||||
lv_label_set_text(g_readyBandLbl, txt);
|
||||
lv_obj_set_style_text_color(g_readyBandLbl, fg, 0);
|
||||
lv_obj_set_style_bg_color(g_readyBand, lv_color_hex(bg), 0);
|
||||
lv_obj_set_style_bg_opa(g_readyBand, LV_OPA_COVER, 0);
|
||||
}
|
||||
|
||||
void ui_update(const MachineState& st) {
|
||||
if (!g_uiReady) return;
|
||||
|
||||
@@ -4104,6 +3998,9 @@ void ui_update(const MachineState& st) {
|
||||
int pctD = (st.setD > 0.0f) ? (int)(st.tempD / st.setD * 100.0f + 0.5f) : 0;
|
||||
temp_progress_set(barDutyD, arcTempD, bulbTempD, pctD, colD);
|
||||
}
|
||||
ready_band_update(st);
|
||||
if (false) {
|
||||
}
|
||||
}
|
||||
// "BEREIT"-Pille im Header: Wasser im Zielband (und Dampf, sofern er heizt), kein
|
||||
// Fehler/Standby/Eco und kein laufender Aufheiz-Countdown. Mit Hysterese gegen
|
||||
|
||||
Reference in New Issue
Block a user