ESPSomfy-RTS/src/outputs/SomfyEvents.cpp
cjkas fdf1a47ff8 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>
2026-10-16 14:40:22 +02:00

134 lines
5.4 KiB
C++

#include <esp_task_wdt.h>
#include "Somfy.h"
#include "SomfyEditor.h"
#include "SocketEmitter.h"
#include "MqttConnection.h"
extern SomfyShadeController somfy;
extern SocketEmitter sockEmit;
extern MqttConnection mqtt;
void SomfyShade::emitState() { this->changed |= SHADE_CHANGED_STATE; }
void SomfyShade::emitState(const char *evt) { this->emitState(255, evt); }
void SomfyShade::emitState(uint8_t num, const char *evt) {
JsonSockEvent *json = sockEmit.beginEmit(evt);
json->beginObject();
json->addElem("shadeId", this->shadeId);
json->addElem("type", static_cast<uint8_t>(this->shadeType));
json->addElem("remoteAddress", (uint32_t)this->getRemoteAddress());
json->addElem("name", this->name);
json->addElem("direction", this->direction);
json->addElem("position", this->transformPosition(this->currentPos));
json->addElem("target", this->transformPosition(this->target));
json->addElem("myPos", this->transformPosition(this->myPos));
json->addElem("tiltType", static_cast<uint8_t>(this->tiltType));
json->addElem("flipCommands", this->flipCommands);
json->addElem("flipPosition", this->flipPosition);
json->addElem("flags", this->flags);
json->addElem("sunSensor", this->hasSunSensor());
json->addElem("light", this->hasLight());
json->addElem("sortOrder", this->sortOrder);
if(this->tiltType != tilt_types::none) {
json->addElem("tiltDirection", this->tiltDirection);
json->addElem("tiltTarget", this->transformPosition(this->tiltTarget));
json->addElem("tiltPosition", this->transformPosition(this->currentTiltPos));
json->addElem("myTiltPos", this->transformPosition(this->myTiltPos));
}
json->endObject();
sockEmit.endEmit(num);
}
void SomfyShade::emitCommand(somfy_commands cmd, const char *source, uint32_t sourceAddress, const char *evt) { this->emitCommand(255, cmd, source, sourceAddress, evt); }
void SomfyShade::emitCommand(uint8_t num, somfy_commands cmd, const char *source, uint32_t sourceAddress, const char *evt) {
JsonSockEvent *json = sockEmit.beginEmit(evt);
json->beginObject();
json->addElem("shadeId", this->shadeId);
json->addElem("remoteAddress", (uint32_t)this->getRemoteAddress());
json->addElem("cmd", translateSomfyCommand(cmd).c_str());
json->addElem("source", source);
json->addElem("rcode", (uint32_t)this->lastRollingCode);
json->addElem("sourceAddress", (uint32_t)sourceAddress);
json->endObject();
sockEmit.endEmit(num);
if(mqtt.connected()) {
this->publish("cmdSource", source);
this->publish("cmdAddress", sourceAddress);
this->publish("cmd", translateSomfyCommand(cmd).c_str());
}
}
void SomfyRoom::emitState(const char *evt) { this->emitState(255, evt); }
void SomfyRoom::emitState(uint8_t num, const char *evt) {
JsonSockEvent *json = sockEmit.beginEmit(evt);
json->beginObject();
json->addElem("roomId", this->roomId);
json->addElem("name", this->name);
json->addElem("sortOrder", this->sortOrder);
json->endObject();
sockEmit.endEmit(num);
this->publish();
}
void SomfyGroup::emitState() { this->changed |= GROUP_CHANGED_STATE; }
void SomfyGroup::emitState(const char *evt) { this->emitState(255, evt); }
void SomfyGroup::emitState(uint8_t num, const char *evt) {
uint8_t flags = 0;
JsonSockEvent *json = sockEmit.beginEmit(evt);
json->beginObject();
json->addElem("groupId", this->groupId);
json->addElem("remoteAddress", (uint32_t)this->getRemoteAddress());
json->addElem("name", this->name);
json->addElem("sunSensor", this->hasSunSensor());
json->beginArray("shades");
for(uint8_t i = 0; i < SOMFY_MAX_GROUPED_SHADES; i++) {
if(this->linkedShades[i] != 255 && this->linkedShades[i] != 0) {
SomfyShade *shade = somfy.getShadeById(this->linkedShades[i]);
if(shade) {
json->addElem(this->linkedShades[i]);
flags |= shade->flags;
}
}
}
json->endArray();
json->addElem("flags", flags);
json->endObject();
sockEmit.endEmit(num);
this->publish();
}
// To every client: the sender picks out its own by requestId.
void emitRequestResult(uint32_t requestId, const edit_result_t &result) {
JsonSockEvent *json = sockEmit.beginEmit("requestResult");
json->beginObject();
json->addElem("requestId", requestId);
json->addElem("ok", result.ok);
json->addElem("id", result.id);
json->addElem("code", result.code);
json->addElem("desc", result.desc);
json->endObject();
sockEmit.endEmit();
}
// The change fan-out. Everything that changed about a shade or group in this
// loop() pass goes out once: its MQTT topics, then one state event.
void SomfyShadeController::sendChanges() {
for(uint8_t i = 0; i < SOMFY_MAX_SHADES; i++) {
SomfyShade &shade = this->shades[i];
const uint16_t changed = shade.changed;
shade.changed = 0;
if(!changed || shade.getShadeId() == 255) continue;
if(changed & SHADE_CHANGED_TOPICS) shade.publishTopics(changed);
shade.emitState(255, "shadeState");
}
for(uint8_t i = 0; i < SOMFY_MAX_GROUPS; i++) {
SomfyGroup &group = this->groups[i];
const uint8_t changed = group.changed;
group.changed = 0;
if(!changed || group.getGroupId() == 255) continue;
if(changed & GROUP_CHANGED_DIRECTION) group.publish("direction", group.direction);
group.emitState(255, "groupState");
}
}
void SomfyShadeController::emitState(uint8_t num) {
for(uint8_t i = 0; i < SOMFY_MAX_SHADES; i++) {
SomfyShade *shade = &this->shades[i];
if(shade->getShadeId() == 255) continue;
esp_task_wdt_reset();
shade->emitState(num);
}
}