feat(mqtt): Phase 6 - MqttClient implementiert (PubSubClient, publishSession, Heartbeat, Reset-Subscribe)
This commit is contained in:
parent
f389a7deea
commit
71ef2c7ad0
|
|
@ -52,7 +52,7 @@
|
|||
// -----------------------------------------------------------------------------
|
||||
// MQTT – Default-Konfiguration (überschreibbar aus NVS)
|
||||
// -----------------------------------------------------------------------------
|
||||
#define DEFAULT_MQTT_BROKER "192.168.1.1"
|
||||
#define DEFAULT_MQTT_BROKER "broker.hivemq.com" // Oeffentlicher Testbroker
|
||||
#define DEFAULT_MQTT_PORT 1883
|
||||
#define DEFAULT_MQTT_USER ""
|
||||
#define DEFAULT_MQTT_PASSWORD ""
|
||||
|
|
|
|||
|
|
@ -81,6 +81,12 @@ public:
|
|||
// Gesamtzeit (NVS + RAM-Session) auf 0 zuruecksetzen (Wartungsreset)
|
||||
void resetTotal();
|
||||
|
||||
// Prueft ob seit dem letzten Aufruf ein Burst beendet wurde ("consume").
|
||||
// Gibt true zurueck, wenn ein neuer Burst abgeschlossen ist – danach
|
||||
// kann getLastBurstSeconds() + getTotalMinutes() sicher gelesen werden.
|
||||
// Wird in main.cpp fuer mqttClient.publishSession() verwendet.
|
||||
bool consumeBurstEnd();
|
||||
|
||||
// Debug-Ausgabe auf Serial
|
||||
void printToSerial() const;
|
||||
|
||||
|
|
@ -100,6 +106,7 @@ private:
|
|||
int _sessionNetSec; // Netto-Sekunden der Session (RAM, 0 nach begin/resetSession)
|
||||
float _totalMinutesBase; // NVS-Gesamtzeit (nach jedem Burst aktualisiert)
|
||||
int _lastBurstSec; // Netto-Sekunden des letzten abgeschlossenen Bursts
|
||||
bool _burstEndPending; // true = Burst gerade beendet, noch nicht consumed
|
||||
|
||||
// ---- Hilfsmethoden ------------------------------------------------------
|
||||
bool readRaw() const; // GPIO lesen + Polaritaet anwenden
|
||||
|
|
|
|||
67
include/mqtt_client.h
Normal file
67
include/mqtt_client.h
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
#pragma once
|
||||
|
||||
// =============================================================================
|
||||
// mqtt_client.h - MQTT-Verbindung, Publish und Subscribe
|
||||
// Projekt: MQTT-Display LaserCutter
|
||||
//
|
||||
// Wrapper um PubSubClient mit Non-Blocking Reconnect.
|
||||
//
|
||||
// Publish:
|
||||
// publishSession() - beim Ende eines Laser-Bursts (aus LaserTracker)
|
||||
// publishStatus() - Heartbeat alle MQTT_HEARTBEAT_MS
|
||||
//
|
||||
// Subscribe:
|
||||
// lasercutter/reset - Payload "1" -> laserTracker.resetTotal()
|
||||
//
|
||||
// Verwendung:
|
||||
// mqttClient.begin(); // einmalig in setup(), nach WiFi-Connect
|
||||
// mqttClient.loop(); // in jedem loop()-Aufruf
|
||||
// =============================================================================
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <PubSubClient.h>
|
||||
#include <WiFi.h>
|
||||
#include "config.h"
|
||||
#include "settings.h"
|
||||
|
||||
class MqttClient {
|
||||
public:
|
||||
MqttClient();
|
||||
|
||||
// MQTT konfigurieren und erste Verbindung versuchen (einmalig in setup())
|
||||
void begin();
|
||||
|
||||
// Verbindung halten, Reconnect, Heartbeat - in jedem loop()-Aufruf
|
||||
void loop();
|
||||
|
||||
// Publish: Session-Ende (wird von LaserTracker-Logik in main aufgerufen)
|
||||
// lastBurstSec : Netto-Sekunden des letzten Bursts
|
||||
// totalMinutes : Gesamtzeit inkl. aktuelle Session (aus LaserTracker)
|
||||
// gratisSec : konfigurierte Gratiszeit
|
||||
void publishSession(int lastBurstSec, float totalMinutes, int gratisSec);
|
||||
|
||||
// Verbindungsstatus
|
||||
bool isConnected();
|
||||
|
||||
// Debug-Ausgabe auf Serial
|
||||
void printToSerial();
|
||||
|
||||
private:
|
||||
WiFiClient _wifiClient;
|
||||
PubSubClient _client;
|
||||
|
||||
uint32_t _lastReconnectMs;
|
||||
uint32_t _lastHeartbeatMs;
|
||||
|
||||
// Verbindungsaufbau (intern, non-blocking: gibt true zurueck wenn verbunden)
|
||||
bool reconnect();
|
||||
|
||||
// Heartbeat-Publish (lasercutter/status)
|
||||
void publishHeartbeat();
|
||||
|
||||
// Callback fuer eingehende Nachrichten (static wegen PubSubClient-API)
|
||||
static void onMessage(const char* topic, byte* payload, unsigned int length);
|
||||
};
|
||||
|
||||
// Globale Instanz
|
||||
extern MqttClient mqttClient;
|
||||
|
|
@ -148,3 +148,34 @@ build_flags =
|
|||
-Wno-cpp
|
||||
lib_deps =
|
||||
majicDesigns/MD_MAX72XX @ ^3.5.1
|
||||
|
||||
; =============================================================================
|
||||
; TEST ENVIRONMENT 6.5 – MqttClient Verifikation
|
||||
; Flash: pio run -e test-mqtt --target upload
|
||||
; Monitor: pio device monitor -e test-mqtt
|
||||
;
|
||||
; Verifikation:
|
||||
; - MQTT Explorer -> broker.hivemq.com:1883
|
||||
; - Subscribe: lasercutter/#
|
||||
; - lasercutter/status erscheint beim Connect (retained) und alle 60s
|
||||
; - lasercutter/session erscheint nach Laser-AUS (GPIO 4 loslassen)
|
||||
; - Publish lasercutter/reset Payload "1" -> Gesamtzeit wird geloescht
|
||||
; - BOOT-Taste 3s halten -> lokaler Reset
|
||||
; =============================================================================
|
||||
[env:test-mqtt]
|
||||
platform = espressif32
|
||||
board = az-delivery-devkit-v4
|
||||
framework = arduino
|
||||
upload_port = COM3
|
||||
monitor_speed = 115200
|
||||
monitor_echo = yes
|
||||
board_build.partitions = min_spiffs.csv
|
||||
build_src_filter = -<*> +<../test_sketches/test_mqtt_client.cpp> +<../src/settings.cpp> +<../src/display_manager.cpp> +<../src/laser_tracker.cpp> +<../src/wifi_connector.cpp> +<../src/mqtt_client.cpp>
|
||||
build_flags =
|
||||
-DCORE_DEBUG_LEVEL=1
|
||||
-Wno-cpp
|
||||
lib_deps =
|
||||
majicDesigns/MD_MAX72XX @ ^3.5.1
|
||||
knolleary/PubSubClient @ ^2.8
|
||||
tzapu/WiFiManager @ ^2.0.17
|
||||
bblanchon/ArduinoJson @ ^7.3.0
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ LaserTracker::LaserTracker()
|
|||
, _sessionNetSec(0)
|
||||
, _totalMinutesBase(0.0f)
|
||||
, _lastBurstSec(0)
|
||||
, _burstEndPending(false)
|
||||
{}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
|
@ -108,7 +109,8 @@ void LaserTracker::onBurstEnd() {
|
|||
Serial.printf("[LaserTracker] BurstEnd: nur Gratiszeit gesamt=%ds "
|
||||
"total=%.2fmin\n", totalBurstSec, _totalMinutesBase);
|
||||
}
|
||||
_burst = BurstState::INACTIVE;
|
||||
_burst = BurstState::INACTIVE;
|
||||
_burstEndPending = true; // Fuer consumeBurstEnd() in main
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
|
@ -172,6 +174,16 @@ void LaserTracker::printToSerial() const {
|
|||
getCountdownRemaining(), getTotalMinutes());
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Einmalig true wenn ein Burst gerade beendet wurde (consume-Semantik)
|
||||
bool LaserTracker::consumeBurstEnd() {
|
||||
if (_burstEndPending) {
|
||||
_burstEndPending = false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
bool LaserTracker::readRaw() const {
|
||||
bool pinHigh = digitalRead(LASER_SIGNAL_PIN);
|
||||
|
|
|
|||
14
src/main.cpp
14
src/main.cpp
|
|
@ -4,6 +4,7 @@
|
|||
#include "wifi_connector.h"
|
||||
#include "display_manager.h"
|
||||
#include "laser_tracker.h"
|
||||
#include "mqtt_client.h"
|
||||
|
||||
void setup() {
|
||||
Serial.begin(SERIAL_BAUD_RATE);
|
||||
|
|
@ -24,11 +25,24 @@ void setup() {
|
|||
|
||||
wifiConnector.begin();
|
||||
wifiConnector.printToSerial();
|
||||
|
||||
mqttClient.begin();
|
||||
mqttClient.printToSerial();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
laserTracker.loop();
|
||||
wifiConnector.loop();
|
||||
mqttClient.loop();
|
||||
|
||||
// MQTT: Session-Publish nach jedem abgeschlossenen Burst
|
||||
if (laserTracker.consumeBurstEnd()) {
|
||||
mqttClient.publishSession(
|
||||
laserTracker.getLastBurstSeconds(),
|
||||
laserTracker.getTotalMinutes(),
|
||||
settings.get().gratisSeconds
|
||||
);
|
||||
}
|
||||
|
||||
// Display mit aktuellen Werten aktualisieren
|
||||
display.showLaserTime((float)laserTracker.getSessionMinutes()); // Module 1-3
|
||||
|
|
|
|||
191
src/mqtt_client.cpp
Normal file
191
src/mqtt_client.cpp
Normal file
|
|
@ -0,0 +1,191 @@
|
|||
// =============================================================================
|
||||
// mqtt_client.cpp - MQTT-Verbindung, Publish und Subscribe
|
||||
// Projekt: MQTT-Display LaserCutter
|
||||
// =============================================================================
|
||||
|
||||
#include "mqtt_client.h"
|
||||
#include "laser_tracker.h"
|
||||
#include "display_manager.h"
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
// Globale Instanz
|
||||
MqttClient mqttClient;
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Konstruktor
|
||||
// --------------------------------------------------------------------------
|
||||
MqttClient::MqttClient()
|
||||
: _client(_wifiClient)
|
||||
, _lastReconnectMs(0)
|
||||
, _lastHeartbeatMs(0)
|
||||
{}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// begin() - Broker konfigurieren und erste Verbindung versuchen
|
||||
// --------------------------------------------------------------------------
|
||||
void MqttClient::begin() {
|
||||
const auto& cfg = settings.get();
|
||||
|
||||
const char* broker = cfg.mqttBroker[0] != '\0'
|
||||
? cfg.mqttBroker
|
||||
: DEFAULT_MQTT_BROKER;
|
||||
uint16_t port = cfg.mqttPort > 0 ? cfg.mqttPort : DEFAULT_MQTT_PORT;
|
||||
|
||||
_client.setServer(broker, port);
|
||||
_client.setCallback(MqttClient::onMessage);
|
||||
_client.setKeepAlive(60);
|
||||
|
||||
Serial.printf("[MQTT] Broker: %s:%u\n", broker, port);
|
||||
Serial.printf("[MQTT] Client-ID: %s\n", MQTT_CLIENT_ID);
|
||||
|
||||
reconnect();
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// loop() - Reconnect und Heartbeat
|
||||
// --------------------------------------------------------------------------
|
||||
void MqttClient::loop() {
|
||||
if (!WiFi.isConnected()) {
|
||||
return; // Kein WiFi - nichts tun
|
||||
}
|
||||
|
||||
if (!_client.connected()) {
|
||||
uint32_t now = millis();
|
||||
if (now - _lastReconnectMs >= MQTT_RECONNECT_MS) {
|
||||
_lastReconnectMs = now;
|
||||
reconnect();
|
||||
}
|
||||
} else {
|
||||
_client.loop(); // PubSubClient interne Verarbeitung
|
||||
|
||||
// Heartbeat
|
||||
uint32_t now = millis();
|
||||
if (now - _lastHeartbeatMs >= MQTT_HEARTBEAT_MS) {
|
||||
_lastHeartbeatMs = now;
|
||||
publishHeartbeat();
|
||||
}
|
||||
}
|
||||
|
||||
// Display MQTT-Fehler aktualisieren
|
||||
display.showMqttError(!_client.connected());
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// publishSession() - beim Ende eines Laser-Bursts
|
||||
// --------------------------------------------------------------------------
|
||||
void MqttClient::publishSession(int lastBurstSec, float totalMinutes, int gratisSec) {
|
||||
if (!_client.connected()) {
|
||||
Serial.println("[MQTT] publishSession: nicht verbunden, uebersprungen");
|
||||
return;
|
||||
}
|
||||
|
||||
JsonDocument doc;
|
||||
doc["session_s"] = lastBurstSec;
|
||||
doc["total_min"] = serialized(String(totalMinutes, 2));
|
||||
doc["gratiszeit_s"] = gratisSec;
|
||||
doc["ip"] = WiFi.localIP().toString();
|
||||
|
||||
char buf[128];
|
||||
serializeJson(doc, buf, sizeof(buf));
|
||||
|
||||
bool ok = _client.publish(MQTT_TOPIC_SESSION, buf, /*retained=*/false);
|
||||
Serial.printf("[MQTT] publishSession: %s -> %s\n", buf, ok ? "OK" : "FEHLER");
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// publishHeartbeat() - Status-Heartbeat
|
||||
// --------------------------------------------------------------------------
|
||||
void MqttClient::publishHeartbeat() {
|
||||
JsonDocument doc;
|
||||
doc["online"] = true;
|
||||
doc["total_min"] = serialized(String(laserTracker.getTotalMinutes(), 2));
|
||||
doc["ip"] = WiFi.localIP().toString();
|
||||
doc["uptime_s"] = (uint32_t)(millis() / 1000UL);
|
||||
|
||||
char buf[128];
|
||||
serializeJson(doc, buf, sizeof(buf));
|
||||
|
||||
bool ok = _client.publish(MQTT_TOPIC_STATUS, buf, /*retained=*/true);
|
||||
Serial.printf("[MQTT] Heartbeat: %s -> %s\n", buf, ok ? "OK" : "FEHLER");
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// reconnect() - Verbindungsaufbau, non-blocking
|
||||
// --------------------------------------------------------------------------
|
||||
bool MqttClient::reconnect() {
|
||||
if (_client.connected()) return true;
|
||||
|
||||
const auto& cfg = settings.get();
|
||||
const char* user = cfg.mqttUser[0] != '\0' ? cfg.mqttUser : nullptr;
|
||||
const char* pass = cfg.mqttPassword[0] != '\0' ? cfg.mqttPassword : nullptr;
|
||||
|
||||
// Offline-LWT (Last Will and Testament)
|
||||
const char* lwtPayload = "{\"online\":false}";
|
||||
|
||||
Serial.printf("[MQTT] Verbinde als '%s'...\n", MQTT_CLIENT_ID);
|
||||
|
||||
bool ok;
|
||||
if (user && pass) {
|
||||
ok = _client.connect(MQTT_CLIENT_ID, user, pass,
|
||||
MQTT_TOPIC_STATUS, 0, true, lwtPayload);
|
||||
} else {
|
||||
ok = _client.connect(MQTT_CLIENT_ID,
|
||||
nullptr, nullptr,
|
||||
MQTT_TOPIC_STATUS, 0, true, lwtPayload);
|
||||
}
|
||||
|
||||
if (ok) {
|
||||
Serial.println("[MQTT] Verbunden!");
|
||||
_client.subscribe(MQTT_TOPIC_RESET);
|
||||
Serial.printf("[MQTT] Abonniert: %s\n", MQTT_TOPIC_RESET);
|
||||
// Sofortigen Heartbeat senden
|
||||
publishHeartbeat();
|
||||
_lastHeartbeatMs = millis();
|
||||
} else {
|
||||
Serial.printf("[MQTT] Verbindung fehlgeschlagen, rc=%d\n", _client.state());
|
||||
}
|
||||
|
||||
display.showMqttError(!ok);
|
||||
return ok;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// onMessage() - Callback fuer eingehende MQTT-Nachrichten
|
||||
// --------------------------------------------------------------------------
|
||||
void MqttClient::onMessage(const char* topic, byte* payload, unsigned int length) {
|
||||
// Payload als String kopieren
|
||||
char msg[64] = {};
|
||||
size_t copyLen = length < sizeof(msg) - 1 ? length : sizeof(msg) - 1;
|
||||
memcpy(msg, payload, copyLen);
|
||||
|
||||
Serial.printf("[MQTT] Nachricht: topic=%s payload=%s\n", topic, msg);
|
||||
|
||||
// Reset-Kommando
|
||||
if (strcmp(topic, MQTT_TOPIC_RESET) == 0) {
|
||||
if (strcmp(msg, "1") == 0) {
|
||||
Serial.println("[MQTT] RESET-Kommando empfangen -> laserTracker.resetTotal()");
|
||||
laserTracker.resetTotal();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// isConnected()
|
||||
// --------------------------------------------------------------------------
|
||||
bool MqttClient::isConnected() {
|
||||
return _client.connected();
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// printToSerial()
|
||||
// --------------------------------------------------------------------------
|
||||
void MqttClient::printToSerial() {
|
||||
const auto& cfg = settings.get();
|
||||
Serial.println("=== MqttClient ===");
|
||||
Serial.printf(" Broker : %s\n", cfg.mqttBroker[0] ? cfg.mqttBroker : DEFAULT_MQTT_BROKER);
|
||||
Serial.printf(" Port : %u\n", cfg.mqttPort > 0 ? cfg.mqttPort : DEFAULT_MQTT_PORT);
|
||||
Serial.printf(" ClientID : %s\n", MQTT_CLIENT_ID);
|
||||
Serial.printf(" Verbunden: %s\n", _client.connected() ? "JA" : "NEIN");
|
||||
Serial.printf(" rc : %d\n", _client.state());
|
||||
Serial.println("==================");
|
||||
}
|
||||
121
test_sketches/test_mqtt_client.cpp
Normal file
121
test_sketches/test_mqtt_client.cpp
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
// =============================================================================
|
||||
// test_mqtt_client.cpp - Phase 6: MqttClient Verifikation
|
||||
// Projekt: MQTT-Display LaserCutter
|
||||
//
|
||||
// Testet: WiFi (WifiManager) -> MQTT Connect -> Heartbeat -> publishSession
|
||||
// -> Reset-Kommando empfangen
|
||||
//
|
||||
// Hardware:
|
||||
// - Taste GPIO 4 (als Laser-Signal-Simulator, wie test_laser_tracker)
|
||||
// - BOOT-Taste GPIO 0 (3s = Gesamtzeit loeschen + MQTT reset)
|
||||
//
|
||||
// Verwendung:
|
||||
// 1. Flashen: pio run -e test-mqtt --target upload
|
||||
// 2. Serial Monitor: pio device monitor -e test-mqtt
|
||||
// 3. MQTT Explorer mit broker.hivemq.com verbinden
|
||||
// - Subscribe: lasercutter/# -> Session/Status-Nachrichten beobachten
|
||||
// - Publish: lasercutter/reset Payload: 1 -> Gesamt-Reset testen
|
||||
// 4. Verifikation der Topics:
|
||||
// lasercutter/session -> wird nach Laser-AUS veroeffentlicht
|
||||
// lasercutter/status -> Heartbeat alle 60s (retained)
|
||||
// =============================================================================
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "config.h"
|
||||
#include "settings.h"
|
||||
#include "wifi_connector.h"
|
||||
#include "display_manager.h"
|
||||
#include "laser_tracker.h"
|
||||
#include "mqtt_client.h"
|
||||
|
||||
// BOOT-Taste
|
||||
static const int BOOT_BTN = 0;
|
||||
static uint32_t bootPressMs = 0;
|
||||
|
||||
// Status-Druck alle 5 Sekunden
|
||||
static uint32_t lastStatusMs = 0;
|
||||
|
||||
// NVS-Fix: Stellt sicher, dass keine alten Werte stoeren
|
||||
void applyDefaults() {
|
||||
settings.saveGratisSeconds(DEFAULT_GRATIS_SECONDS);
|
||||
}
|
||||
|
||||
void setup() {
|
||||
Serial.begin(SERIAL_BAUD_RATE);
|
||||
delay(500);
|
||||
|
||||
settings.begin();
|
||||
applyDefaults();
|
||||
LOG_I("TEST-MQTT", "=== Phase 6 MQTT Test gestartet ===");
|
||||
LOG_I("TEST-MQTT", "Broker Default: %s:%d", DEFAULT_MQTT_BROKER, DEFAULT_MQTT_PORT);
|
||||
settings.printToSerial();
|
||||
|
||||
display.begin();
|
||||
display.printToSerial();
|
||||
display.showWifiError(false);
|
||||
display.showMqttError(false);
|
||||
display.showLaserTime(0.0f);
|
||||
display.showIdle();
|
||||
|
||||
laserTracker.begin();
|
||||
laserTracker.printToSerial();
|
||||
|
||||
wifiConnector.begin();
|
||||
wifiConnector.printToSerial();
|
||||
|
||||
mqttClient.begin();
|
||||
mqttClient.printToSerial();
|
||||
|
||||
pinMode(BOOT_BTN, INPUT);
|
||||
LOG_I("TEST-MQTT", "Setup abgeschlossen. Taste GPIO4=Laser, GPIO0=Reset");
|
||||
}
|
||||
|
||||
void loop() {
|
||||
laserTracker.loop();
|
||||
wifiConnector.loop();
|
||||
mqttClient.loop();
|
||||
|
||||
// MQTT: Session-Publish nach Burst-Ende
|
||||
if (laserTracker.consumeBurstEnd()) {
|
||||
LOG_I("TEST-MQTT", "BurstEnd erkannt -> publishSession (lastBurst=%ds, total=%.2fmin)",
|
||||
laserTracker.getLastBurstSeconds(),
|
||||
laserTracker.getTotalMinutes());
|
||||
mqttClient.publishSession(
|
||||
laserTracker.getLastBurstSeconds(),
|
||||
laserTracker.getTotalMinutes(),
|
||||
settings.get().gratisSeconds
|
||||
);
|
||||
}
|
||||
|
||||
// Display
|
||||
display.showLaserTime((float)laserTracker.getSessionMinutes());
|
||||
int countdown = laserTracker.getCountdownRemaining();
|
||||
if (laserTracker.isActive() && countdown > 0) {
|
||||
display.showCountdown(countdown);
|
||||
} else {
|
||||
display.showIdle();
|
||||
}
|
||||
display.update();
|
||||
|
||||
// BOOT-Taste (GPIO 0): 3s halten -> Gesamtzeit loeschen
|
||||
if (digitalRead(BOOT_BTN) == LOW) {
|
||||
if (bootPressMs == 0) bootPressMs = millis();
|
||||
if (millis() - bootPressMs >= 3000) {
|
||||
LOG_I("TEST-MQTT", "BOOT 3s: Gesamtzeit loeschen");
|
||||
laserTracker.resetTotal();
|
||||
bootPressMs = 0;
|
||||
}
|
||||
} else {
|
||||
bootPressMs = 0;
|
||||
}
|
||||
|
||||
// Periodischer Status-Druck
|
||||
if (millis() - lastStatusMs >= 5000) {
|
||||
lastStatusMs = millis();
|
||||
LOG_I("TEST-MQTT", "--- Status ---");
|
||||
mqttClient.printToSerial();
|
||||
laserTracker.printToSerial();
|
||||
}
|
||||
|
||||
delay(50);
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user