Commit Graph
57 Commits
Author SHA1 Message Date
thomas 27a3ee840e Merge pull request 'feat(P4): 7-Zoll-Display JC1060P470C-I-W unterstützen (1.5.0)' (#26) from feat/7zoll-display-JC1060P470C into main 2026-08-22 02:36:52 +02:00
raw-designsandClaude Opus 5 92c1446824 feat(P4): 7-Zoll-Display JC1060P470C-I-W unterstützen (1.5.0)
Dieselbe Display-Firmware bedient jetzt wahlweise das bisherige 4,3-Zoll-Panel
JC4880P443C-I-W (ST7701, 480x800) oder das neue 7-Zoll-Panel JC1060P470C-I-W
(JD9165, 1024x600). Umgeschaltet wird über JC_PANEL_TYPE in config.h
(JC_PANEL_43 / JC_PANEL_70) oder per Compiler-Flag -DJC_PANEL_TYPE=70. Vorgabe
bleibt das 4,3-Zoll-Panel; dessen Verhalten ändert sich nicht.

- src/lcd/esp_lcd_jd9165.c/.h aus dem Hersteller-Paket übernommen;
  board_bringup.c legt je nach Panel DSI-Bus, DPI-Zeitbasis und Herstellertreiber an.
- pins_config.h liefert Auflösung, LCD-Reset (4,3": GPIO5, 7,0": GPIO27) und
  Ausrichtung panelabhängig. Das 7-Zoll-Panel ist nativ Querformat, deshalb
  entfallen dort die 270-Grad-Rotation und die PPA-Beschleunigung.
- lvgl_port_v9.h bezieht LVGL_PORT_H/V_RES aus pins_config.h statt fest 480/800.
- Der GT911 des 7-Zöllers meldet Rohkoordinaten im Raster 800x480 statt 1024x600.
  Die Umrechnung hängt am process_coordinates-Hook von esp_lcd_touch, damit die
  Herstellerdatei esp_lcd_touch_gt911.c unverändert bleibt.
- ui.cpp rechnet nicht mehr mit fest verdrahteten 480 Pixeln Höhe, sondern mit
  DISP_VER_RES. Layout und Schriften bleiben sonst unverändert.
- Hersteller-Paket des 7-Zöllers unter JC_Display_Firmware_7zoll/ abgelegt;
  Werkzeuge, Archive und mitgelieferte Fremdbibliotheken per .gitignore
  ausgeschlossen (587 MB im Original, 21 MB im Repo).

Kompiliertest ESP32-P4, beide Varianten:
  4,3": 1.173.768 B Flash (37 %), 322.880 B RAM (98 %)
  7,0": 1.138.752 B Flash (36 %), 322.600 B RAM (98 %)

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-22 02:35:40 +02:00
thomas 544c6ae3b8 Merge pull request 'fix: Auswahl beim Aufwecken über Touch entfiel manchmal (S3 5.6.3 / P4 1.4.2)' (#25) from fix/wake-abfrage-touch-pfad into main 2026-08-19 01:03:24 +02:00
raw-designsandClaude Opus 5 743c38e994 fix: Auswahl beim Aufwecken über Touch entfiel manchmal (S3 5.6.3 / P4 1.4.2)
Über den Schalter kam die Abfrage "Espresso oder Cold Extraction" zuverlässig,
über Antippen am Display nur manchmal. Ursache waren zwei unterschiedliche
Bedingungen für dieselbe Sache:

- askMode (zeigt die Auswahl im Dialog) verlangte zusätzlich cxArmable
- choiceRelevant (sendet "wakeEspresso" und schließt damit das Auswahlfenster
  der S3) verlangte es nicht

In der Lücke dazwischen zeigte der Dialog nur "Aufwecken", unterdrückte aber
trotzdem die Rückfrage der S3 - die Frage war auf beiden Seiten weg. Der
Schalterweg hatte diese Lücke nie, weil er allein an der S3 hängt.

P4: beide Stellen benutzen jetzt wake_choice_offered(). Bot der Dialog die
Auswahl nicht an, sendet er "deactivateStandby"; dann öffnet die S3 ihr
eigenes Auswahlfenster und die Frage kommt trotzdem.

S3: Die Fensterentscheidung ist als Bedingungskette geschrieben und hält
Quelle und Ergebnis des letzten Aufweckens fest. /Cold-Extraction zeigt das
an - die bisherige Live-Liste zeigt nur den jetzigen Stand, der beim
Nachsehen längst wieder ein anderer sein kann.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-19 01:02:30 +02:00
thomas 535f640bbd Merge pull request 'fix: Abfrage beim Aufwecken geht in beide Richtungen (S3 5.6.2 / P4 1.4.1)' (#24) from fix/cold-extraction-abfrage-beide-richtungen into main 2026-08-12 07:20:11 +02:00
raw-designsandClaude Opus 5 f8d51a57b7 fix: Abfrage beim Aufwecken geht in beide Richtungen (S3 5.6.2 / P4 1.4.1)
Die Abfrage erschien nicht, sobald der Cold-Extraction-Modus noch aktiv war — und
da er seit 5.3.1 persistent ist, war er das nach dem ersten kalten Bezug dauerhaft.
Damit erklärt sich, warum weder der Schalter- noch der Touch-Weg etwas zeigte.

Die Bedingung "Modus ist aus" war falsch gedacht ("sonst gibt es nichts zu fragen").
Die Auswahl muss in beide Richtungen gehen, also auch von kalt zurück auf Espresso.
Sonst hängt man nach dem ersten kalten Bezug im kalten Modus fest, ohne beim
Aufwecken je wieder gefragt zu werden.

- Bedingung aus beiden Öffnungspfaden entfernt (Standby-Übergang und Kaltstart).
- Das Fenster bleibt bei aktivem Modus offen; bisher schloss es sofort wieder.
- "wakeEspresso" beendet jetzt einen laufenden Modus, statt ihn nur nicht
  einzuschalten — sonst wäre die Auswahl eine Einbahnstraße.
- Diagnose auf /Cold-Extraction listet den Modus nicht mehr als Voraussetzung,
  sondern zeigt ihn als Ist-Zustand.
- P4: Der Cold-Knopf zeigt den Ist-Zustand ("aktiv lassen" und hervorgehoben, wenn
  der Modus läuft).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-12 07:19:50 +02:00
thomas 8432bd3f15 Merge pull request 'fix(S3): Auswahl beim Aufwecken auch nach Kaltstart + Diagnose der Bedingungen (5.6.1)' (#23) from fix/cold-extraction-auswahl-diagnose into main 2026-08-12 02:33:54 +02:00
raw-designsandClaude Opus 5 49bdc686c4 fix(S3): Auswahl beim Aufwecken auch nach Kaltstart + Diagnose der Bedingungen (5.6.1)
Die Abfrage hängt an fünf Bedingungen gleichzeitig (freigeschaltet, Abfrage
eingeschaltet, Display verbunden, Modus gerade aus, kein Wartungsmodus/Reinigung/
Tuning). Fehlt eine, passiert schlicht nichts, und von außen war nicht erkennbar
welche. Die Seite /Cold-Extraction zeigt sie jetzt live mit Haken bzw. Kreuz an,
dazu ob das Auswahlfenster gerade offen ist.

Zusätzlich eine echte Lücke geschlossen: Die Abfrage kam nur beim Standby-Übergang.
Wer die Maschine am Netzschalter einschaltet, durchläuft nie einen solchen Übergang
— dieser Weg war nicht abgedeckt. Jetzt öffnet das Fenster einmal pro Laufzeit auch
nach einem Kaltstart, sobald sich das Display gemeldet hat. Startet die Maschine in
den Standby hinein, bleibt es beim Standby-Übergang.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-12 02:33:35 +02:00
thomas 8dcebaa22f Merge pull request 'feat: Espresso/Cold-Auswahl bei jedem Aufwecken, auch per Schalter (S3 5.6.0 / P4 1.4.0)' (#22) from feat/cold-extraction-auswahl-nach-aufwecken into main 2026-08-12 01:47:09 +02:00
raw-designsandClaude Opus 5 7c1e485722 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>
2026-08-12 01:46:47 +02:00
thomas 7d14f94a72 Merge pull request 'feat: Abfrage Espresso oder Cold Extraction beim Aufwecken (S3 5.5.0 / P4 1.3.0)' (#21) from feat/cold-extraction-abfrage-beim-aufwecken into main 2026-08-12 01:02:58 +02:00
raw-designsandClaude Opus 5 11307d255b feat: Abfrage Espresso oder Cold Extraction beim Aufwecken (S3 5.5.0 / P4 1.3.0)
Der Aufweck-Dialog am Touch-Display wird zur Auswahl: "Womit aufwecken?" mit
"Espresso" (heizt normal auf) und "Cold Extraction (Wasser bleibt kalt)". Damit
lässt sich bei jedem Aufwecken neu entscheiden, ohne vorher die Web-UI zu bedienen.
Bei der kalten Variante wird der Modus scharf geschaltet, bevor der Standby endet —
der Wasserkreis heizt also gar nicht erst an.

Abschaltbar über die neue Einstellung "Abfrage beim Aufwecken" (EEPROM 982), zu
finden auf /Cold-Extraction und auf der Cold-Extraction-Seite des Displays. Ist sie
aus, erscheint wieder der bisherige Dialog. Ohne angeschlossenes Display oder bei
nicht freigeschalteter Funktion hat sie keine Wirkung. Neues Feld cxAskOnWake im
State und in saveBrew.

Dazu: Die Meldungstexte der kalten Extraktion sind jetzt mit echten Umlauten
geschrieben ("nicht möglich" statt "nicht moeglich"). Für das OLED übersetzt die
neue Hilfsfunktion oledUmlauts() sie beim Rendern nach CP437 — dort hätte UTF-8
sonst zwei Fehlzeichen je Umlaut ergeben, weshalb die Texte ursprünglich
transliteriert waren. Web-UI und Touch-Display stellen UTF-8 direkt dar.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-12 01:02:37 +02:00
thomas f1a8d8c175 Merge pull request 'fix: Zielgewicht bei Cold Extraction ueberall korrekt anzeigen (S3 5.4.1 / P4 1.2.1)' (#20) from fix/cold-extraction-zielgewicht-anzeige into main 2026-08-12 00:52:07 +02:00
raw-designsandClaude Opus 5 334896b9cf fix: Zielgewicht bei Cold Extraction überall korrekt anzeigen (S3 5.4.1 / P4 1.2.1)
Während einer kalten Extraktion stand als Zielgewicht überall noch der
Brew-by-Weight-Wert des normalen Espresso-Bezugs. OLED, Web-Dashboard und
Touch-Display griffen alle direkt auf brewByWeightTargetGrams zu — die kalte
Extraktion ersetzt Brew-by-Weight aber und stoppt nach coldExtractionTargetGrams.

Neue Hilfsfunktion activeTargetWeightGrams() liefert das Ziel des aktuellen bzw.
nächsten Bezugs. Das UART-Feld targetWeight führt jetzt diesen Wert; bbwTarget
bleibt unverändert die Roh-Einstellung, damit die Brew-Control-Seite weiter das
Richtige anzeigt.

Zusätzlich hing die Gewichtsanzeige selbst an "Brew-by-Weight aktiv" — das ist bei
kalter Extraktion typischerweise aus, obwohl ein Ziel existiert. OLED, Waage-Kachel
und Live-Bezugsschirm zeigen Gewicht und Fortschritt jetzt auch beim kalten Bezug.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-12 00:51:48 +02:00
thomas e8b1832fc1 Merge pull request 'feat: eigene Cold-Extraction-Seite in Web-UI und Display (S3 5.4.0 / P4 1.2.0)' (#19) from feat/cold-extraction-eigene-seite into main 2026-08-12 00:09:49 +02:00
raw-designsandClaude Opus 5 2d8f70ae37 feat: eigene Cold-Extraction-Seite in Web-UI und Display (S3 5.4.0 / P4 1.2.0)
Cold Extraction bekommt in beiden Oberflächen einen eigenen Menüpunkt statt eines
angehängten Blocks auf der Brew-Control-Seite. Die Parameter sind damit erstmals
auch am Touch-Display änderbar.

S3: neue Seite /Cold-Extraction, gegliedert in Grundeinstellung, Vorbenetzung,
Hauptbezug, Bezugsende und Pumpenschutz, jeder Abschnitt mit kurzer Begründung.
/Brew-Control verweist nur noch darauf. Das UART-Kommando saveBrew akzeptiert jetzt
die cx-Felder, und das State-JSON liefert die restlichen Parameter mit, damit das
Display seine Felder vorbelegen kann.

Wichtig: Der Speicher-Handler von /Brew-Control wertet die cx-Felder nicht mehr aus.
Er tat es bisher, und nach dem Verschieben der Checkbox hätte ein Speichern dort die
Freischaltung abgeschaltet, weil das Feld im Formular fehlt.

P4: neue Seite "Cold Extraction" mit allen Parametern; der Modus-Schalter ist von der
Temperatur-Seite dorthin umgezogen, damit es nur eine Stelle gibt. Die Brew-Control-
Seite ist neu gegliedert: jede Funktion in einer eigenen Karte mit Titel und einer
Zeile, die erklärt was sie tut, statt einer durchlaufenden Liste unter
Zwischenüberschriften. Neues Hilfsmakro group_card() für beide Seiten.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-12 00:09:23 +02:00
thomas 537f1d4c20 Merge pull request 'fix(S3): Cold Extraction benetzt sanft statt mit voller Leistung (5.3.6)' (#18) from fix/cold-extraction-sanfte-vorbenetzung into main 2026-08-11 23:41:43 +02:00
raw-designsandClaude Opus 5 2cf375a2b4 fix(S3): Cold Extraction benetzt jetzt sanft statt mit voller Leistung (5.3.6)
Messung an der Maschine: Nach 7 s Vorbenetzung kommen heiß 1-2 sirupartige Tropfen,
kalt bei voller Pumpenleistung rund 10 g dünne Brühe ohne Crema — etwa zehnfacher
Durchfluss trotz dreifacher Viskosität.

Die Ursache ist nicht die Viskosität, sondern das Kaffeebett: Kaltes Mehl quillt
nicht, ist schlecht benetzbar, es wandert kein Feinanteil und es lösen sich kaum
Feststoffe, die das Bett verdichten. Volle Leistung auf den trockenen kalten Puck
legt deshalb sofort Kanäle an, die sich — anders als bei heißem Bezug — nie wieder
schließen; der restliche Bezug läuft daran vorbei statt zu extrahieren.

Vorbenetzung und Hauptbezug pulsen jetzt beide, nur mit unterschiedlicher Leistung.
Neue Einstellung "Pumpenleistung Vorbenetzung" (Standard 10 %), Standard im
Hauptbezug von 30 % auf 20 % gesenkt. Bestehende Installationen behalten ihre Werte;
das neue Feld greift beim Update automatisch auf den Default zurück.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-11 23:41:23 +02:00
thomas e33de56edc Merge pull request 'feat: Cold Extraction im Standby scharf schaltbar (S3 5.3.5 / P4 1.1.3)' (#17) from feat/cold-extraction-im-standby into main 2026-08-11 03:01:10 +02:00
raw-designsandClaude Opus 5 9b91543435 feat: Cold Extraction im Standby scharf schaltbar (S3 5.3.5 / P4 1.1.3)
"Standby aktiv" und "Kessel zu warm" galten bisher auch fürs Aktivieren. Das war
falsch herum gedacht: Der Modus schaltet die Heizung AB, man kam aber erst an den
Schalter, nachdem die Maschine aufgeweckt war und schon zu heizen begonnen hatte —
genau der Ablauf, den die Funktion vermeiden soll.

Scharfschalten und Beziehen sind jetzt getrennt:
- Scharfschalten (neues State-Feld cxArmable): blockiert nur durch fehlende
  Freischaltung, Wartungsmodus, Reinigungsassistent, PID-Tuning oder einen
  laufenden Bezug/Spülvorgang.
- Bezug (unverändert cxAllowed): zusätzlich kein Standby, Kessel unter der
  Freigabeschwelle, gültiger Sensorwert.

Ist der Modus scharf, der Bezug aber gesperrt, sagen Web-UI und Display das jetzt
ausdrücklich. Bei Aktivierung mit warmem Kessel geht die Heizung sofort aus, die
Rückmeldung nennt die Sperre bis zum Unterschreiten der Schwelle.

P4: Der Aufweck-Dialog bekommt "Aufwecken mit Cold Extraction" — sendet
startColdExtraction vor deactivateStandby, damit der Wasserkreis gar nicht erst
anheizt. Der Schalter hängt jetzt an cxArmable; bei älterer S3-Firmware fällt das
Feld auf cxEnabled zurück und bleibt bedienbar.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-11 02:59:22 +02:00
thomas 6dd3f1eaf2 Merge pull request 'feat: Cold Extraction warnt bei fehlender Waage (S3 5.3.4 / P4 1.1.2)' (#16) from feat/cold-extraction-waagen-hinweis into main 2026-08-11 02:07:35 +02:00
raw-designsandClaude Opus 5 b6155acafe feat: Cold Extraction warnt bei fehlender Waage (S3 5.3.4 / P4 1.1.2)
Ohne aktive und verbundene Waage greifen weder das Zielgewicht noch die
Stillstands-Erkennung — der Bezug endet dann erst nach der maximalen Bezugsdauer,
die damit faktisch zur Dosierung wird. Bisher passierte diese Degradierung
stillschweigend.

Die Funktion bleibt ohne Waage bewusst nutzbar (Zeitsteuerung als Rückfallebene),
damit ein kurzzeitig abgemeldeter HX711 die kalte Extraktion nicht komplett
blockiert. Angezeigt wird der Zustand jetzt an vier Stellen: dauerhafter
Warnhinweis auf /Brew-Control (Zielgewicht-Feld zusätzlich als "nur mit Waage
wirksam" beschriftet), Hinweiszeile unter dem Dashboard-Schalter, Statustext
"Cold Extraction bereit (ohne Waage: Zeitsteuerung)" und eine einmalige Meldung
beim Aktivieren.

P4: Statuszeile zeigt "ohne Waage, Ende nach Zeit" in Warnfarbe statt des blauen
Normalhinweises; Erklärzeile am Schalter und Parameter-Anzeige auf der Brew-Seite
ergänzen den Hinweis und nennen bei aktivem Modus ohne Waage die Zeit statt des
Zielgewichts. Neuer cxNotice-Code 4 (additiv, Protokoll bleibt v2).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-11 02:05:50 +02:00
thomas 4cc9ceea7c Merge pull request 'fix(S3): Cold Extraction brach waehrend der Vorbenetzung ab (5.3.3)' (#15) from fix/cold-extraction-vorbenetzung into main 2026-08-11 01:55:31 +02:00
raw-designsandClaude Opus 5 881acec3df fix(S3): Cold Extraction brach während der Vorbenetzung ab (5.3.3)
Die Stillstands-Erkennung lief bereits während der Vorbenetzung mit. In dieser
Phase sättigt der Puck aber erst, in der Tasse kommt naturgemäß nichts an — bei
einer Vorbenetzung länger als die 15 s Stillstands-Zeit wurde deshalb jeder kalte
Bezug mit "kein Zulauf" abgebrochen. Mit dem bisherigen Standard von 30 s wäre das
ausnahmslos passiert; die Funktion war mit aktiver Waage unbenutzbar. Die
Erkennung startet jetzt erst mit dem Hauptbezug.

Dazu der Standard der Vorbenetzung von 30 s auf 10 s: Die Pumpe läuft in dieser
Phase bewusst ungepulst auf voller Leistung. Heiß kommt der erste Tropfen nach
etwa 7 s, kalt (rund dreifache Viskosität) entsprechend später — 30 s wären längst
voller Bezug bei vollem Druck gewesen, und die Hälfte des Pumpen-Laufzeitbudgets
wäre vor dem eigentlichen Bezug verbraucht. Bestehende Installationen behalten
ihren gespeicherten Wert.

Die Beschriftung auf /Brew-Control sagt jetzt ausdrücklich, dass die Pumpe während
der Vorbenetzung durchläuft und erst im Hauptbezug gepulst wird.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-11 01:53:48 +02:00
thomas bc78a10505 Merge pull request 'fix(P4): Compiler-Warnungen des Display-Builds beseitigt (1.1.1)' (#14) from fix/p4-compiler-warnungen into main 2026-08-11 01:23:02 +02:00
raw-designsandClaude Opus 5 1f8cce48aa fix(P4): Compiler-Warnungen des Display-Builds beseitigt (1.1.1)
Von 68 Warnungen (arduino-cli --warnings all) auf eine einzige, die im
ESP32-Core-SDK steckt und nicht im Projekt behebbar ist.

- LV_FS_DEFAULT_DRIVE_LETTER heißt ab LVGL 9.3 LV_FS_DEFAULT_DRIVER_LETTER. Der
  alte Name funktionierte weiter, löste aber in lv_api_map_v9_1.h ein #warning in
  JEDER Übersetzungseinheit aus, die lvgl.h einbindet — allein rund 60 Warnungen
  pro Build, die alles andere zugedeckt haben. In lv_conf.h umbenannt.
- LV_PART_* und LV_STATE_* sind in LVGL 9 verschiedene Enum-Typen; die direkte
  |-Verknüpfung ist in C++20 abgekündigt. Neues Makro TH_SEL(part, state) in
  theme.h castet beide auf lv_style_selector_t (ohnehin uint32_t), 5 Stellen.
- Bug-Fix: Der Puffer der Cold-Extraction-Infozeile auf der Brew-Seite war mit 192
  Bytes zu klein für den ~205 Zeichen langen Text (das "°" zählt doppelt), die
  letzte Zeile wurde abgeschnitten. Jetzt 256 Bytes.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-11 01:20:49 +02:00
thomas 1933a41e64 Merge pull request 'feat(P4): Cold Extraction am Touch-Display + RX-Zeilenlimit-Fix (1.1.0 / S3 5.3.2)' (#13) from feat/cold-extraction-p4 into main 2026-08-10 23:58:06 +02:00
raw-designsandClaude Opus 5 e8edc8eb30 feat(P4): Cold Extraction am Touch-Display + RX-Zeilenlimit-Fix (1.1.0 / S3 5.3.2)
Display-Seite der kalten Extraktion: Schalter unter "Modi" auf der Temperatur-Seite
mit Erklärzeile, eigener Slot in der Statuszeile direkt hinter der
Sicherheitsmeldung, "Cold Extraction - Heizen aus" in der Wasser-Kachel statt eines
unerreichbaren Sollwerts, unterdrückter Aufheiz-Countdown, "Vorbenetzung" als erste
Phase des kalten Bezugs, Parameter-Anzeige auf der Brew-Seite und "(kalt)"-Markierung
in der Statistik (kalte Bezüge zählen nicht in die mittlere Dauer).

Bug-Fix P4: PROTO_RX_LINE_MAX lag bei 2048 Bytes, während die State-Zeile der S3
bereits rund 2,1 KB erreicht. Mit langem Status-, Profil- oder SSID-Text lag sie
darüber — dann wurde die ganze Zeile verworfen und das Display fror auf dem letzten
Stand ein, ohne dass die Verbindung als tot erkannt wurde. Limit jetzt 4096 Bytes;
der Puffer bleibt bei 2 KB reserviert, weil der interne RAM knapp ist und eine
Arduino-String nicht ins PSRAM alloziert werden kann.

S3 5.3.2: Sperrgrund und transiente Meldung gehen als Codes (cxBlock/cxNotice) statt
als Klartext ans Display, dazu cxPreInf für die Phasenleiste. Der bis zu 110 Byte
lange Freitext hätte die State-Zeile über das Zeilenlimit gedrückt; die Texte rendert
jetzt das Display, analog zur Trennung statusKey/statusText. Auf dem OLED und in den
ack-Antworten bleibt der Klartext unverändert.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-10 23:56:17 +02:00
thomas 57b7969f8b Merge pull request 'feat(S3): Cold Extraction ueberlebt Standby und Neustart (5.3.1)' (#12) from feat/cold-extraction-persistent into main 2026-08-10 21:33:40 +02:00
raw-designsandClaude Opus 5 c697e65a01 feat(S3): Cold Extraction überlebt Standby und Neustart (5.3.1)
Der Modus wird im EEPROM (Adresse 977) gespeichert und beim Start wieder
übernommen, sofern die Funktion auf /Brew-Control freigeschaltet ist. Standby
beendet ihn nicht mehr, sondern verwirft nur die Laufzeitdaten.

Grund: Wer nur kalte Bezüge machen will, musste den Modus nach jedem Standby
neu einschalten. Bis dahin heizte die Maschine bereits auf und war für die
nächste kalte Extraktion zu warm — man musste auf das Abkühlen warten, also
genau die Situation, die der Modus vermeiden soll.

Der Modus endet nur noch durch explizites Ausschalten, durch Entzug der
Freischaltung oder durch einen Werksreset.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-10 21:31:59 +02:00
thomas d7a1a8dee2 Merge pull request 'feat(S3): Cold Extraction (kalte Extraktion) mit Temperatur-Freigabe (5.3.0)' (#11) from feat/cold-extraction into main 2026-08-10 21:04:17 +02:00
raw-designsandClaude Opus 5 db1b080dc4 feat(S3): Cold Extraction (kalte Extraktion) mit Temperatur-Freigabe (5.3.0)
Kalte Extraktion ohne Kessel-Bypass: Da kaltes Wasser nur bei kaltem Wasserkessel
am Puck ankommt, wird die Funktion über eine Temperaturschwelle freigegeben
(Standard 30 °C, 10–40 °C einstellbar). Solange der Modus aktiv ist, heizt der
Wasserkreis nicht (SSR gesperrt, Stellgröße und dutyW-Telemetrie auf 0, I-Anteil
eingefroren, Feed-Forward-Boost aus); der Dampfkreis bleibt unberührt.

Die Freigabe wird vor jedem Bezug neu geprüft, weil der weiter heizende
Dampfkessel den Wasserkessel über die Zeit über die Schwelle bringen kann. Ein
abgewiesener Start meldet den Grund auf OLED, Touch-Display und Web-Dashboard;
ein laufender Bezug wird nie abgebrochen. 5 °C Hysterese, Sensorfehler sperrt.

Fluss über Pumpen-Pulsung nach einer Vorbenetzung mit voller Leistung; Ende über
Zielgewicht oder Timeout. Brew-by-Time/Weight und FlowGuard sind während einer
kalten Extraktion außer Kraft, da FlowGuard sonst um denselben Pumpen-Ausgang
konkurrieren würde. Pumpenschutz über kumulierte Einschaltzeit mit Zwangspause
plus Stillstands-Erkennung bei aktiver Waage.

Kalte Bezüge werden im CSV-Log mit einem vierten Feld "C" gekennzeichnet, zählen
in allen Stückzahlen mit, bleiben aber aus der durchschnittlichen Bezugsdauer
heraus. Neue additive State-Felder cx* im UART-JSON (Protokoll bleibt v2) und
neuer statusKey "coldextraction".

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-10 21:02:11 +02:00
thomas 5a1e8d4b50 Merge pull request 'feat(S3): Feed-Forward-Boost bei Bezug für den Wasserkessel (5.2.0)' (#10) from feat/feed-forward-bei-bezug into main 2026-07-18 04:11:40 +02:00
raw-designsandClaude Fable 5 4f840173a9 feat(S3): Feed-Forward-Boost bei Bezug für den Wasserkessel (5.2.0)
Während eines Bezugs strömt kaltes Wasser in den Kessel; die PID reagiert
erst auf den verzögert gemessenen Temperaturabfall. Der neue Feed-Forward
schaltet der Heizung sofort einen einstellbaren Leistungs-Boost auf
(0-100 % der Fenstergröße, 0 % = aus), die PID regelt nur den Restfehler.

- Zustandslose Aufschaltung in der SSR-Fensterlogik (effectiveOutputWasserMs),
  gedeckelt auf die Fenstergröße; Duty-Telemetrie (dutyW) zeigt den Boost mit
- Optional: I-Anteil der Wasser-PID während des Bezugs einfrieren
  (zentral in der PID-Schleife verwaltet, applyPidWasserTunings-Helper)
- Nur bei echten Bezügen (Hardware/Software-Shot), nicht bei Spülen,
  Wartungsmodus oder AutoTune; Sicherheitslogik unverändert
- Web-UI: neue Sektion „Feed-Forward bei Bezug (Wasser)“ auf /PID;
  EEPROM 944/945, bewusst kein Profilfeld (maschinenabhängig)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-18 04:09:13 +02:00
thomas 6371b22683 Merge pull request 'fix(S3): „Aktives Profil"-Anzeige auf der Profil-Seite ins Karten-Layout eingefügt' (#9) from fix/profilseite-aktiv-anzeige-layout into main 2026-07-14 00:15:30 +02:00
raw-designsandClaude Fable 5 de2d0635b2 fix(S3): „Aktives Profil"-Anzeige auf der Profil-Seite ins Karten-Layout eingefügt
Die Zeile stand linksbündig ohne max-width außerhalb der zentrierten
Seitenstruktur. Jetzt im status-message-Stil der Seite (zentriert,
max. 600 px, dezenter neutraler Rahmen), Profilname fett. Version 5.1.2.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 00:14:53 +02:00
thomas 801a659b0c Merge pull request 'feat(P4): Profil-Schnellwahl im Header + Anzeige des aktiven Profils' (#8) from feat/profil-schnellwahl-p4 into main 2026-07-13 20:55:47 +02:00
raw-designsandClaude Fable 5 d97e4c34d5 feat(P4): Profil-Schnellwahl im Header + Anzeige des aktiven Profils
Neuer Profil-Chip im Header (alle Seiten): zeigt das zuletzt geladene
bzw. gespeicherte Profil aus den neuen S3-State-Feldern profile/profDirty
(S3 ab 5.1.1), „*" = seitdem geänderte Einstellungen. Antippen öffnet
ein Schnellwahl-Overlay mit allen Profilen (aktives mit Häkchen und
Akzentfarbe); ein Tap lädt direkt per loadProfile. Profile-Seite
markiert das aktive Profil in der Liste. Bei älterer S3-Firmware bleibt
der Chip unsichtbar. Version 1.0.13, Protokoll-Doku ergänzt.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-13 20:55:10 +02:00
thomas 00a4c80b13 Merge pull request 'feat(S3): Aktives Profil führen und anzeigen — Grundlage für Profil-Schnellwahl am Display' (#7) from feat/aktives-profil-anzeige-s3 into main 2026-07-13 20:48:40 +02:00
raw-designsandClaude Fable 5 a1431a9d42 feat(S3): Aktives Profil führen und anzeigen — Grundlage für Profil-Schnellwahl am Display
Die Steuerung merkt sich das zuletzt geladene bzw. gespeicherte Profil
dauerhaft im EEPROM (Adressen 912-943). Profil-relevante Änderungen
(Setpoints, PID inkl. AutoTune, Boost, Eco, Brew-Control, Piezo,
Fast-Heat-Up) markieren das Profil als „geändert"; reine Anzeige-/
Systemeinstellungen bewusst nicht. Löschen des aktiven Profils und
Werksreset setzen die Anzeige zurück.

Sichtbar in der Web-UI (Dashboard + Profil-Seite) und als neue additive
State-Felder "profile"/"profDirty" im UART-JSON für das Touch-Display.
Version 5.1.1.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-13 20:47:59 +02:00
thomas d9bc31b555 Merge pull request 'feat(S3): Display-Auswahl über die Web-UI statt Compile-Schalter — Default „Ohne Display"' (#6) from feat/display-auswahl-über-web-ui into main 2026-07-13 01:56:25 +02:00
raw-designsandClaude Fable 5 5691a4c04f feat(S3): Display-Auswahl in die Web-UI verlegt — Default „Ohne Display" für sicheren Start
Compile-Schalter ENABLE_DISPLAY entfällt: Der Display-Typ (Ohne / OLED SH1106 /
UART-Touch) wird jetzt zur Laufzeit unter /Sensoren gewählt, im EEPROM (Adresse 911)
gespeichert und ohne Neustart übernommen. Vor der OLED-Initialisierung prüft eine
I2C-Probe (0x3C), ob das Display angeschlossen ist — ohne Antwort bleibt die Anzeige
deaktiviert und die Steuerung bootet sicher weiter. Die Touch-UART (Serial1) wird nur
noch bei gewähltem UART-Touch-Display initialisiert und bedient.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-13 01:54:37 +02:00
thomas f8df6f85cd Merge pull request 'fix(P4): Heizleistungs-Kurven flackerten in großen Zeitfenstern — Bucket-Mittelung statt Einzelsample' (#5) from fix/verlauf-duty-dezimierung-mitteln into main 2026-07-13 01:27:13 +02:00
raw-designsandClaude Fable 5 f43375e991 fix(P4): Heizleistungs-Kurven flackerten in großen Zeitfenstern — Bucket-Mittelung statt Einzelsample
Die Dezimierung im Verlauf-Chart pickte pro Punkt ein Einzelsample; das
Abtast-Raster hing an g_histPos und wanderte mit jedem Sekundentick um
eine Position. Die schnell schaltende Heizleistung (PWM) sprang dadurch
sichtbar zwischen zwei Kurvenbildern hin und her. Jetzt wird über den
gesamten stride-Bucket gemittelt — Bild steht ruhig, Leistungs-Kurve
zeigt die echte mittlere Heizleistung. Version 1.0.12.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-13 01:26:26 +02:00
thomas 92ef4fbfb6 Merge pull request 'fix(P4): Verlaufs-Historie ins PSRAM verlagern — interner RAM lief über' (#4) from fix/verlaufs-historie-ins-psram into main 2026-07-12 21:17:13 +02:00
raw-designsandClaude Fable 5 fd6ec5371b fix(P4): Verlaufs-Historie ins PSRAM verlagern — interner RAM lief über
Die 60-min-Ringpuffer der Verlauf-Seite (~29 KB) lagen als statische Arrays
im internen RAM und sprengten das Board-Limit (Linker: 107 % dynamischer
Speicher, Build brach ab). Historie jetzt als ein Block per heap_caps_malloc
im PSRAM (Fallback MALLOC_CAP_8BIT), wie die LVGL-Framebuffer; alle Zugriffe
gegen Allokationsfehler abgesichert (Chart bliebe dann leer).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-12 21:16:37 +02:00
thomas ea64e7de04 Merge pull request 'fix(P4): Shot-Zusammenfassung — größere Abstände zwischen Dauer/Gewicht/Flow' (#3) from fix/shot-zusammenfassung-abstände into main 2026-07-12 21:12:32 +02:00
raw-designsandClaude Fable 5 7d240cd13e fix(P4): Shot-Zusammenfassung — größere Abstände zwischen Dauer/Gewicht/Flow
Karte von 460 auf 560 px verbreitert und Spaltenabstand von 10 auf 28 px
erhöht; die drei großen Werte standen zu nahe beisammen und waren schlecht
lesbar.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-12 21:12:01 +02:00
thomas 27dabd884a Merge pull request 'feat(P4): Verlauf mit Zeitfenster, Soll-Linien und Heizleistung; PID-Tuning-Live-Karte' (#2) from feature/verlauf-zeitfenster-und-tuning-karte into main 2026-07-12 18:47:52 +02:00
raw-designsandClaude Fable 5 dc6cbbb191 feat(P4): Verlauf mit Zeitfenster, Soll-Linien und Heizleistung; PID-Tuning-Live-Karte
- Verlauf-Seite: umschaltbares Zeitfenster 2/10/30/60 min über 1-s-Ringpuffer
  (60 min Historie, 120 Chart-Punkte dezimiert), Fensterwahl in NVS
- Gestrichelte Soll-Linien für Wasser/Dampf; Y-Skala bezieht Soll-Werte nur
  sichtbarer Kreise ein
- Heizleistung (Duty) Wasser/Dampf als zuschaltbare Zusatzkurven auf
  Sekundärachse 0–100 % inkl. Live-Legende, Einstellung in NVS
- Temperaturkurven in Zehntelgrad statt ganzzahlig (Schwingungen ablesbar)
- PID-AutoTune-Live-Karte auf der Verlauf-Seite: Laufzeit, heizt/kühlt ab,
  Schwingungshub je Kreis; nach Ende ~30 s Ergebnis farbcodiert
- PID-Tuning-Statusmeldung antippbar -> springt zur Verlauf-Seite
- Display-Firmware 1.0.11 + Changelog

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-12 18:43:52 +02:00