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>
142 lines
7.7 KiB
C
142 lines
7.7 KiB
C
// =====================================================================================
|
|
// machine_state.h - Spiegelbild des 'state'-Objekts der Hauptplatine
|
|
// =====================================================================================
|
|
// Enthaelt genau die Felder, die die S3 im 'state'-Push sendet
|
|
// (siehe buildTouchUartStateJson() bzw. Doku/JC-Display_UART-Protokoll.md, Abschnitt 5).
|
|
// Das Display haelt KEINEN abweichenden Zustand - es spiegelt nur.
|
|
// =====================================================================================
|
|
|
|
#pragma once
|
|
|
|
#include <Arduino.h>
|
|
|
|
struct MachineState {
|
|
// --- Meta ---
|
|
uint16_t protocolVersion = 0;
|
|
String firmwareVersion;
|
|
|
|
// --- Temperaturen ---
|
|
float tempW = 0, setW = 0; // Wasser ist/soll
|
|
float tempD = 0, setD = 0; // Dampf ist/soll
|
|
|
|
// --- Status ---
|
|
String statusText; // Klartext (DE)
|
|
String statusKey; // sprachneutral: ready/error/standby/maintenance/...
|
|
bool wasserSensorError = false; // Wassersensor liefert ungueltigen Wert
|
|
bool wasserSafetyShutdown = false; // Wassertemperatur ueber Sicherheitslimit -> Heizung aus
|
|
bool dampfSensorError = false; // Dampfsensor liefert ungueltigen Wert
|
|
bool dampfSafetyShutdown = false; // Dampftemperatur ueber Sicherheitslimit -> Heizung aus
|
|
bool shotActive = false;
|
|
uint32_t shotElapsedMs = 0;
|
|
bool scaleTaring = false; // Tarier-Phase vor einem Brew-by-Weight-Bezug laeuft
|
|
bool steamCircuitActive = false;
|
|
uint32_t steamElapsedMs = 0; // verstrichene Dampfbezugszeit (fuer rueckwirkende Timer-Kopplung)
|
|
bool steamFlushActive = false;
|
|
uint32_t steamFlushElapsedMs = 0; // verstrichene Dampf-Flush-Zeit (aus steamFlushEndTime, race-frei)
|
|
bool flushActive = false;
|
|
uint32_t flushElapsedMs = 0; // verstrichene Wasser-Flush-Zeit (fuer rueckwirkende Timer-Kopplung)
|
|
bool ecoActive = false;
|
|
long ecoCountdownSec = -1; // Sekunden bis automatische Eco-Aktivierung (-1 = kein Timer scharf)
|
|
bool ecoShowInfo = false; // S3-Einstellung "Eco-Info auf dem Display anzeigen"
|
|
bool standbyActive = false;
|
|
bool standbyShowClock = false; // S3-Einstellung "Uhrzeit im Standby anzeigen"
|
|
uint8_t backlightActive = 100; // Helligkeit % wenn Display aktiv (von S3 konfiguriert)
|
|
uint8_t backlightStandbyClock = 30;// Helligkeit % fuer Standby-Uhr (von S3 konfiguriert)
|
|
bool maintenanceActive = false;
|
|
bool steamHeatDisabled = false;
|
|
bool steamDelayActive = false; // Dampf-Startverzoegerung laeuft
|
|
long steamDelayRemainSec = 0; // verbleibende Sekunden der Startverzoegerung
|
|
int heatUpMinutes = 0; // konfigurierte Aufheizzeit (Minuten); 0 = aus
|
|
long heatUpRemainSec = -1; // verbleibende Sekunden bis "durchgewaermt" (-1 = aus)
|
|
bool lightOn = false;
|
|
bool piezoEnabled = false;
|
|
String activeProfile; // zuletzt geladenes/gespeichertes Profil (leer = keines; seit S3 5.1.1)
|
|
bool profileDirty = false; // Einstellungen weichen seit dem Laden vom Profil ab
|
|
|
|
// --- Waage ---
|
|
float weight = 0, targetWeight = 0;
|
|
float lastShotWeight = 0; // Endgewicht des letzten Bezugs inkl. Offset (fuer Shot-Zusammenfassung)
|
|
bool lastShotByWeight = false;// war der letzte Bezug gewichtsbasiert? (dann lastShotWeight statt weight anzeigen)
|
|
float flowRate = 0; // aktuelle Flussrate in g/s (waehrend Bezug)
|
|
bool scaleEnabled = false;
|
|
uint8_t scaleType = 0;
|
|
bool scaleConnected = false;
|
|
|
|
// --- Brew-Control ---
|
|
bool piEnabled = false, bbtEnabled = false, bbwEnabled = false, sbtEnabled = false;
|
|
float bbtSecs = 0, sbtSecs = 0, piDurSecs = 0, piPauseSecs = 0;
|
|
float bbwTarget = 0, bbwOffset = 0;
|
|
uint8_t piState = 0; // Pre-Infusion-Phase (0=inaktiv,1=Pre-Infusion,2=Pause,3=Hauptbezug; seit S3 5.0.12)
|
|
|
|
// --- Cold Extraction (kalte Extraktion; seit S3 5.3.0) ---
|
|
bool cxEnabled = false; // Funktion auf der S3 freigeschaltet (sonst Bedienelement ausblenden)
|
|
bool cxActive = false; // Modus scharf: Wasserkreis heizt nicht (persistent, seit S3 5.3.1)
|
|
bool cxShot = false; // der laufende Bezug ist eine kalte Extraktion
|
|
bool cxAllowed = false; // Bezug jetzt moeglich (Wasserkessel kalt genug, kein Standby/Wartung/Tuning)
|
|
bool cxArmable = false; // Modus umschaltbar - auch im Standby und bei warmem Kessel (seit S3 5.3.5)
|
|
bool cxResting = false; // Zwangspause des Pumpenschutzes laeuft (Bezug laeuft weiter)
|
|
float cxMaxTemp = 0; // Freigabeschwelle in C
|
|
float cxTarget = 0; // Zielgewicht in g
|
|
float cxPreInfSec = 0; // Vorbenetzung in s (fuer die Phasenleiste des kalten Bezugs)
|
|
// Restliche Parameter fuer die Einstellseite am Display (seit S3 5.4.0)
|
|
float cxPreInfDuty = 0; // Pumpenleistung Vorbenetzung in %
|
|
float cxDuty = 0; // Pumpenleistung Hauptbezug in %
|
|
uint16_t cxPulseMs = 0; // Pulsperiode in ms
|
|
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
|
|
uint8_t cxBlock = 0;
|
|
// Transiente Meldung: 0=keine, 1=Start abgewiesen, 2=Bezug ohne Zulauf beendet,
|
|
// 3=Umschalten waehrend eines Bezugs abgelehnt
|
|
uint8_t cxNotice = 0;
|
|
|
|
// --- Gehaeusesensor ---
|
|
bool caseSensorEnabled = false;
|
|
bool caseTempDashboard = false;
|
|
uint8_t caseSensorType = 0; // 0 = Gehaeuse, 1 = Tassenablage
|
|
bool hasCaseTemp = false; // false => caseTemp war null
|
|
float caseTemp = 0;
|
|
|
|
// --- Service ---
|
|
int maintenanceInterval = 0;
|
|
uint32_t maintenanceIntervalCounter = 0;
|
|
uint8_t flushDurationSeconds = 0;
|
|
uint8_t steamFlushDurationSeconds = 0;
|
|
|
|
// --- Reinigungsassistent (Live-Status + Parameter) ---
|
|
bool cleaningActive = false;
|
|
bool cleaningWaiting = false; // heizt noch auf 93 C vor
|
|
bool cleaningBrewPhase = false; // true = Bezug, false = Pause
|
|
uint8_t cleaningCycle = 0; // aktueller Zyklus
|
|
uint8_t cleaningCycles = 0; // Gesamtzahl Zyklen
|
|
uint8_t cleaningBrewSeconds = 0; // Bezugsdauer je Zyklus
|
|
uint8_t cleaningPauseSeconds = 0; // Pausendauer je Zyklus
|
|
long cleaningPhaseRemainSec = 0; // verbleibende Sekunden der aktuellen Phase
|
|
|
|
// --- v2: Heizleistung / PID / AutoTune ---
|
|
float dutyW = 0, dutyD = 0;
|
|
float kpW = 0, kiW = 0, kdW = 0;
|
|
float kpD = 0, kiD = 0, kdD = 0;
|
|
bool autoTuneW = false, autoTuneD = false;
|
|
// Ergebnis/Grund des letzten Tuning-Laufs (0=Idle,1=laeuft,2=Erfolg,3=Failsafe,
|
|
// 4=degeneriert,5=Sensorfehler,6=Sicherheitsabsch.,7=manuell)
|
|
uint8_t autoTuneWStatus = 0, autoTuneDStatus = 0;
|
|
|
|
// --- v2: Netzwerk ---
|
|
bool wifiConnected = false;
|
|
bool apMode = false;
|
|
String ip;
|
|
String ssid;
|
|
int rssi = 0;
|
|
String timeStr; // "HH:MM" wenn NTP synchronisiert, sonst leer
|
|
|
|
// --- Verbindungsstatus (lokal, nicht von der S3) ---
|
|
bool linkUp = false; // UART-Verbindung steht (hello bestaetigt)
|
|
unsigned long lastRxMs = 0; // letzte empfangene Nachricht
|
|
};
|