Der Ordner hieß JC_Display_Firmware, bedient seit 1.6.0 aber auch das Waveshare 7inch DSI LCD (H) am ESP32-P4-Pico. Der Name führte in die Irre. - JC_Display_Firmware/ -> P4_Display_Firmware/ (samt Sketch, den Arduino gleichnamig zum Ordner verlangt) - Doku/JC-Display_UART-Protokoll.md -> Doku/P4-Display_UART-Protokoll.md, Verweise und Titel angepasst - Verweise in CLAUDE.md, README und Quelltextköpfen nachgezogen Nur Namen und Pfade, keine Logikänderung. Der Vendor-Ordner JC_Display_Firmware_7zoll/ behält seinen Namen, ebenso die Bezeichner JC_PANEL_TYPE/jc_board_bringup im Quelltext. Enthält außerdem die bereits im Arbeitsverzeichnis liegende, noch nicht committete Ergänzung des Git-Workflows in CLAUDE.md (PRs über die Gitea-API statt der hängenden tea-CLI). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018QoLDQeUh1dCQz7yYZVb4Y
92 lines
4.1 KiB
C++
92 lines
4.1 KiB
C++
// =====================================================================================
|
|
// protocol_client.h - UART-Protokoll-Client (P4-Seite)
|
|
// =====================================================================================
|
|
// Implementiert die Display-Seite des in Doku/P4-Display_UART-Protokoll.md (v2)
|
|
// beschriebenen Protokolls:
|
|
// - empfaengt : state / ack / error / profiles / profileDetails / hello
|
|
// - sendet : hello / ping / getState / listProfiles / loadProfile / action /
|
|
// saveBrew / saveService / saveSensor / setPid /
|
|
// startAutotune / stopAutotune / getProfileDetails
|
|
// - Heartbeat, hello-Handshake, Link-Timeout-Ueberwachung
|
|
//
|
|
// Parsen: ArduinoJson (der ESP32-P4 hat reichlich RAM/PSRAM).
|
|
// =====================================================================================
|
|
|
|
#pragma once
|
|
|
|
#include <Arduino.h>
|
|
#include "config.h"
|
|
#include "machine_state.h"
|
|
|
|
class ProtocolClient {
|
|
public:
|
|
// Callback-Typen
|
|
typedef void (*StateCb)(const MachineState& st);
|
|
typedef void (*ProfilesCb)(const String profiles[], int count);
|
|
typedef void (*RawJsonCb)(const String& json); // profileDetails (Roh-JSON)
|
|
typedef void (*AckCb)(uint32_t id, bool ok, const String& message);
|
|
|
|
explicit ProtocolClient(MachineState& state) : _state(state) {}
|
|
|
|
void begin();
|
|
void loop();
|
|
|
|
bool linkUp() const { return _state.linkUp; }
|
|
|
|
// --- Diagnose-Zaehler (fuer On-Screen-Debug) ---
|
|
unsigned long rxByteCount = 0; // gesamt empfangene Bytes (auch unvollstaendige)
|
|
unsigned long rxLineCount = 0; // vollstaendige Zeilen
|
|
unsigned long txCmdCount = 0; // gesendete Kommandos
|
|
unsigned long helloCount = 0; // gesendete hello
|
|
unsigned long parseErrorCount = 0; // JSON-Parse-Fehler
|
|
String lastRxLine; // zuletzt empfangene Rohzeile
|
|
|
|
// --- Callbacks registrieren ---
|
|
void onState(StateCb cb) { _stateCb = cb; }
|
|
void onProfiles(ProfilesCb cb) { _profilesCb = cb; }
|
|
void onProfileDetails(RawJsonCb cb) { _profileDetailsCb = cb; }
|
|
void onUsageStats(RawJsonCb cb) { _usageStatsCb = cb; } // Antwort auf getUsageStats (Roh-JSON)
|
|
void onWifiNetworks(RawJsonCb cb) { _wifiNetworksCb = cb; } // Antwort auf scanWifi (Roh-JSON)
|
|
void onOta(RawJsonCb cb) { _otaCb = cb; } // OTA-Nachrichten von der S3 (Roh-JSON)
|
|
void onAck(AckCb cb) { _ackCb = cb; }
|
|
|
|
// --- Kommandos (Rueckgabe: vergebene id) ---
|
|
uint32_t sendHello();
|
|
uint32_t sendPing();
|
|
uint32_t sendGetState();
|
|
uint32_t sendListProfiles();
|
|
uint32_t sendGetUsageStats(); // Nutzungsstatistik anfordern
|
|
uint32_t sendLoadProfile(const String& profile);
|
|
uint32_t sendGetProfileDetails(const String& profile);
|
|
uint32_t sendAction(const String& action, const String& value = "");
|
|
uint32_t sendSetPid(const String& fieldsJson); // z.B. "\"kpW\":5.0,\"kiW\":0.2"
|
|
uint32_t sendStartAutotune(const String& target);// "water" | "steam"
|
|
uint32_t sendStopAutotune();
|
|
uint32_t sendScanWifi(); // WLAN-Scan anstossen
|
|
uint32_t sendSetWifi(const String& ssid, const String& password); // verbinden
|
|
// Frei-Form: zusaetzliche Felder als bereits serialisiertes JSON-Fragment ohne
|
|
// aeussere Klammern, z.B. sendCommand("saveBrew", "\"bbtEnabled\":true,\"bbtSecs\":25");
|
|
uint32_t sendCommand(const String& op, const String& extraFields = "");
|
|
|
|
private:
|
|
void handleLine(const String& line);
|
|
void applyState(const String& json);
|
|
void applyProfiles(const String& json);
|
|
void maintainLink();
|
|
|
|
MachineState& _state;
|
|
String _rxBuf;
|
|
bool _rxOverflow = false;
|
|
uint32_t _nextId = 1;
|
|
unsigned long _lastHeartbeatMs = 0;
|
|
unsigned long _lastHelloMs = 0;
|
|
|
|
StateCb _stateCb = nullptr;
|
|
ProfilesCb _profilesCb = nullptr;
|
|
RawJsonCb _profileDetailsCb = nullptr;
|
|
RawJsonCb _usageStatsCb = nullptr;
|
|
RawJsonCb _wifiNetworksCb = nullptr;
|
|
RawJsonCb _otaCb = nullptr;
|
|
AckCb _ackCb = nullptr;
|
|
};
|