mirror of
https://github.com/rstrouse/ESPSomfy-RTS.git
synced 2026-10-31 22:02:17 +01:00
refactor: split the transports into the modules GLOSSARY.md names
Code moves unchanged; only files and names change. - entryPoints/WebUiRoutes.cpp: registerWebUiRoutes(), the port 80 routes and the UI's files, with the helpers only they use. - entryPoints/ApiRoutes.cpp: registerApiRoutes(), the port 8081 routes. - entryPoints/Web.cpp keeps the servers' lifecycle, auth and the handlers both route sets call; entryPoints/WebRoutes.h is what the three share. - entryPoints/MQTT.* -> MqttConnection.*, class MQTTClass -> MqttConnection. - outputs/SomfyMqtt.cpp -> outputs/MqttPublisher.cpp. - outputs/Sockets.* -> outputs/SocketEmitter.*. The subscribe and unsubscribe lists (the latter repeated groups/+/direction/set) become MqttCommands' MQTT_COMMAND_TOPICS, and a native test checks the parser takes every topic in it. GLOSSARY.md gains MqttConnection and Change fan-out. 328 native tests. Flash: esp32devdbg +3,112 bytes (the routes are a second ArduinoJson file), esp32dev -2,336 bytes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
4c5bc01fe5
commit
a0ad301779
20 changed files with 1186 additions and 1066 deletions
|
|
@ -1,243 +0,0 @@
|
|||
#include <WiFi.h>
|
||||
#include <PubSubClient.h>
|
||||
#include <ArduinoJson.h>
|
||||
#include <esp_task_wdt.h>
|
||||
#include "esp_log.h"
|
||||
#include "ConfigSettings.h"
|
||||
#include "MQTT.h"
|
||||
#include "MqttCommands.h"
|
||||
#include "Somfy.h"
|
||||
#include "LoopQueue.h"
|
||||
#include "ESPNetwork.h"
|
||||
#include "Utils.h"
|
||||
|
||||
static const char *TAG = "MQTT";
|
||||
|
||||
WiFiClient tcpClient;
|
||||
PubSubClient mqttClient(tcpClient);
|
||||
|
||||
#define MQTT_MAX_RESPONSE 2048
|
||||
static char g_content[MQTT_MAX_RESPONSE];
|
||||
|
||||
extern ConfigSettings settings;
|
||||
extern SomfyShadeController somfy;
|
||||
extern ESPNetwork net;
|
||||
extern rebootDelay_t rebootDelay;
|
||||
extern LoopQueue loopQueue;
|
||||
|
||||
|
||||
bool MQTTClass::begin() {
|
||||
this->suspended = false;
|
||||
return true;
|
||||
}
|
||||
bool MQTTClass::end() {
|
||||
this->suspended = true;
|
||||
this->disconnect();
|
||||
return true;
|
||||
}
|
||||
void MQTTClass::reset() {
|
||||
this->disconnect();
|
||||
this->lastConnect = 0;
|
||||
this->connect();
|
||||
}
|
||||
bool MQTTClass::loop() {
|
||||
if(settings.MQTT.enabled && !rebootDelay.reboot && !this->suspended && !mqttClient.connected()) {
|
||||
esp_task_wdt_reset();
|
||||
if(!this->connected() && net.connected()) this->connect();
|
||||
}
|
||||
esp_task_wdt_reset();
|
||||
if(settings.MQTT.enabled) mqttClient.loop();
|
||||
return true;
|
||||
}
|
||||
void MQTTClass::receive(const char *topic, byte*payload, uint32_t length) {
|
||||
esp_task_wdt_reset(); // Make sure we do not reboot here.
|
||||
ESP_LOGD(TAG, "MQTT Topic:%s payload:%.*s", topic, (int)length, (const char *)payload);
|
||||
// This already runs on loop(), but going through the loop queue keeps MQTT
|
||||
// and web requests in order and holds them while the radio is full.
|
||||
loop_item_t item;
|
||||
if(!parseMqttCommand(topic, payload, length, item.request)) {
|
||||
ESP_LOGW(TAG, "MQTT command not understood: %s", topic);
|
||||
return;
|
||||
}
|
||||
loopQueue.submit(item);
|
||||
}
|
||||
bool MQTTClass::connect() {
|
||||
esp_task_wdt_reset(); // Make sure we do not reboot here.
|
||||
if(mqttClient.connected()) {
|
||||
if(!settings.MQTT.enabled || this->suspended)
|
||||
return this->disconnect();
|
||||
else
|
||||
return true;
|
||||
}
|
||||
if(settings.MQTT.enabled && !this->suspended) {
|
||||
if(this->lastConnect + 10000 > millis()) return false;
|
||||
uint64_t mac = ESP.getEfuseMac();
|
||||
snprintf(this->clientId, sizeof(this->clientId), "client-%08x%08x", (uint32_t)((mac >> 32) & 0xFFFFFFFF), (uint32_t)(mac & 0xFFFFFFFF));
|
||||
if(strlen(settings.MQTT.protocol) > 0 && strlen(settings.MQTT.hostname) > 0) {
|
||||
mqttClient.setServer(settings.MQTT.hostname, settings.MQTT.port);
|
||||
char lwtTopic[128] = "status";
|
||||
if(strlen(settings.MQTT.rootTopic) > 0)
|
||||
snprintf(lwtTopic, sizeof(lwtTopic), "%s/status", settings.MQTT.rootTopic);
|
||||
esp_task_wdt_reset();
|
||||
if(mqttClient.connect(this->clientId, settings.MQTT.username, settings.MQTT.password, lwtTopic, 0, true, "offline")) {
|
||||
ESP_LOGI(TAG, "Successfully connected MQTT client %s", this->clientId);
|
||||
this->publish("status", "online", true);
|
||||
this->publish("ipAddress", settings.IP.ip.toString().c_str(), true);
|
||||
this->publish("host", settings.hostname, true);
|
||||
this->publish("firmware", settings.fwVersion.name, true);
|
||||
this->publish("serverId", settings.serverId, true);
|
||||
this->publish("mac", net.mac.c_str());
|
||||
somfy.publish();
|
||||
this->subscribe("shades/+/target/set");
|
||||
this->subscribe("shades/+/tiltTarget/set");
|
||||
this->subscribe("shades/+/direction/set");
|
||||
this->subscribe("shades/+/mypos/set");
|
||||
this->subscribe("shades/+/myTiltPos/set");
|
||||
this->subscribe("shades/+/sunFlag/set");
|
||||
this->subscribe("shades/+/sunny/set");
|
||||
this->subscribe("shades/+/windy/set");
|
||||
this->subscribe("shades/+/position/set");
|
||||
this->subscribe("shades/+/tiltPosition/set");
|
||||
this->subscribe("groups/+/direction/set");
|
||||
this->subscribe("groups/+/sunFlag/set");
|
||||
this->subscribe("groups/+/sunny/set");
|
||||
this->subscribe("groups/+/windy/set");
|
||||
mqttClient.setCallback(MQTTClass::receive);
|
||||
ESP_LOGI(TAG, "MQTT Startup Completed");
|
||||
esp_task_wdt_reset();
|
||||
this->lastConnect = millis();
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
ESP_LOGE(TAG, "MQTT Connection failed for: %d", mqttClient.state());
|
||||
this->lastConnect = millis();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool MQTTClass::disconnect() {
|
||||
if(mqttClient.connected()) {
|
||||
this->unsubscribe("shades/+/target/set");
|
||||
this->unsubscribe("shades/+/direction/set");
|
||||
this->unsubscribe("shades/+/tiltTarget/set");
|
||||
this->unsubscribe("shades/+/mypos/set");
|
||||
this->unsubscribe("shades/+/myTiltPos/set");
|
||||
this->unsubscribe("shades/+/sunFlag/set");
|
||||
this->unsubscribe("groups/+/direction/set");
|
||||
this->unsubscribe("shades/+/sunny/set");
|
||||
this->unsubscribe("shades/+/windy/set");
|
||||
this->unsubscribe("shades/+/position/set");
|
||||
this->unsubscribe("shades/+/tiltPosition/set");
|
||||
this->unsubscribe("groups/+/direction/set");
|
||||
this->unsubscribe("groups/+/sunFlag/set");
|
||||
this->unsubscribe("groups/+/sunny/set");
|
||||
this->unsubscribe("groups/+/windy/set");
|
||||
mqttClient.disconnect();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool MQTTClass::unsubscribe(const char *topic) {
|
||||
if(mqttClient.connected()) {
|
||||
char top[128];
|
||||
if(strlen(settings.MQTT.rootTopic) > 0)
|
||||
snprintf(top, sizeof(top), "%s/%s", settings.MQTT.rootTopic, topic);
|
||||
else
|
||||
strlcpy(top, topic, sizeof(top));
|
||||
ESP_LOGD(TAG, "MQTT Unsubscribed from:%s", top);
|
||||
return mqttClient.unsubscribe(top);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool MQTTClass::subscribe(const char *topic) {
|
||||
if(mqttClient.connected()) {
|
||||
esp_task_wdt_reset(); // Make sure we do not reboot here.
|
||||
char top[128];
|
||||
if(strlen(settings.MQTT.rootTopic) > 0)
|
||||
snprintf(top, sizeof(top), "%s/%s", settings.MQTT.rootTopic, topic);
|
||||
else
|
||||
strlcpy(top, topic, sizeof(top));
|
||||
ESP_LOGD(TAG, "MQTT Subscribed to:%s", top);
|
||||
return mqttClient.subscribe(top);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool MQTTClass::publish(const char *topic, const char *payload, bool retain) {
|
||||
if(mqttClient.connected()) {
|
||||
char top[128];
|
||||
if(strlen(settings.MQTT.rootTopic) > 0)
|
||||
snprintf(top, sizeof(top), "%s/%s", settings.MQTT.rootTopic, topic);
|
||||
else
|
||||
strlcpy(top, topic, sizeof(top));
|
||||
esp_task_wdt_reset(); // Make sure we do not reboot here.
|
||||
mqttClient.publish(top, payload, retain);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool MQTTClass::publish(const char *topic, uint32_t val, bool retain) {
|
||||
snprintf(g_content, sizeof(g_content), "%u", val);
|
||||
return this->publish(topic, g_content, retain);
|
||||
}
|
||||
bool MQTTClass::unpublish(const char *topic) {
|
||||
if(mqttClient.connected()) {
|
||||
char top[128];
|
||||
if(strlen(settings.MQTT.rootTopic) > 0)
|
||||
snprintf(top, sizeof(top), "%s/%s", settings.MQTT.rootTopic, topic);
|
||||
else
|
||||
strlcpy(top, topic, sizeof(top));
|
||||
esp_task_wdt_reset(); // Make sure we do not reboot here.
|
||||
mqttClient.publish(top, (const uint8_t *)"", 0, true);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
// mqttClient.beginPublish(topic, 0, true);
|
||||
// mqttClient.endPublish();
|
||||
}
|
||||
|
||||
bool MQTTClass::publishBuffer(const char *topic, uint8_t *data, uint16_t len, bool retain) {
|
||||
size_t res;
|
||||
uint16_t offset = 0;
|
||||
uint16_t to_write = len;
|
||||
uint16_t buff_len;
|
||||
esp_task_wdt_reset(); // Make sure we do not reboot here.
|
||||
mqttClient.beginPublish(topic, len, retain);
|
||||
do {
|
||||
buff_len = to_write;
|
||||
if(buff_len > 128) buff_len = 128;
|
||||
res = mqttClient.write(data+offset, buff_len);
|
||||
offset += buff_len;
|
||||
to_write -= buff_len;
|
||||
} while(res == buff_len && to_write > 0);
|
||||
mqttClient.endPublish();
|
||||
return true;
|
||||
}
|
||||
bool MQTTClass::publishDisco(const char *topic, JsonObject &obj, bool retain) {
|
||||
serializeJson(obj, g_content, sizeof(g_content));
|
||||
this->publishBuffer(topic, (uint8_t *)g_content, strlen(g_content), retain);
|
||||
return true;
|
||||
}
|
||||
bool MQTTClass::publish(const char *topic, int8_t val, bool retain) {
|
||||
snprintf(g_content, sizeof(g_content), "%d", val);
|
||||
return this->publish(topic, g_content, retain);
|
||||
}
|
||||
bool MQTTClass::publish(const char *topic, uint8_t val, bool retain) {
|
||||
snprintf(g_content, sizeof(g_content), "%u", val);
|
||||
return this->publish(topic, g_content, retain);
|
||||
}
|
||||
bool MQTTClass::publish(const char *topic, uint16_t val, bool retain) {
|
||||
snprintf(g_content, sizeof(g_content), "%u", val);
|
||||
return this->publish(topic, g_content, retain);
|
||||
}
|
||||
bool MQTTClass::publish(const char *topic, bool val, bool retain) {
|
||||
snprintf(g_content, sizeof(g_content), "%s", val ? "true" : "false");
|
||||
return this->publish(topic, g_content, retain);
|
||||
}
|
||||
bool MQTTClass::connected() {
|
||||
if(settings.MQTT.enabled) return mqttClient.connected();
|
||||
return false;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue