MQTT messages. Button anleren, Wifi frontend
This commit is contained in:
99
src/buttonassigh.h
Normal file
99
src/buttonassigh.h
Normal file
@@ -0,0 +1,99 @@
|
||||
#pragma once
|
||||
#include <Arduino.h>
|
||||
#include "master.h"
|
||||
// Aquacross Timer - ESP32 Master (Webserver + ESP-NOW + Anlernmodus)
|
||||
#include <ESPAsyncWebServer.h>
|
||||
|
||||
|
||||
|
||||
void handleLearningMode(const uint8_t* mac) {
|
||||
// Prüfen ob MAC bereits einem anderen Button zugewiesen ist
|
||||
if (buttonConfigs.start1.isAssigned && memcmp(buttonConfigs.start1.mac, mac, 6) == 0) {
|
||||
Serial.println("Diese MAC ist bereits zugewiesen - wird ignoriert");
|
||||
return;
|
||||
}
|
||||
if (buttonConfigs.stop1.isAssigned && memcmp(buttonConfigs.stop1.mac, mac, 6) == 0) {
|
||||
Serial.println("Diese MAC ist bereits zugewiesen - wird ignoriert");
|
||||
return;
|
||||
}
|
||||
if (buttonConfigs.start2.isAssigned && memcmp(buttonConfigs.start2.mac, mac, 6) == 0) {
|
||||
Serial.println("Diese MAC ist bereits zugewiesen - wird ignoriert");
|
||||
return;
|
||||
}
|
||||
if (buttonConfigs.stop2.isAssigned && memcmp(buttonConfigs.stop2.mac, mac, 6) == 0) {
|
||||
Serial.println("Diese MAC ist bereits zugewiesen - wird ignoriert");
|
||||
return;
|
||||
}
|
||||
|
||||
// MAC ist noch nicht zugewiesen, normal fortfahren
|
||||
switch(learningStep) {
|
||||
case 0: // Start1
|
||||
memcpy(buttonConfigs.start1.mac, mac, 6);
|
||||
buttonConfigs.start1.isAssigned = true;
|
||||
Serial.println("Start1 Button zugewiesen");
|
||||
break;
|
||||
case 1: // Stop1
|
||||
memcpy(buttonConfigs.stop1.mac, mac, 6);
|
||||
buttonConfigs.stop1.isAssigned = true;
|
||||
Serial.println("Stop1 Button zugewiesen");
|
||||
break;
|
||||
case 2: // Start2
|
||||
memcpy(buttonConfigs.start2.mac, mac, 6);
|
||||
buttonConfigs.start2.isAssigned = true;
|
||||
Serial.println("Start2 Button zugewiesen");
|
||||
break;
|
||||
case 3: // Stop2
|
||||
memcpy(buttonConfigs.stop2.mac, mac, 6);
|
||||
buttonConfigs.stop2.isAssigned = true;
|
||||
Serial.println("Stop2 Button zugewiesen");
|
||||
break;
|
||||
}
|
||||
|
||||
learningStep++;
|
||||
if (learningStep >= 4) {
|
||||
learningMode = false;
|
||||
learningStep = 0;
|
||||
saveButtonConfig();
|
||||
Serial.println("Lernmodus beendet!");
|
||||
}
|
||||
}
|
||||
|
||||
void handleStartLearning() {
|
||||
learningMode = true;
|
||||
|
||||
// Count assigned buttons and set appropriate learning step
|
||||
int assignedButtons = 0;
|
||||
if (buttonConfigs.start1.isAssigned) assignedButtons++;
|
||||
if (buttonConfigs.stop1.isAssigned) assignedButtons++;
|
||||
if (buttonConfigs.start2.isAssigned) assignedButtons++;
|
||||
if (buttonConfigs.stop2.isAssigned) assignedButtons++;
|
||||
|
||||
learningStep = assignedButtons;
|
||||
|
||||
Serial.printf("Learning mode started - %d buttons already assigned, continuing at step %d\n",
|
||||
assignedButtons, learningStep);
|
||||
}
|
||||
|
||||
void handleLearningStatus() {
|
||||
DynamicJsonDocument doc(256);
|
||||
doc["active"] = learningMode;
|
||||
doc["step"] = learningStep;
|
||||
|
||||
String response;
|
||||
serializeJson(doc, response);
|
||||
}
|
||||
|
||||
void unlearnButton() {
|
||||
|
||||
memset(buttonConfigs.start1.mac, 0, 6);
|
||||
buttonConfigs.start1.isAssigned = false;
|
||||
memset(buttonConfigs.stop1.mac, 0, 6);
|
||||
buttonConfigs.stop1.isAssigned = false;
|
||||
memset(buttonConfigs.start2.mac, 0, 6);
|
||||
buttonConfigs.start2.isAssigned = false;
|
||||
memset(buttonConfigs.stop2.mac, 0, 6);
|
||||
buttonConfigs.stop2.isAssigned = false;
|
||||
|
||||
saveButtonConfig();
|
||||
Serial.println("Buttons wurden verlernt.");
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
#pragma once
|
||||
#include <Arduino.h>
|
||||
#include "master.h"
|
||||
#include <ArduinoJson.h>
|
||||
@@ -6,6 +7,8 @@
|
||||
|
||||
#include <statusled.h>
|
||||
#include "timesync.h"
|
||||
#include "buttonassigh.h"
|
||||
#include "helper.h"
|
||||
|
||||
|
||||
// Datenstruktur für ESP-NOW Nachrichten
|
||||
@@ -19,31 +22,110 @@ typedef struct {
|
||||
} ButtonMessage;
|
||||
|
||||
PicoMQTT::Server mqtt;
|
||||
PicoMQTT::ServerLocalSubscribe localsubscribe;
|
||||
|
||||
|
||||
void readButtonJSON(const char * topic, const char * payload) {
|
||||
|
||||
if(strcmp(topic, "aquacross/button/press") == 0){
|
||||
|
||||
// Create a JSON document to parse the incoming message
|
||||
JsonDocument doc;
|
||||
DeserializationError error = deserializeJson(doc, payload);
|
||||
|
||||
if (error) {
|
||||
Serial.print("JSON parsing failed: ");
|
||||
Serial.println(error.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
// Extract values from JSON
|
||||
int pressType = doc["type"] | 0;
|
||||
const char* buttonId = doc["buttonmac"] | "unknown";
|
||||
const char* messageId = doc["messageId"] | "unknown";
|
||||
uint64_t timestamp = doc["timestamp"] | 0;
|
||||
|
||||
// Print received data
|
||||
Serial.printf("Button Press Received:\n");
|
||||
Serial.printf(" Type: %d\n", pressType);
|
||||
Serial.printf(" Button MAC: %s\n", buttonId);
|
||||
Serial.printf(" Message ID: %s\n", messageId);
|
||||
Serial.printf(" Timestamp: %llu\n", timestamp);
|
||||
|
||||
|
||||
auto macBytes = macStringToBytes(buttonId);
|
||||
|
||||
if (learningMode) {
|
||||
handleLearningMode(macBytes.data());
|
||||
return;
|
||||
}
|
||||
|
||||
// Button-Zuordnung prüfen und entsprechende Aktion ausführen
|
||||
if (memcmp(macBytes.data(), buttonConfigs.start1.mac, 6) == 0 && (pressType == 2)) {
|
||||
handleStart1();
|
||||
} else if (memcmp(macBytes.data(), buttonConfigs.stop1.mac, 6) == 0 && (pressType == 2)) {
|
||||
handleStop1();
|
||||
} else if (memcmp(macBytes.data(), buttonConfigs.start2.mac, 6) == 0 && (pressType == 2)) {
|
||||
handleStart2();
|
||||
} else if (memcmp(macBytes.data(), buttonConfigs.stop2.mac, 6) == 0 && (pressType == 2)) {
|
||||
handleStop2();
|
||||
}
|
||||
|
||||
// Flash status LED to indicate received message
|
||||
updateStatusLED(3);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void setupMqttServer() {
|
||||
|
||||
// Set up the MQTT server with the desired port
|
||||
// Subscribe to a topic pattern and attach a callback
|
||||
mqtt.subscribe("#", [](const char * topic, const char * payload) {
|
||||
Serial.printf("Received message in topic '%s': %s\n", topic, payload);
|
||||
updateStatusLED(3); // Flash LED on message received
|
||||
});
|
||||
Serial.printf("Received message in topic '%s': %s\n", topic, payload);
|
||||
readButtonJSON(topic, payload);
|
||||
updateStatusLED(3); // Flash LED on message received
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
// Add the button subscription
|
||||
|
||||
// Start the MQTT server
|
||||
mqtt.begin();
|
||||
|
||||
Serial.println("MQTT server started on port 1883");
|
||||
}
|
||||
|
||||
|
||||
|
||||
void loopMqttServer() {
|
||||
// Handle incoming MQTT messages
|
||||
mqtt.loop();
|
||||
|
||||
// Optionally, you can publish a message periodically
|
||||
static unsigned long lastPublish = 0;
|
||||
if (millis() - lastPublish > 5000) { // Publish every 5 seconds
|
||||
mqtt.publish("heartbeat/live", "Alive!");
|
||||
lastPublish = millis();
|
||||
}
|
||||
mqtt.loop();
|
||||
|
||||
static unsigned long lastPublish = 0;
|
||||
if (millis() - lastPublish > 30000) {
|
||||
// Convert timestamp to string before publishing
|
||||
char timeStr[32];
|
||||
snprintf(timeStr, sizeof(timeStr), "%llu", getCurrentTimestampMs());
|
||||
mqtt.publish("sync/time", timeStr);
|
||||
lastPublish = millis();
|
||||
}
|
||||
}
|
||||
|
||||
void sendMQTTMessage(const char * topic, const char * message) {
|
||||
// Publish a message to the specified topic
|
||||
mqtt.publish(topic, message);
|
||||
Serial.printf("Published message to topic '%s': %s\n", topic, message);
|
||||
}
|
||||
|
||||
void sendMQTTJSONMessage(const char * topic, const JsonDocument & doc) {
|
||||
String jsonString;
|
||||
serializeJson(doc, jsonString);
|
||||
|
||||
// Publish the JSON string to the specified topic
|
||||
auto publish = mqtt.begin_publish(topic, measureJson(doc));
|
||||
serializeJson(doc, publish);
|
||||
publish.send();
|
||||
Serial.printf("Published JSON message to topic '%s': %s\n", topic, jsonString.c_str());
|
||||
}
|
||||
10
src/helper.h
Normal file
10
src/helper.h
Normal file
@@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
#include <Arduino.h>
|
||||
#include "master.h"
|
||||
|
||||
std::array<uint8_t, 6> macStringToBytes(const char* macStr) {
|
||||
std::array<uint8_t, 6> bytes;
|
||||
sscanf(macStr, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
|
||||
&bytes[0], &bytes[1], &bytes[2], &bytes[3], &bytes[4], &bytes[5]);
|
||||
return bytes;
|
||||
}
|
||||
101
src/master.cpp
101
src/master.cpp
@@ -24,100 +24,11 @@ const char* firmwareversion = "1.0.0"; // Version der Firmware
|
||||
|
||||
|
||||
|
||||
void handleLearningMode(const uint8_t* mac) {
|
||||
// Prüfen ob MAC bereits einem anderen Button zugewiesen ist
|
||||
if (buttonConfigs.start1.isAssigned && memcmp(buttonConfigs.start1.mac, mac, 6) == 0) {
|
||||
Serial.println("Diese MAC ist bereits zugewiesen - wird ignoriert");
|
||||
return;
|
||||
}
|
||||
if (buttonConfigs.stop1.isAssigned && memcmp(buttonConfigs.stop1.mac, mac, 6) == 0) {
|
||||
Serial.println("Diese MAC ist bereits zugewiesen - wird ignoriert");
|
||||
return;
|
||||
}
|
||||
if (buttonConfigs.start2.isAssigned && memcmp(buttonConfigs.start2.mac, mac, 6) == 0) {
|
||||
Serial.println("Diese MAC ist bereits zugewiesen - wird ignoriert");
|
||||
return;
|
||||
}
|
||||
if (buttonConfigs.stop2.isAssigned && memcmp(buttonConfigs.stop2.mac, mac, 6) == 0) {
|
||||
Serial.println("Diese MAC ist bereits zugewiesen - wird ignoriert");
|
||||
return;
|
||||
}
|
||||
|
||||
// MAC ist noch nicht zugewiesen, normal fortfahren
|
||||
switch(learningStep) {
|
||||
case 0: // Start1
|
||||
memcpy(buttonConfigs.start1.mac, mac, 6);
|
||||
buttonConfigs.start1.isAssigned = true;
|
||||
Serial.println("Start1 Button zugewiesen");
|
||||
break;
|
||||
case 1: // Stop1
|
||||
memcpy(buttonConfigs.stop1.mac, mac, 6);
|
||||
buttonConfigs.stop1.isAssigned = true;
|
||||
Serial.println("Stop1 Button zugewiesen");
|
||||
break;
|
||||
case 2: // Start2
|
||||
memcpy(buttonConfigs.start2.mac, mac, 6);
|
||||
buttonConfigs.start2.isAssigned = true;
|
||||
Serial.println("Start2 Button zugewiesen");
|
||||
break;
|
||||
case 3: // Stop2
|
||||
memcpy(buttonConfigs.stop2.mac, mac, 6);
|
||||
buttonConfigs.stop2.isAssigned = true;
|
||||
Serial.println("Stop2 Button zugewiesen");
|
||||
break;
|
||||
}
|
||||
|
||||
learningStep++;
|
||||
if (learningStep >= 4) {
|
||||
learningMode = false;
|
||||
learningStep = 0;
|
||||
saveButtonConfig();
|
||||
Serial.println("Lernmodus beendet!");
|
||||
}
|
||||
}
|
||||
|
||||
void handleStartLearning() {
|
||||
learningMode = true;
|
||||
|
||||
// Count assigned buttons and set appropriate learning step
|
||||
int assignedButtons = 0;
|
||||
if (buttonConfigs.start1.isAssigned) assignedButtons++;
|
||||
if (buttonConfigs.stop1.isAssigned) assignedButtons++;
|
||||
if (buttonConfigs.start2.isAssigned) assignedButtons++;
|
||||
if (buttonConfigs.stop2.isAssigned) assignedButtons++;
|
||||
|
||||
learningStep = assignedButtons;
|
||||
|
||||
Serial.printf("Learning mode started - %d buttons already assigned, continuing at step %d\n",
|
||||
assignedButtons, learningStep);
|
||||
}
|
||||
|
||||
void handleLearningStatus() {
|
||||
DynamicJsonDocument doc(256);
|
||||
doc["active"] = learningMode;
|
||||
doc["step"] = learningStep;
|
||||
|
||||
String response;
|
||||
serializeJson(doc, response);
|
||||
}
|
||||
|
||||
void unlearnButton() {
|
||||
|
||||
memset(buttonConfigs.start1.mac, 0, 6);
|
||||
buttonConfigs.start1.isAssigned = false;
|
||||
memset(buttonConfigs.stop1.mac, 0, 6);
|
||||
buttonConfigs.stop1.isAssigned = false;
|
||||
memset(buttonConfigs.start2.mac, 0, 6);
|
||||
buttonConfigs.start2.isAssigned = false;
|
||||
memset(buttonConfigs.stop2.mac, 0, 6);
|
||||
buttonConfigs.stop2.isAssigned = false;
|
||||
|
||||
saveButtonConfig();
|
||||
Serial.println("Buttons wurden verlernt.");
|
||||
}
|
||||
|
||||
void handleStart1() {
|
||||
if (!timerData.isRunning1) {
|
||||
if (!timerData.isRunning1 && timerData.isReady1) {
|
||||
timerData.isReady1 = false; // Setze auf "Nicht bereit" bis Stopp
|
||||
timerData.startTime1 = millis();
|
||||
timerData.isRunning1 = true;
|
||||
timerData.endTime1 = 0;
|
||||
@@ -141,7 +52,8 @@ void handleStop1() {
|
||||
}
|
||||
|
||||
void handleStart2() {
|
||||
if (!timerData.isRunning2) {
|
||||
if (!timerData.isRunning2 && timerData.isReady2) {
|
||||
timerData.isReady2 = false; // Setze auf "Nicht bereit" bis Stopp
|
||||
timerData.startTime2 = millis();
|
||||
timerData.isRunning2 = true;
|
||||
timerData.endTime2 = 0;
|
||||
@@ -185,6 +97,7 @@ void checkAutoReset() {
|
||||
timerData.startTime1 = 0;
|
||||
timerData.endTime1 = 0;
|
||||
timerData.finishedSince1 = 0;
|
||||
timerData.isReady1 = true; // Zurücksetzen auf "Bereit"
|
||||
Serial.println("Bahn 1 automatisch auf 'Bereit' zurückgesetzt");
|
||||
}
|
||||
}
|
||||
@@ -194,6 +107,7 @@ void checkAutoReset() {
|
||||
timerData.startTime2 = 0;
|
||||
timerData.endTime2 = 0;
|
||||
timerData.finishedSince2 = 0;
|
||||
timerData.isReady2 = true; // Zurücksetzen auf "Bereit"
|
||||
Serial.println("Bahn 2 automatisch auf 'Bereit' zurückgesetzt");
|
||||
}
|
||||
}
|
||||
@@ -321,12 +235,11 @@ void setup() {
|
||||
setupRoutes();
|
||||
setupLED();
|
||||
setupMqttServer(); // MQTT Server initialisieren
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
void loop() {
|
||||
checkAutoReset();
|
||||
loopMqttServer(); // MQTT Server in der Loop aufrufen
|
||||
delay(100);
|
||||
}
|
||||
|
||||
@@ -18,6 +18,8 @@ struct TimerData {
|
||||
bool isRunning2 = false;
|
||||
unsigned long finishedSince1 = 0;
|
||||
unsigned long finishedSince2 = 0;
|
||||
bool isReady1 = true; // Status für Bahn 1
|
||||
bool isReady2 = true; // Status für Bahn 2
|
||||
};
|
||||
|
||||
// Button Konfiguration
|
||||
|
||||
@@ -196,3 +196,9 @@ bool isValidDateTime(int year, int month, int day, int hour, int minute, int sec
|
||||
|
||||
return day <= daysInMonth[month - 1];
|
||||
}
|
||||
|
||||
uint64_t getCurrentTimestampMs() {
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
return (uint64_t)tv.tv_sec * 1000LL + (uint64_t)tv.tv_usec / 1000LL;
|
||||
}
|
||||
|
||||
@@ -5,6 +5,9 @@
|
||||
#include <SPIFFS.h>
|
||||
#include <esp_wifi.h>
|
||||
|
||||
|
||||
#include <buttonassigh.h>
|
||||
|
||||
AsyncWebServer server(80);
|
||||
|
||||
void setupRoutes(){
|
||||
|
||||
Reference in New Issue
Block a user