feat(P4): Vier neue Dashboard-Darstellungen (1.8.0) #60
@@ -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:
|
Version 1.7.3:
|
||||||
- Die Schriftgröße steht jetzt auf der Info-Seite im Abschnitt „Darstellung", zusammen mit
|
- 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
|
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_28) \
|
||||||
LV_FONT_DECLARE(lv_font_maven_pro_40) \
|
LV_FONT_DECLARE(lv_font_maven_pro_40) \
|
||||||
LV_FONT_DECLARE(lv_font_maven_pro_48) \
|
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)
|
LV_FONT_DECLARE(lv_font_clock_240)
|
||||||
|
|
||||||
/*Always set a default font*/
|
/*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
+196
-299
@@ -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_MINIMAL - rahmenlos, nur grosse Werte mit duenner Ist/Soll-Linie
|
||||||
// TD_NEO - Soft-3D/Neumorph: Flaeche wirkt aus dem Hintergrund herausgedrueckt
|
// TD_NEO - Soft-3D/Neumorph: Flaeche wirkt aus dem Hintergrund herausgedrueckt
|
||||||
// TD_THERMO - vertikale Thermometer-Saeulen mit Kolben und Glanzstreifen
|
// 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 };
|
enum TempDesign { TD_GEWICHTET = 0, TD_VERLAUF, TD_FLAECHEN, TD_BAND, TD_DESIGN_COUNT };
|
||||||
static uint8_t g_tempDesign = TD_GAUGE;
|
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* 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* 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;
|
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 (pct > 100) pct = 100; else if (pct < 0) pct = 0;
|
||||||
if (bar) {
|
if (bar) {
|
||||||
lv_bar_set_value(bar, pct, LV_ANIM_OFF);
|
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) {
|
if (arc) {
|
||||||
lv_arc_set_value(arc, pct);
|
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);
|
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) {
|
// Temperaturbereich des Dashboards - vier Darstellungen
|
||||||
lv_obj_t* card = th_card(parent);
|
//
|
||||||
lv_obj_set_size(card, LV_PCT(49), LV_PCT(100));
|
// Gemeinsam ist allen: zwei Kessel, die Zahl ist das Erste, was man sieht. Unterschiedlich
|
||||||
lv_obj_set_flex_flow(card, LV_FLEX_FLOW_COLUMN);
|
// ist, was die Flaeche zusaetzlich leistet.
|
||||||
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);
|
// Die grossen Zahlen brauchen Schriftgrade, die es vorher nicht gab (96 und 140 Pixel).
|
||||||
lv_obj_add_flag(card, LV_OBJ_FLAG_CLICKABLE); // antippbar -> Temperatur-Seite
|
// Diese beiden Schriften enthalten nur Ziffern, Komma, Punkt, Minus und Gradzeichen - mit
|
||||||
lv_obj_add_event_cb(card, temp_card_cb, LV_EVENT_CLICKED, nullptr);
|
// vollem Zeichensatz waeren sie um ein Vielfaches groesser, ohne etwas beizutragen.
|
||||||
lv_obj_t* t = lv_label_create(card);
|
// ------------------------------------------------------------------------------------
|
||||||
lv_label_set_text(t, title);
|
|
||||||
lv_obj_set_style_text_color(t, accent, 0);
|
// Ein Kesselfeld. 'grow' verteilt die Breite zwischen den beiden, 'valueFont' bestimmt die
|
||||||
lv_obj_set_style_text_font(t, font_text(), 0);
|
// Groesse der Zahl, 'flat' laesst den Kartenrahmen weg und faerbt stattdessen die Flaeche.
|
||||||
*big = lv_label_create(card);
|
static lv_obj_t* tempField(lv_obj_t* parent, const char* title, lv_color_t accent,
|
||||||
lv_label_set_text(*big, "--.-");
|
lv_obj_t** big, lv_obj_t** setp, lv_obj_t** bar,
|
||||||
lv_obj_set_style_text_color(*big, COL_TEXT, 0);
|
uint8_t grow, const lv_font_t* valueFont,
|
||||||
lv_obj_set_style_text_font(*big, &lv_font_maven_pro_48, 0);
|
bool flat, uint32_t flatBg) {
|
||||||
*setp = lv_label_create(card);
|
lv_obj_t* c;
|
||||||
lv_label_set_text(*setp, "Soll --.-");
|
if (flat) {
|
||||||
lv_obj_set_style_text_color(*setp, COL_TEXT_DIM, 0);
|
c = lv_obj_create(parent);
|
||||||
lv_obj_set_style_text_font(*setp, font_text(), 0);
|
lv_obj_set_style_bg_color(c, lv_color_hex(flatBg), 0);
|
||||||
*bar = lv_bar_create(card);
|
lv_obj_set_style_bg_opa(c, LV_OPA_COVER, 0);
|
||||||
lv_obj_set_size(*bar, LV_PCT(92), 12);
|
lv_obj_set_style_border_width(c, 0, 0);
|
||||||
lv_obj_set_style_bg_color(*bar, lv_color_hex(0x3a3a3a), 0); // sichtbarer Track (auch bei 0 %)
|
lv_obj_set_style_radius(c, 0, 0);
|
||||||
lv_obj_set_style_bg_opa(*bar, LV_OPA_COVER, 0);
|
lv_obj_set_style_pad_all(c, 14, 0);
|
||||||
lv_obj_set_style_border_color(*bar, COL_BORDER, 0);
|
} else {
|
||||||
lv_obj_set_style_border_width(*bar, 1, 0);
|
c = th_card(parent);
|
||||||
lv_obj_set_style_radius(*bar, 6, 0);
|
lv_obj_set_style_pad_all(c, 12, 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.
|
lv_obj_set_height(c, LV_PCT(100));
|
||||||
// Leichte 3D-Wirkung ueber einen "Metall"-Bezel (vertikaler Verlauf hell -> dunkel) mit
|
lv_obj_set_flex_grow(c, grow);
|
||||||
// weichem Schlagschatten und ein leicht aufgehelltes Zifferblatt darunter. Der 270-Grad-
|
lv_obj_set_flex_flow(c, LV_FLEX_FLOW_COLUMN);
|
||||||
// Bogen zeigt Ist/Soll in % und faerbt sich mit der Zustandsfarbe des Ist-Werts.
|
lv_obj_set_flex_align(c, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
|
||||||
static void tempGauge(lv_obj_t* parent, const char* title, lv_color_t accent,
|
lv_obj_clear_flag(c, LV_OBJ_FLAG_SCROLLABLE);
|
||||||
lv_obj_t** big, lv_obj_t** setp, lv_obj_t** arc) {
|
lv_obj_add_flag(c, LV_OBJ_FLAG_CLICKABLE); // antippbar -> Temperatur-Seite
|
||||||
lv_obj_t* holder = lv_obj_create(parent);
|
lv_obj_add_event_cb(c, temp_card_cb, LV_EVENT_CLICKED, nullptr);
|
||||||
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);
|
|
||||||
|
|
||||||
// Bezel-Ring: Verlauf von hell (oben) nach dunkel (unten) + Schatten = Metall-Optik
|
lv_obj_t* t = lv_label_create(c);
|
||||||
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
|
|
||||||
|
|
||||||
// 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_label_set_text(t, title);
|
lv_label_set_text(t, title);
|
||||||
lv_obj_set_style_text_color(t, accent, 0);
|
lv_obj_set_style_text_color(t, accent, 0);
|
||||||
lv_obj_set_style_text_font(t, font_small(), 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_label_set_text(*big, "--.-");
|
||||||
lv_obj_set_style_text_color(*big, COL_TEXT, 0);
|
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_set_style_text_font(*big, valueFont, 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(c);
|
||||||
*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_label_set_text(*setp, "Soll --.-");
|
lv_label_set_text(*setp, "Soll --.-");
|
||||||
lv_obj_set_style_text_color(*setp, COL_TEXT_DIM, 0);
|
lv_obj_set_style_text_color(*setp, COL_TEXT_DIM, 0);
|
||||||
lv_obj_set_style_text_font(*setp, font_text(), 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);
|
*bar = lv_bar_create(c);
|
||||||
lv_obj_set_size(inner, LV_PCT(100), LV_PCT(100));
|
lv_obj_set_size(*bar, LV_PCT(92), 8);
|
||||||
lv_obj_set_style_radius(inner, 20, 0);
|
lv_obj_set_style_bg_color(*bar, lv_color_hex(0x2c2c2c), 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);
|
|
||||||
lv_obj_set_style_bg_opa(*bar, LV_OPA_COVER, 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_border_width(*bar, 0, 0);
|
||||||
lv_obj_set_style_radius(*bar, 5, 0);
|
lv_obj_set_style_radius(*bar, 4, 0);
|
||||||
lv_obj_set_style_bg_color(*bar, accent, LV_PART_INDICATOR); // folgt spaeter der Zustandsfarbe
|
lv_obj_set_style_bg_color(*bar, accent, LV_PART_INDICATOR);
|
||||||
lv_obj_set_style_radius(*bar, 5, LV_PART_INDICATOR);
|
lv_obj_set_style_radius(*bar, 4, LV_PART_INDICATOR);
|
||||||
lv_bar_set_range(*bar, 0, 100);
|
lv_bar_set_range(*bar, 0, 100);
|
||||||
lv_bar_set_value(*bar, 0, LV_ANIM_OFF);
|
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)
|
// Flache Verlaufskurve unter einer Temperatur. Zeigt, ob die Regelung haelt - das ist die
|
||||||
lv_obj_set_size(th, 48, 190);
|
// eigentliche Frage an eine PID-Regelung, und eine Zahl kann sie grundsaetzlich nicht
|
||||||
lv_obj_set_style_bg_opa(th, LV_OPA_TRANSP, 0);
|
// beantworten. Gespeist wird sie aus derselben Sekundenabtastung wie die Verlaufsseite.
|
||||||
lv_obj_set_style_border_width(th, 0, 0);
|
static lv_obj_t* tempSpark(lv_obj_t* parent, lv_color_t col, lv_chart_series_t** ser) {
|
||||||
lv_obj_set_style_pad_all(th, 0, 0);
|
lv_obj_t* ch = lv_chart_create(parent);
|
||||||
lv_obj_clear_flag(th, LV_OBJ_FLAG_SCROLLABLE);
|
lv_obj_set_size(ch, LV_PCT(96), 72);
|
||||||
lv_obj_clear_flag(th, LV_OBJ_FLAG_CLICKABLE);
|
lv_chart_set_type(ch, LV_CHART_TYPE_LINE);
|
||||||
*bar = lv_bar_create(th); // hochkant -> fuellt sich von unten
|
lv_chart_set_point_count(ch, DASH_SPARK_POINTS);
|
||||||
lv_obj_set_size(*bar, 20, 158);
|
lv_chart_set_div_line_count(ch, 0, 0);
|
||||||
lv_obj_align(*bar, LV_ALIGN_TOP_MID, 0, 0);
|
lv_obj_set_style_bg_opa(ch, LV_OPA_TRANSP, 0);
|
||||||
lv_obj_set_style_bg_color(*bar, lv_color_hex(0x262626), 0);
|
lv_obj_set_style_border_width(ch, 0, 0);
|
||||||
lv_obj_set_style_bg_opa(*bar, LV_OPA_COVER, 0);
|
lv_obj_set_style_pad_all(ch, 0, 0);
|
||||||
lv_obj_set_style_border_width(*bar, 0, 0);
|
lv_obj_set_style_size(ch, 0, 0, LV_PART_INDICATOR); // keine Punktmarkierungen
|
||||||
lv_obj_set_style_radius(*bar, 10, 0);
|
lv_obj_set_style_line_width(ch, 3, LV_PART_ITEMS);
|
||||||
lv_obj_set_style_bg_color(*bar, accent, LV_PART_INDICATOR); // folgt spaeter der Zustandsfarbe
|
lv_obj_clear_flag(ch, LV_OBJ_FLAG_SCROLLABLE);
|
||||||
lv_obj_set_style_radius(*bar, 10, LV_PART_INDICATOR);
|
*ser = lv_chart_add_series(ch, col, LV_CHART_AXIS_PRIMARY_Y);
|
||||||
lv_bar_set_range(*bar, 0, 100);
|
return ch;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
// 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() {
|
static void build_temp_row_content() {
|
||||||
if (!g_tempRow) return;
|
if (!g_tempRow) return;
|
||||||
lv_obj_clean(g_tempRow);
|
lv_obj_clean(g_tempRow);
|
||||||
@@ -1105,33 +905,83 @@ static void build_temp_row_content() {
|
|||||||
lblTempD = lblSetD = barDutyD = nullptr;
|
lblTempD = lblSetD = barDutyD = nullptr;
|
||||||
arcTempW = arcTempD = nullptr;
|
arcTempW = arcTempD = nullptr;
|
||||||
bulbTempW = bulbTempD = nullptr;
|
bulbTempW = bulbTempD = nullptr;
|
||||||
// Nur Soft-3D braucht Innenabstand, damit die weichen Schatten nicht am Rand abgeschnitten werden
|
g_sparkW = g_sparkD = nullptr;
|
||||||
lv_obj_set_style_pad_hor(g_tempRow, (g_tempDesign == TD_NEO) ? 12 : 0, 0);
|
g_sparkSerW = g_sparkSerD = nullptr;
|
||||||
lv_obj_set_style_pad_ver(g_tempRow, (g_tempDesign == TD_NEO) ? 12 : 0, 0);
|
g_readyBand = g_readyBandLbl = nullptr;
|
||||||
|
|
||||||
const lv_color_t teal = lv_color_hex(0x80cbc4);
|
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) {
|
switch (g_tempDesign) {
|
||||||
case TD_GAUGE:
|
|
||||||
tempGauge(g_tempRow, "WASSER", COL_ACCENT, &lblTempW, &lblSetW, &arcTempW);
|
case TD_GEWICHTET: {
|
||||||
tempGauge(g_tempRow, "DAMPF", teal, &lblTempD, &lblSetD, &arcTempD);
|
// 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;
|
break;
|
||||||
case TD_MINIMAL:
|
}
|
||||||
tempMinimal(g_tempRow, "WASSER", COL_ACCENT, &lblTempW, &lblSetW, &barDutyW);
|
|
||||||
tempMinimal(g_tempRow, "DAMPF", teal, &lblTempD, &lblSetD, &barDutyD);
|
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;
|
break;
|
||||||
case TD_NEO:
|
}
|
||||||
tempNeo(g_tempRow, "WASSER", COL_ACCENT, &lblTempW, &lblSetW, &barDutyW);
|
|
||||||
tempNeo(g_tempRow, "DAMPF", teal, &lblTempD, &lblSetD, &barDutyD);
|
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;
|
break;
|
||||||
case TD_THERMO:
|
}
|
||||||
tempThermo(g_tempRow, "WASSER", COL_ACCENT, &lblTempW, &lblSetW, &barDutyW, &bulbTempW);
|
|
||||||
tempThermo(g_tempRow, "DAMPF", teal, &lblTempD, &lblSetD, &barDutyD, &bulbTempD);
|
default: { // TD_BAND
|
||||||
break;
|
// Ein farbiges Band ueber die volle Breite sagt den Zustand, bevor man eine Zahl
|
||||||
default:
|
// liest. Deshalb hier eine Spalte: Band oben, darunter die beiden Kessel.
|
||||||
tempCard(g_tempRow, "WASSER", COL_ACCENT, &lblTempW, &lblSetW, &barDutyW);
|
lv_obj_set_flex_flow(g_tempRow, LV_FLEX_FLOW_COLUMN);
|
||||||
tempCard(g_tempRow, "DAMPF", teal, &lblTempD, &lblSetD, &barDutyD);
|
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;
|
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) {
|
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) {
|
||||||
lv_obj_t* card = th_card(parent);
|
lv_obj_t* card = th_card(parent);
|
||||||
lv_obj_set_height(card, LV_PCT(100));
|
lv_obj_set_height(card, LV_PCT(100));
|
||||||
@@ -1578,6 +1428,20 @@ static void chart_duty_btn_cb(lv_event_t*) {
|
|||||||
else lv_obj_add_flag(g_legDuty, LV_OBJ_FLAG_HIDDEN);
|
else lv_obj_add_flag(g_legDuty, LV_OBJ_FLAG_HIDDEN);
|
||||||
}
|
}
|
||||||
chart_redraw();
|
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) {
|
static void build_chart(lv_obj_t* p) {
|
||||||
lv_obj_clear_flag(p, LV_OBJ_FLAG_SCROLLABLE);
|
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;
|
if (valOut) *valOut = v;
|
||||||
}
|
}
|
||||||
// --- Darstellung: Dashboard-Temperaturdesign umschalten (P4-lokal, in NVS gespeichert) ---
|
// --- 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() {
|
static void design_btns_refresh() {
|
||||||
for (int i = 0; i < TD_DESIGN_COUNT; i++) {
|
for (int i = 0; i < TD_DESIGN_COUNT; i++) {
|
||||||
if (!g_designBtn[i]) continue;
|
if (!g_designBtn[i]) continue;
|
||||||
@@ -3362,13 +3226,16 @@ void ui_init(ProtocolClient* client) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
{ Preferences prefs; prefs.begin("ui", false);
|
{ 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_brewLiveEnabled = prefs.getBool("brewlive", true);
|
||||||
g_chartWin = prefs.getUChar("chartwin", 0);
|
g_chartWin = prefs.getUChar("chartwin", 0);
|
||||||
if (g_chartWin > 3) g_chartWin = 0;
|
if (g_chartWin > 3) g_chartWin = 0;
|
||||||
g_chartDuty = prefs.getBool("chartduty", false);
|
g_chartDuty = prefs.getBool("chartduty", false);
|
||||||
prefs.end();
|
prefs.end();
|
||||||
if (g_tempDesign >= TD_DESIGN_COUNT) g_tempDesign = TD_GAUGE; }
|
}
|
||||||
|
|
||||||
font_step_load(); // gewaehlte Schriftgroesse, bevor irgendetwas angelegt wird
|
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
|
// 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) {
|
void ui_update(const MachineState& st) {
|
||||||
if (!g_uiReady) return;
|
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;
|
int pctD = (st.setD > 0.0f) ? (int)(st.tempD / st.setD * 100.0f + 0.5f) : 0;
|
||||||
temp_progress_set(barDutyD, arcTempD, bulbTempD, pctD, colD);
|
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
|
// "BEREIT"-Pille im Header: Wasser im Zielband (und Dampf, sofern er heizt), kein
|
||||||
// Fehler/Standby/Eco und kein laufender Aufheiz-Countdown. Mit Hysterese gegen
|
// Fehler/Standby/Eco und kein laufender Aufheiz-Countdown. Mit Hysterese gegen
|
||||||
|
|||||||
Reference in New Issue
Block a user