feat: Espresso/Cold-Auswahl bei jedem Aufwecken, auch per Schalter (S3 5.6.0 / P4 1.4.0)
Die Abfrage war eine reine Vorab-Abfrage des Displays und erschien nur beim Antippen des Standby-Bildschirms. Beim Aufwecken über den Schalter ist der Standby aber schon beendet, bevor das Display überhaupt fragen könnte — dieser Weg war nie abgedeckt. Die Steuerung hält jetzt nach dem Aufwecken ein Auswahlfenster offen (20 s): Der Wasserkreis heizt in dieser Zeit nicht, das Display blendet die Auswahl von sich aus ein und zeigt einen Countdown. Ohne Entscheidung wird danach normal geheizt, es geht also nichts verloren, wenn niemand hinsieht. Das Fenster öffnet nur mit angeschlossenem Display (sonst könnte niemand wählen), bei freigeschalteter Funktion und aktiver Einstellung "Abfrage beim Aufwecken", und nur wenn der Modus nicht ohnehin schon läuft. Es schließt bei Entscheidung, Bezug/Spülen oder erneutem Standby. Neue Aktion wakeEspresso (beendet Standby falls aktiv und schließt das Fenster) — das Display sendet sie statt deactivateStandby, sobald die Auswahl relevant ist, sonst würde direkt nach dem Aufwecken nochmal gefragt. Neue State-Felder cxWakeChoice und cxWakeChoiceSec. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
7d14f94a72
commit
7c1e485722
@@ -1,3 +1,20 @@
|
||||
Version 5.6.0:
|
||||
- Die Abfrage „Espresso oder Cold Extraction" kommt jetzt bei JEDEM Weg aus dem Standby, also auch beim
|
||||
Aufwecken über den Schalter. Bisher war sie eine reine Vorab-Abfrage des Touch-Displays und erschien nur
|
||||
beim Antippen des Standby-Bildschirms - beim Schalter ist der Standby aber schon beendet, bevor das
|
||||
Display überhaupt fragen könnte. Dieser Weg war damit nie abgedeckt.
|
||||
- Dafür hält die Steuerung nach dem Aufwecken ein Auswahlfenster offen (20 s): Der Wasserkreis heizt in
|
||||
dieser Zeit nicht, das Display zeigt die Auswahl mit Countdown. Ohne Entscheidung wird anschließend
|
||||
normal geheizt - es geht also nichts verloren, wenn niemand hinsieht.
|
||||
- Das Fenster öffnet nur mit angeschlossenem Touch-Display (ohne Display könnte niemand wählen), bei
|
||||
freigeschalteter Funktion und aktivierter Einstellung „Abfrage beim Aufwecken", und nur wenn der
|
||||
Cold-Extraction-Modus nicht ohnehin schon aktiv ist. Es schließt sofort bei einer Entscheidung, bei
|
||||
Bezug/Spülen oder erneutem Standby.
|
||||
- Neue Aktion „wakeEspresso": beendet den Standby (falls noch aktiv) und schließt das Auswahlfenster.
|
||||
Das Display sendet sie statt „deactivateStandby", sobald die Auswahl relevant ist - sonst würde nach
|
||||
dem Aufwecken über den Dialog gleich nochmal gefragt.
|
||||
- Neue State-Felder „cxWakeChoice" (Fenster offen) und „cxWakeChoiceSec" (Restsekunden).
|
||||
|
||||
Version 5.5.0:
|
||||
- Neu: Beim Aufwecken aus dem Standby fragt das Touch-Display, ob normal geheizt (Espresso) oder kalt
|
||||
extrahiert werden soll. Damit lässt sich das bei jedem Aufwecken neu entscheiden, ohne vorher die
|
||||
|
||||
@@ -322,6 +322,7 @@ Alle gültigen `action`-Strings aus `executeDashboardAction()` (Stand v4.8.1, Ze
|
||||
| `startColdExtraction` | — | Modus aktivieren (Wasserkreis heizt nicht, Dampf bleibt möglich) |
|
||||
| `stopColdExtraction` | — | Modus beenden |
|
||||
| `toggleColdExtraction` | — | Modus umschalten |
|
||||
| `wakeEspresso` | — | Standby beenden (falls aktiv) und das Auswahlfenster schließen, also „normal heizen" wählen (ab S3 5.6.0) |
|
||||
|
||||
Für das Bedienelement zählt `cxArmable`, **nicht** `cxAllowed`: Der Modus schaltet die
|
||||
Wasserheizung ab und muss deshalb auch im Standby und bei noch warmem Kessel scharf zu
|
||||
@@ -407,6 +408,8 @@ Aus `getTouchUartStatus()`. Für sprach-unabhängige UI-Logik/Icons auf dem P4 v
|
||||
| `cxPumpMaxRun` | float | Pumpenschutz: max. kumulierte Laufzeit in s (ab S3 5.4.0) |
|
||||
| `cxPumpRest` | float | Pumpenschutz: Zwangspause in s (ab S3 5.4.0) |
|
||||
| `cxAskOnWake` | bool | Beim Aufwecken aus dem Standby nach Espresso/Cold Extraction fragen (ab S3 5.5.0) |
|
||||
| `cxWakeChoice` | bool | Auswahlfenster nach dem Aufwecken offen — Wasserkreis heizt solange nicht (ab S3 5.6.0) |
|
||||
| `cxWakeChoiceSec` | long | Restsekunden der Bedenkzeit |
|
||||
| `cxMaxSecs` | float | Sicherheits-Timeout des Bezugs in s |
|
||||
| `cxBlock` | uint8 | Sperrgrund (siehe unten), `0` = frei |
|
||||
| `cxNotice` | uint8 | transiente Meldung, `0` = keine (läuft nach ~6 s selbst ab) |
|
||||
|
||||
+74
-5
@@ -369,7 +369,7 @@ Adafruit_SH1106G display = Adafruit_SH1106G(128, 64, &Wire);
|
||||
* Firmware-Informationen
|
||||
************************************************************************************/
|
||||
|
||||
String version = "5.5.0";
|
||||
String version = "5.6.0";
|
||||
String versionHersteller = "Thomas Müller";
|
||||
String versionHerstellerMail =
|
||||
"<a href='mailto:thomas@mueller.black' class='info-link'>thomas@mueller.black</a>";
|
||||
@@ -794,6 +794,15 @@ float coldExtractionPumpRestSec = 20.0f; // Dauer der Zwangspause
|
||||
// extrahiert werden soll. Nur wirksam bei angeschlossenem UART-Display und freigeschalteter
|
||||
// Funktion; abschaltbar, wenn man den Zwischenschritt nicht mehr will.
|
||||
bool coldExtractionAskOnWake = true;
|
||||
// Auswahlfenster nach dem Aufwecken: Der Dialog am Display ist eine Vorab-Abfrage und kann
|
||||
// den Schalter-Weg nicht abdecken - dort ist der Standby schon beendet, bevor das Display
|
||||
// fragen koennte. Deshalb haelt die Steuerung den Wasserkreis nach dem Aufwecken kurz aus
|
||||
// und wartet auf die Entscheidung; laeuft das Fenster ab, wird normal geheizt.
|
||||
bool coldExtractionWakeChoicePending = false;
|
||||
unsigned long coldExtractionWakeChoiceUntilMs = 0;
|
||||
unsigned long coldExtractionWakeDecisionMs = 0; // Zeitpunkt der letzten expliziten Wahl
|
||||
const unsigned long COLDEX_WAKE_CHOICE_MS = 20000UL; // Bedenkzeit
|
||||
const unsigned long COLDEX_WAKE_DECISION_GRACE_MS = 5000UL; // frisch entschieden -> kein Fenster
|
||||
|
||||
const bool defaultColdExtractionEnabled = false;
|
||||
const float defaultColdExtractionMaxTempC = 30.0f;
|
||||
@@ -5436,6 +5445,24 @@ void loop() {
|
||||
lastShotTime = millis();
|
||||
resetOffsetCompensationReferences();
|
||||
applySteamHeatDisabledOnStartupWakeIfConfigured();
|
||||
// Auswahlfenster oeffnen: gilt fuer JEDEN Weg aus dem Standby (Schalter, Touch, Web,
|
||||
// Timer). Nur sinnvoll mit angeschlossenem Display - ohne das koennte niemand waehlen,
|
||||
// und die Maschine wuerde nur unnoetig spaeter heizen.
|
||||
if (coldExtractionEnabled && coldExtractionAskOnWake && touchUartClientActive &&
|
||||
!coldExtractionModeActive && coldExtractionArmable() &&
|
||||
(coldExtractionWakeDecisionMs == 0 ||
|
||||
(currentMillis - coldExtractionWakeDecisionMs) > COLDEX_WAKE_DECISION_GRACE_MS)) {
|
||||
coldExtractionWakeChoicePending = true;
|
||||
coldExtractionWakeChoiceUntilMs = currentMillis + COLDEX_WAKE_CHOICE_MS;
|
||||
}
|
||||
}
|
||||
// Auswahlfenster beenden: Zeit abgelaufen, Standby, oder es wird ohnehin schon bezogen
|
||||
if (coldExtractionWakeChoicePending) {
|
||||
if (standbyModeActive || coldExtractionModeActive || shotActive || shotSoftwareActive ||
|
||||
flushActive || !coldExtractionEnabled ||
|
||||
(long)(currentMillis - coldExtractionWakeChoiceUntilMs) >= 0) {
|
||||
coldExtractionWakeChoicePending = false;
|
||||
}
|
||||
}
|
||||
if (standbyModeActive != lastStandbyModeActive) {
|
||||
syncFullyKioskWithStandby(standbyModeActive);
|
||||
@@ -5467,7 +5494,7 @@ void loop() {
|
||||
// nach Software-Shots, Einstellungsänderungen mid-shot etc. immer konsistent ist.
|
||||
// Bei Cold Extraction zusaetzlich einfrieren: der Wasserkreis heizt minutenlang nicht,
|
||||
// ohne Freeze wuerde der I-Anteil aufladen und nach dem Modus stark ueberschwingen.
|
||||
setPidWasserIntegralFrozen(coldExtractionModeActive ||
|
||||
setPidWasserIntegralFrozen(coldExtractionModeActive || coldExtractionWakeChoicePending ||
|
||||
(ffIFreezeWasser && (shotActive || shotSoftwareActive) && !wartungsModusAktiv));
|
||||
|
||||
// --- Angepasste Sicherheitsueberpruefung Wasser ---
|
||||
@@ -5488,12 +5515,12 @@ void loop() {
|
||||
} else {
|
||||
if (wasserSensorError) Serial.println("INFO: Wassertemperatursensor wieder OK."); wasserSensorError = false;
|
||||
if (wasserSafetyShutdown) Serial.println("INFO: Wassertemperatur wieder im sicheren Bereich."); wasserSafetyShutdown = false;
|
||||
bool activateBoost = boostWasserActive && !wartungsModusAktiv && !ecoModeAktiv && !autoTuneWasserActive && !coldExtractionModeActive && (InputWasser < (SetpointWasser * 0.95));
|
||||
bool activateBoost = boostWasserActive && !wartungsModusAktiv && !ecoModeAktiv && !autoTuneWasserActive && !coldExtractionModeActive && !coldExtractionWakeChoicePending && (InputWasser < (SetpointWasser * 0.95));
|
||||
if (activateBoost) { OutputWasser = windowSizeWasser; } else if (!autoTuneWasserActive) { pidWasser.Compute(); }
|
||||
// Cold Extraction: Stellgroesse hart auf 0 - der Wasserkreis heizt nicht. Die PID
|
||||
// laeuft weiter (D-Anteil/lastInput bleiben aktuell), nur der Output wird verworfen,
|
||||
// damit auch die dutyW-Telemetrie fuer das Display die Wahrheit zeigt.
|
||||
if (coldExtractionModeActive) { OutputWasser = 0; }
|
||||
if (coldExtractionModeActive || coldExtractionWakeChoicePending) { OutputWasser = 0; }
|
||||
}
|
||||
yield();
|
||||
|
||||
@@ -5570,7 +5597,7 @@ void loop() {
|
||||
recordResetCheckpoint(RESET_CP_LOOP_SSR);
|
||||
unsigned long now = millis();
|
||||
// Wasser SSR
|
||||
if (wasserSensorError || wasserSafetyShutdown || standbyModeActive || displayOtaActive || coldExtractionModeActive) { digitalWrite(SSR_WASSER_PIN, LOW); } else {
|
||||
if (wasserSensorError || wasserSafetyShutdown || standbyModeActive || displayOtaActive || coldExtractionModeActive || coldExtractionWakeChoicePending) { digitalWrite(SSR_WASSER_PIN, LOW); } else {
|
||||
if (now - windowStartTimeWasser > windowSizeWasser) { windowStartTimeWasser = now; }
|
||||
unsigned long effOutWasser = effectiveOutputWasserMs(); // PID-Output + Feed-Forward-Boost bei Bezug
|
||||
bool pidWantsHeat = (effOutWasser > 0) && (now < (windowStartTimeWasser + effOutWasser));
|
||||
@@ -15658,6 +15685,29 @@ bool executeDashboardAction(const String& action, const String& value,
|
||||
success = true;
|
||||
}
|
||||
}
|
||||
// Gegenstueck zu startColdExtraction beim Aufwecken: "normal heizen" bewusst waehlen.
|
||||
// Beendet den Standby, falls noch aktiv, und schliesst das Auswahlfenster - sonst
|
||||
// wuerde nach dem Aufwecken noch einmal gefragt.
|
||||
else if (action == "wakeEspresso") {
|
||||
coldExtractionWakeDecisionMs = millis();
|
||||
coldExtractionWakeChoicePending = false;
|
||||
if (standbyModeActive) {
|
||||
standbyModeActive = false;
|
||||
startupTime = millis();
|
||||
ecoForcedActive = false;
|
||||
steamDelayOverridden = false;
|
||||
EEPROM.get(EEPROM_ADDR_SETPOINT_WASSER, SetpointWasser);
|
||||
EEPROM.get(EEPROM_ADDR_SETPOINT_DAMPF, SetpointDampf);
|
||||
ecoModeAktiv = false;
|
||||
ecoModeActivatedTime = 0;
|
||||
lastShotTime = millis();
|
||||
applyLightOutput();
|
||||
message = "Espresso: Standby aufgehoben, Kessel heizt auf.";
|
||||
} else {
|
||||
message = "Espresso: Kessel heizt auf.";
|
||||
}
|
||||
success = true;
|
||||
}
|
||||
else if (action == "activateStandby") {
|
||||
if (standbyModeActive) {
|
||||
message = "Standby ist bereits aktiv.";
|
||||
@@ -15787,6 +15837,9 @@ bool executeDashboardAction(const String& action, const String& value,
|
||||
} else {
|
||||
target = !coldExtractionModeActive;
|
||||
}
|
||||
// Jede bewusste Wahl schliesst das Auswahlfenster nach dem Aufwecken
|
||||
coldExtractionWakeDecisionMs = millis();
|
||||
coldExtractionWakeChoicePending = false;
|
||||
success = setColdExtractionMode(target, message);
|
||||
if (!success) {
|
||||
coldExtractionBlockMessage = message;
|
||||
@@ -16289,6 +16342,9 @@ void buildDashboardJson(char *buffer, size_t bufferSize) {
|
||||
}
|
||||
}
|
||||
statusKey = "brewing";
|
||||
} else if (coldExtractionWakeChoicePending) {
|
||||
statusText = "Auswahl: Espresso oder Cold Extraction?";
|
||||
statusKey = "coldextraction";
|
||||
} else if (coldExtractionModeActive) {
|
||||
statusText = coldExtractionScaleUsable()
|
||||
? "Cold Extraction bereit (Wasserkreis heizt nicht)"
|
||||
@@ -16540,6 +16596,9 @@ static void getTouchUartStatus(String& statusText, String& statusKey) {
|
||||
statusText = "Bezug aktiv...";
|
||||
}
|
||||
statusKey = "brewing";
|
||||
} else if (coldExtractionWakeChoicePending) {
|
||||
statusText = "Auswahl: Espresso oder Cold Extraction?";
|
||||
statusKey = "coldextraction";
|
||||
} else if (coldExtractionModeActive) {
|
||||
statusText = coldExtractionScaleUsable() ? "Cold Extraction bereit"
|
||||
: "Cold Extraction bereit (Zeitsteuerung)";
|
||||
@@ -16741,6 +16800,16 @@ static void buildTouchUartStateJson(char *buffer, size_t bufferSize) {
|
||||
offset += snprintf(buffer + offset, bufferSize - offset, "\"cxArmable\":%s,", coldExtractionArmable() ? "true" : "false");
|
||||
offset += snprintf(buffer + offset, bufferSize - offset, "\"cxResting\":%s,", coldExtractionPumpResting ? "true" : "false");
|
||||
offset += snprintf(buffer + offset, bufferSize - offset, "\"cxAskOnWake\":%s,", coldExtractionAskOnWake ? "true" : "false");
|
||||
// Offenes Auswahlfenster nach dem Aufwecken (+ Restsekunden fuer den Countdown am Display)
|
||||
offset += snprintf(buffer + offset, bufferSize - offset, "\"cxWakeChoice\":%s,", coldExtractionWakeChoicePending ? "true" : "false");
|
||||
{
|
||||
long cxWakeSec = 0;
|
||||
if (coldExtractionWakeChoicePending) {
|
||||
long remainMs = (long)(coldExtractionWakeChoiceUntilMs - millis());
|
||||
cxWakeSec = (remainMs > 0) ? (long)((remainMs + 999) / 1000) : 0;
|
||||
}
|
||||
offset += snprintf(buffer + offset, bufferSize - offset, "\"cxWakeChoiceSec\":%ld,", cxWakeSec);
|
||||
}
|
||||
dtostrf(coldExtractionMaxTempC, 4, 1, floatBuf); offset += snprintf(buffer + offset, bufferSize - offset, "\"cxMaxTemp\":%s,", floatBuf);
|
||||
dtostrf(coldExtractionTargetGrams, 4, 1, floatBuf); offset += snprintf(buffer + offset, bufferSize - offset, "\"cxTarget\":%s,", floatBuf);
|
||||
dtostrf(coldExtractionPreInfusionSeconds, 4, 1, floatBuf); offset += snprintf(buffer + offset, bufferSize - offset, "\"cxPreInf\":%s,", floatBuf);
|
||||
|
||||
@@ -1,3 +1,14 @@
|
||||
Version 1.4.0:
|
||||
- Die Auswahl „Espresso oder Cold Extraction" erscheint jetzt auch beim Aufwecken über den Schalter
|
||||
(braucht S3-Firmware ab 5.6.0). Meldet die S3 ein offenes Auswahlfenster (cxWakeChoice), blendet das
|
||||
Display den Dialog von sich aus ein - ohne Antippen - und zeigt die verbleibende Bedenkzeit als
|
||||
Countdown. „Abbrechen" entfällt in diesem Fall, weil es nichts abzubrechen gibt: Läuft die Zeit ab,
|
||||
heizt die Maschine normal auf.
|
||||
- Der Espresso-Knopf sendet „wakeEspresso" statt „deactivateStandby", sobald die Auswahl relevant ist.
|
||||
Damit wird die Entscheidung auf der S3 vermerkt und nicht direkt danach erneut gefragt.
|
||||
- Der Cold-Extraction-Knopf beendet den Standby nur noch, wenn er überhaupt aktiv ist - im Auswahlfenster
|
||||
nach dem Aufwecken schaltet er nur den Modus.
|
||||
|
||||
Version 1.3.0:
|
||||
- Der Aufweck-Dialog wird zur Auswahl: „Womit aufwecken?" mit den Knöpfen „Espresso" (heizt normal auf)
|
||||
und „Cold Extraction (Wasser bleibt kalt)". Braucht S3-Firmware ab 5.5.0.
|
||||
|
||||
@@ -65,7 +65,7 @@
|
||||
// -------------------------------------------------------------------------------------
|
||||
// Firmware
|
||||
// -------------------------------------------------------------------------------------
|
||||
#define DISPLAY_FW_VERSION "1.3.0" // Firmware-Stand der P4-Display-Steuerung (Info-Seite)
|
||||
#define DISPLAY_FW_VERSION "1.4.0" // Firmware-Stand der P4-Display-Steuerung (Info-Seite)
|
||||
|
||||
// -------------------------------------------------------------------------------------
|
||||
// Protokoll
|
||||
|
||||
@@ -85,6 +85,8 @@ struct MachineState {
|
||||
float cxPumpMaxRun = 0; // Pumpenschutz: max. kumulierte Laufzeit in s
|
||||
float cxPumpRest = 0; // Pumpenschutz: Zwangspause in s
|
||||
bool cxAskOnWake = false; // Beim Aufwecken aus dem Standby fragen (seit S3 5.5.0)
|
||||
bool cxWakeChoice = false; // Auswahlfenster nach dem Aufwecken offen (seit S3 5.6.0)
|
||||
long cxWakeChoiceSec = 0; // Restsekunden der Bedenkzeit
|
||||
float cxMaxSecs = 0; // Sicherheits-Timeout des Bezugs in s
|
||||
// Sperrgrund: 0=frei, 1=nicht freigeschaltet, 2=Standby, 3=Wartung, 4=Reinigungsassistent,
|
||||
// 5=PID-Tuning, 6=Sensorfehler, 7=Wasserkessel zu warm
|
||||
|
||||
@@ -237,6 +237,8 @@ void ProtocolClient::applyState(const String& json) {
|
||||
s.cxPumpMaxRun = doc["cxPumpMaxRun"] | s.cxPumpMaxRun;
|
||||
s.cxPumpRest = doc["cxPumpRest"] | s.cxPumpRest;
|
||||
s.cxAskOnWake = doc["cxAskOnWake"] | false;
|
||||
s.cxWakeChoice = doc["cxWakeChoice"] | false;
|
||||
s.cxWakeChoiceSec = doc["cxWakeChoiceSec"] | (long)0;
|
||||
s.cxMaxSecs = doc["cxMaxSecs"] | s.cxMaxSecs;
|
||||
s.cxBlock = doc["cxBlock"] | (uint8_t)0;
|
||||
s.cxNotice = doc["cxNotice"] | (uint8_t)0;
|
||||
|
||||
@@ -41,6 +41,7 @@ static lv_obj_t* g_wakeConfirm = nullptr; // Bestaetigungsdialog "Aus dem Stan
|
||||
static lv_obj_t* g_wakeColdBtn = nullptr; // "Cold Extraction" im Aufweck-Dialog
|
||||
static lv_obj_t* g_wakeMsg = nullptr; // Text des Aufweck-Dialogs (wechselt bei Abfrage-Modus)
|
||||
static lv_obj_t* g_wakeYesLbl = nullptr; // Beschriftung des Bestaetigen-Knopfs
|
||||
static lv_obj_t* g_wakeNoBtn = nullptr; // "Abbrechen" (entfaellt beim Auswahlfenster nach dem Aufwecken)
|
||||
static bool g_wakeDialogOpen = false; // Dialog sichtbar -> Display hell schalten (lesbar)
|
||||
static bool g_standbyShown = false; // Standby-Uhr-Overlay zuletzt als sichtbar geschaltet (fuer Ein-/Ausblend-Uebergang)
|
||||
|
||||
@@ -607,7 +608,12 @@ static void wake_yes_cb(lv_event_t*) { // Aufwecken -> hell lassen, S3 bee
|
||||
wake_confirm_hide();
|
||||
// g_wakeDialogOpen bleibt true, bis der Standby wirklich endet (ui_update) - sonst wuerde
|
||||
// das Display in der Uebergangsphase kurz auf Standby-Helligkeit abdunkeln.
|
||||
if (g_client) { g_client->sendAction("deactivateStandby"); showToast("Maschine wird aufgeweckt...", false); }
|
||||
if (!g_client) return;
|
||||
// "wakeEspresso" beendet den Standby UND schliesst das Auswahlfenster der S3. Ohne das
|
||||
// wuerde nach dem Aufwecken noch einmal gefragt bzw. der Wasserkreis bliebe kurz aus.
|
||||
const bool choiceRelevant = g_state.cxWakeChoice || (g_state.cxEnabled && g_state.cxAskOnWake);
|
||||
g_client->sendAction(choiceRelevant ? "wakeEspresso" : "deactivateStandby");
|
||||
showToast(g_state.standbyActive ? "Maschine wird aufgeweckt..." : "Espresso: Kessel heizt auf.", false);
|
||||
}
|
||||
// Aufwecken direkt in die kalte Extraktion. Reihenfolge ist wichtig: erst den Modus scharf
|
||||
// stellen, dann den Standby beenden - sonst heizt der Wasserkreis in der Zwischenzeit an,
|
||||
@@ -616,8 +622,8 @@ static void wake_cold_cb(lv_event_t*) {
|
||||
wake_confirm_hide();
|
||||
if (g_client) {
|
||||
g_client->sendAction("startColdExtraction");
|
||||
g_client->sendAction("deactivateStandby");
|
||||
showToast("Aufwecken mit Cold Extraction...", false);
|
||||
if (g_state.standbyActive) g_client->sendAction("deactivateStandby");
|
||||
showToast("Cold Extraction aktiviert.", false);
|
||||
}
|
||||
}
|
||||
bool ui_wake_dialog_open() { return g_wakeDialogOpen; } // fuer die Helligkeitssteuerung in onState
|
||||
@@ -3349,6 +3355,7 @@ void ui_init(ProtocolClient* client) {
|
||||
lv_obj_t* wakeNo = th_button(wakeBtns, "Abbrechen", COL_CARD2, COL_TEXT);
|
||||
lv_obj_set_width(wakeNo, 150);
|
||||
lv_obj_add_event_cb(wakeNo, wake_no_cb, LV_EVENT_CLICKED, nullptr);
|
||||
g_wakeNoBtn = wakeNo;
|
||||
lv_obj_t* wakeYes = th_accent_button(wakeBtns, "Aufwecken");
|
||||
lv_obj_set_width(wakeYes, 150);
|
||||
lv_obj_add_event_cb(wakeYes, wake_yes_cb, LV_EVENT_CLICKED, nullptr);
|
||||
@@ -3555,7 +3562,9 @@ void ui_update(const MachineState& st) {
|
||||
}
|
||||
// Aufweck-Ablauf: nach beendetem Standby Dialog schliessen und Helligkeits-Flag loeschen
|
||||
// (auch wenn der Dialog schon ausgeblendet ist, weil "Aufwecken" das Flag bewusst haelt).
|
||||
if (!st.standbyActive) {
|
||||
// Bei offenem Auswahlfenster (cxWakeChoice) bleibt der Dialog stehen, obwohl der Standby
|
||||
// schon beendet ist - genau dafuer ist er da.
|
||||
if (!st.standbyActive && !st.cxWakeChoice) {
|
||||
g_wakeDialogOpen = false;
|
||||
if (g_wakeConfirm && !lv_obj_has_flag(g_wakeConfirm, LV_OBJ_FLAG_HIDDEN))
|
||||
lv_obj_add_flag(g_wakeConfirm, LV_OBJ_FLAG_HIDDEN);
|
||||
@@ -3591,19 +3600,45 @@ void ui_update(const MachineState& st) {
|
||||
// Abschaltbar ueber die Einstellung cxAskOnWake, damit man sich den Zwischenschritt
|
||||
// sparen kann, wenn gerade keine kalten Bezuege anstehen.
|
||||
{
|
||||
const bool askMode = st.cxEnabled && st.cxArmable && !st.cxActive && st.cxAskOnWake;
|
||||
// Zwei Faelle: Vorab-Abfrage beim Antippen im Standby (askMode) und das von der S3
|
||||
// geoeffnete Auswahlfenster NACH dem Aufwecken (choiceOpen) - letzteres deckt auch
|
||||
// das Aufwecken per Schalter ab, wo es keine Vorab-Abfrage geben kann.
|
||||
const bool choiceOpen = st.cxWakeChoice;
|
||||
const bool askMode = choiceOpen ||
|
||||
(st.cxEnabled && st.cxArmable && !st.cxActive && st.cxAskOnWake);
|
||||
if (g_wakeColdBtn) {
|
||||
if (askMode) lv_obj_remove_flag(g_wakeColdBtn, LV_OBJ_FLAG_HIDDEN);
|
||||
else lv_obj_add_flag(g_wakeColdBtn, LV_OBJ_FLAG_HIDDEN);
|
||||
}
|
||||
// Im Auswahlfenster gibt es nichts abzubrechen - laeuft die Zeit ab, wird geheizt.
|
||||
if (g_wakeNoBtn) {
|
||||
if (choiceOpen) lv_obj_add_flag(g_wakeNoBtn, LV_OBJ_FLAG_HIDDEN);
|
||||
else lv_obj_remove_flag(g_wakeNoBtn, LV_OBJ_FLAG_HIDDEN);
|
||||
}
|
||||
if (g_wakeMsg) {
|
||||
label_set_if_changed(g_wakeMsg, askMode
|
||||
? "Die Maschine befindet sich im Standby.\nWomit aufwecken?"
|
||||
: "Die Maschine befindet sich im Standby.\nAus dem Standby aufwecken?");
|
||||
if (choiceOpen) {
|
||||
char b[128];
|
||||
snprintf(b, sizeof(b),
|
||||
"Womit weiter?\nEspresso heizt auf, Cold Extraction bleibt kalt.\n"
|
||||
"Ohne Auswahl wird in %ld s geheizt.", st.cxWakeChoiceSec);
|
||||
label_set_if_changed(g_wakeMsg, b);
|
||||
} else {
|
||||
label_set_if_changed(g_wakeMsg, askMode
|
||||
? "Die Maschine befindet sich im Standby.\nWomit aufwecken?"
|
||||
: "Die Maschine befindet sich im Standby.\nAus dem Standby aufwecken?");
|
||||
}
|
||||
}
|
||||
if (g_wakeYesLbl) {
|
||||
label_set_if_changed(g_wakeYesLbl, askMode ? "Espresso" : "Aufwecken");
|
||||
}
|
||||
// Auswahlfenster von der S3 -> Dialog von sich aus zeigen (kein Antippen noetig)
|
||||
if (choiceOpen && g_wakeConfirm && lv_obj_has_flag(g_wakeConfirm, LV_OBJ_FLAG_HIDDEN)) {
|
||||
wake_confirm_show();
|
||||
} else if (!choiceOpen && !st.standbyActive && g_wakeConfirm &&
|
||||
!lv_obj_has_flag(g_wakeConfirm, LV_OBJ_FLAG_HIDDEN)) {
|
||||
wake_confirm_hide(); // Fenster abgelaufen oder entschieden
|
||||
g_wakeDialogOpen = false;
|
||||
}
|
||||
}
|
||||
if (st.cxNotice == 2) {
|
||||
status_set(ST_COLDEX, true, LV_SYMBOL_WARNING " Cold Extraction beendet: kein Zulauf",
|
||||
|
||||
Reference in New Issue
Block a user