mirror of
https://github.com/rstrouse/ESPSomfy-RTS.git
synced 2026-10-31 13:52:15 +01:00
fix: send socket events only from loop()
Every socket event is formatted into one static buffer by one shared formatter. setConnected() runs on the WiFi/Ethernet event task and sent memStatus, wifiStrength and ethernet, then ran sockEmit.loop(), while loop() could be building its own event. _safecat() checks the room and then writes at _len, so another task moving _len in between could write past the end of g_response. setConnected() now sends nothing. loop() broadcasts the status every STATUS_EMIT_MS (30 s): memStatus, then ethernet, or wifiStrength when it moved 3 dBm or changed channel. A client that connects still gets all of it at once from initClients(), so needsBroadcast and the 1.5 s tick go, and so does the 1.5 s memStatus for the config panel. SocketEmitter records loop()'s task in begin(). Off it, beginEmit() logs and hands out a formatter that writes nothing, and endEmit(), endEmitRoom() and loop() do nothing. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
474c7c0f42
commit
25d548ef07
11 changed files with 153 additions and 117 deletions
|
|
@ -8,6 +8,7 @@
|
|||
#include "ESPNetwork.h"
|
||||
#include "GitOTA.h"
|
||||
#include "Timing.h"
|
||||
#include "Utils.h"
|
||||
|
||||
static const char *TAG = "Sockets";
|
||||
|
||||
|
|
@ -92,20 +93,36 @@ void SocketEmitter::startup() {
|
|||
|
||||
}
|
||||
void SocketEmitter::begin() {
|
||||
// Called from setup(), which runs on loop()'s task.
|
||||
this->_owner = xTaskGetCurrentTaskHandle();
|
||||
ws.onEvent(SocketEmitter::wsEvent);
|
||||
wsServer.addHandler(&ws);
|
||||
wsServer.begin();
|
||||
ESP_LOGI(TAG, "Socket Server Started...");
|
||||
}
|
||||
bool SocketEmitter::onLoopTask() const { return emitAllowed(xTaskGetCurrentTaskHandle(), this->_owner); }
|
||||
void SocketEmitter::loop() {
|
||||
if(!this->onLoopTask()) {
|
||||
ESP_LOGE(TAG, "Socket loop off loop() from %s, skipped", pcTaskGetName(nullptr));
|
||||
return;
|
||||
}
|
||||
ws.cleanupClients();
|
||||
this->initClients();
|
||||
}
|
||||
JsonSockEvent *SocketEmitter::beginEmit(const char *evt) {
|
||||
// Another task would overwrite the event loop() is building in g_response,
|
||||
// and could write past its end.
|
||||
if(!this->onLoopTask()) {
|
||||
ESP_LOGE(TAG, "Socket emit %s off loop() from %s, dropped", evt, pcTaskGetName(nullptr));
|
||||
this->_discard.discard();
|
||||
return &this->_discard;
|
||||
}
|
||||
this->json.beginEvent(&ws, evt, g_response, sizeof(g_response));
|
||||
return &this->json;
|
||||
}
|
||||
void SocketEmitter::endEmit(uint8_t num) {
|
||||
// beginEmit() has logged it.
|
||||
if(!this->onLoopTask()) return;
|
||||
if(num == 255) {
|
||||
this->json.endEvent(0);
|
||||
} else {
|
||||
|
|
@ -115,6 +132,7 @@ void SocketEmitter::endEmit(uint8_t num) {
|
|||
resetTaskWdt();
|
||||
}
|
||||
void SocketEmitter::endEmitRoom(uint8_t room) {
|
||||
if(!this->onLoopTask()) return;
|
||||
if(room < SOCK_MAX_ROOMS) {
|
||||
room_t *r = &this->rooms[room];
|
||||
for(uint8_t i = 0; i < sizeof(r->clients); i++) {
|
||||
|
|
|
|||
|
|
@ -22,6 +22,11 @@ class SocketEmitter {
|
|||
protected:
|
||||
uint8_t newclients = 0;
|
||||
uint8_t newClients[5] = {255,255,255,255,255};
|
||||
// loop()'s task, recorded by begin(). Only it may send; see emitAllowed().
|
||||
TaskHandle_t _owner = nullptr;
|
||||
// What beginEmit() hands any other task, so the event goes nowhere.
|
||||
JsonSockEvent _discard;
|
||||
bool onLoopTask() const;
|
||||
void delayInit(uint8_t num);
|
||||
public:
|
||||
JsonSockEvent json;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue