Skip to content

Commit

Permalink
Remove static from SysModWeb
Browse files Browse the repository at this point in the history
SysModWeb:
- ws-> to ws.
- server-> to server.
- ws.onEvent, server.addHandler and server.on using lambda functions
  • Loading branch information
ewowi committed Mar 29, 2024
1 parent 8daea1c commit f7f621c
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 97 deletions.
2 changes: 1 addition & 1 deletion src/App/LedModFixture.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ class LedModFixture:public SysModule {
// ui->setComment(var, "Click to enlarge");
return true;
case f_LoopFun: {
var["interval"] = max(eff->fixture.nrOfLeds * web->ws->count()/200, 16U)*10; //interval in ms * 10, not too fast //from cs to ms
var["interval"] = max(eff->fixture.nrOfLeds * web->ws.count()/200, 16U)*10; //interval in ms * 10, not too fast //from cs to ms

web->sendDataWs([this](AsyncWebSocketMessageBuffer * wsBuf) {
byte* buffer;
Expand Down
2 changes: 1 addition & 1 deletion src/Sys/SysModSystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ void SysModSystem::setup() {

ui->initButton(parentVar, "reboot", false, [](JsonObject var, unsigned8 rowNr, unsigned8 funType) { switch (funType) { //varFun
case f_ChangeFun:
web->ws->closeAll(1012);
web->ws.closeAll(1012);

// mdls->reboot(); //not working yet
// long dly = millis();
Expand Down
109 changes: 40 additions & 69 deletions src/Sys/SysModWeb.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,32 +26,7 @@
//https://techtutorialsx.com/2018/08/24/esp32-web-server-serving-html-from-file-system/
//https://randomnerdtutorials.com/esp32-async-web-server-espasyncwebserver-library/

WebServer * SysModWeb::server = nullptr;
WebSocket * SysModWeb::ws = nullptr;

bool SysModWeb::clientsChanged = false;

unsigned8 SysModWeb::sendWsCounter = 0;
unsigned16 SysModWeb::sendWsTBytes = 0;
unsigned16 SysModWeb::sendWsBBytes = 0;
unsigned8 SysModWeb::recvWsCounter = 0;
unsigned16 SysModWeb::recvWsBytes = 0;
unsigned8 SysModWeb::sendUDPCounter = 0;
unsigned16 SysModWeb::sendUDPBytes = 0;
unsigned8 SysModWeb::recvUDPCounter = 0;
unsigned16 SysModWeb::recvUDPBytes = 0;

SemaphoreHandle_t SysModWeb::wsMutex = xSemaphoreCreateMutex();

SysModWeb::SysModWeb() :SysModule("Web") {
#ifdef STARMOD_USE_Psychic
ws = new WebSocket();
server = new WebServer();
#else
ws = new WebSocket("/ws");
server = new WebServer(80);
#endif

//CORS compatiblity
DefaultHeaders::Instance().addHeader(F("Access-Control-Allow-Origin"), "*");
DefaultHeaders::Instance().addHeader(F("Access-Control-Allow-Methods"), "*");
Expand All @@ -74,7 +49,7 @@ void SysModWeb::setup() {

ui->initNumber(tableVar, "clNr", UINT16_MAX, 0, 999, true, [this](JsonObject var, unsigned8 rowNr, unsigned8 funType) { switch (funType) { //varFun
case f_ValueFun: {
unsigned8 rowNr = 0; for (auto client:ws->getClients())
unsigned8 rowNr = 0; for (auto client:ws.getClients())
mdl->setValue(var, client->id(), rowNr++);
return true; }
case f_UIFun:
Expand All @@ -85,7 +60,7 @@ void SysModWeb::setup() {

ui->initText(tableVar, "clIp", nullptr, 16, true, [this](JsonObject var, unsigned8 rowNr, unsigned8 funType) { switch (funType) { //varFun
case f_ValueFun: {
unsigned8 rowNr = 0; for (auto client:ws->getClients())
unsigned8 rowNr = 0; for (auto client:ws.getClients())
mdl->setValue(var, JsonString(client->remoteIP().toString().c_str(), JsonString::Copied), rowNr++);
return true; }
case f_UIFun:
Expand All @@ -96,7 +71,7 @@ void SysModWeb::setup() {

ui->initCheckBox(tableVar, "clIsFull", UINT16_MAX, true, [this](JsonObject var, unsigned8 rowNr, unsigned8 funType) { switch (funType) { //varFun
case f_ValueFun: {
unsigned8 rowNr = 0; for (auto client:ws->getClients())
unsigned8 rowNr = 0; for (auto client:ws.getClients())
mdl->setValue(var, client->queueIsFull(), rowNr++);
return true; }
case f_UIFun:
Expand All @@ -107,7 +82,7 @@ void SysModWeb::setup() {

ui->initSelect(tableVar, "clStatus", UINT16_MAX, true, [this](JsonObject var, unsigned8 rowNr, unsigned8 funType) { switch (funType) { //varFun
case f_ValueFun: {
unsigned8 rowNr = 0; for (auto client:ws->getClients())
unsigned8 rowNr = 0; for (auto client:ws.getClients())
mdl->setValue(var, client->status(), rowNr++);
return true; }
case f_UIFun:
Expand All @@ -125,7 +100,7 @@ void SysModWeb::setup() {

ui->initNumber(tableVar, "clLength", UINT16_MAX, 0, WS_MAX_QUEUED_MESSAGES, true, [this](JsonObject var, unsigned8 rowNr, unsigned8 funType) { switch (funType) { //varFun
case f_ValueFun: {
unsigned8 rowNr = 0; for (auto client:ws->getClients())
unsigned8 rowNr = 0; for (auto client:ws.getClients())
mdl->setValue(var, client->queueLength(), rowNr++);
return true; }
case f_UIFun:
Expand Down Expand Up @@ -213,37 +188,37 @@ void SysModWeb::loop1s() {

void SysModWeb::reboot() {
USER_PRINTF("SysModWeb reboot\n");
ws->closeAll(1012);
ws.closeAll(1012);
}

void SysModWeb::connectedChanged() {
if (mdls->isConnected) {
#ifdef STARMOD_USE_Psychic

server->listen(80);
server.listen(80);

ws->onOpen(wsEventOpen);
ws->onFrame(wsEventFrame);
ws->onClose(wsEventClose);
ws.onOpen(wsEventOpen);
ws.onFrame(wsEventFrame);
ws.onClose(wsEventClose);

server->on("/ws")->setHandler(ws);
server.on("/ws")->setHandler(&ws);

#else
ws->onEvent(wsEvent);
server->addHandler(ws);
server->begin();
ws.onEvent( [this](WebSocket * server, WebClient * client, AwsEventType type, void * arg, uint8_t *data, size_t len) {wsEvent(server, client, type, arg, data, len);});
server.addHandler(&ws);
server.begin();
#endif

server->on("/", HTTP_GET, serveIndex);
server.on("/", HTTP_GET, [this](WebRequest *request) {serveIndex(request);});

//serve json calls
server->on("/json", HTTP_GET, serveJson);
server.on("/json", HTTP_GET, [this](WebRequest *request) {serveJson(request);});

server->addHandler(new AsyncCallbackJsonWebHandler("/json", jsonHandler));
server.addHandler(new AsyncCallbackJsonWebHandler("/json", [this](WebRequest *request, JsonVariant &json){jsonHandler(request, json);}));

server->on("/update", HTTP_POST, [](WebRequest *request) {}, serveUpdate);
server->on("/file", HTTP_GET, serveFiles);
server->on("/upload", HTTP_POST, [](WebRequest *request) {}, serveUpload);
server.on("/update", HTTP_POST, nullptr, [this](WebRequest *request, const String& filename, size_t index, byte *data, size_t len, bool final) {serveUpdate(request, filename, index, data, len, final);});
server.on("/file", HTTP_GET, [this](WebRequest *request) {serveFiles(request);});
server.on("/upload", HTTP_POST, nullptr, [this](WebRequest *request, const String& filename, size_t index, byte *data, size_t len, bool final) {serveUpload(request, filename, index, data, len, final);});

// USER_PRINTF("%s server (re)started\n", name); //causes crash for some reason...
USER_PRINTF("server (re)started\n");
Expand All @@ -259,7 +234,7 @@ void SysModWeb::connectedChanged() {

// https://github.com/me-no-dev/ESPAsyncWebServer/blob/master/examples/ESP_AsyncFSBrowser/ESP_AsyncFSBrowser.ino
void SysModWeb::wsEvent(WebSocket * ws, WebClient * client, AwsEventType type, void * arg, byte *data, size_t len){
// if (!ws->count()) {
// if (!ws.count()) {
// USER_PRINT_Async("wsEvent no clients\n");
// return;
// }
Expand Down Expand Up @@ -334,12 +309,12 @@ void SysModWeb::wsEvent(WebSocket * ws, WebClient * client, AwsEventType type, v
//message is comprised of multiple frames or the frame is split into multiple packets
if(info->index == 0){
// if(info->num == 0)
// USER_PRINT_Async("ws[%s][%u] %s-message start\n", ws->url(), client->id(), (info->message_opcode == WS_TEXT)?"text":"binary");
// USER_PRINT_Async("ws[%s][%u] frame[%u] start[%llu]\n", ws->url(), client->id(), info->num, info->len);
// USER_PRINT_Async("ws[%s][%u] %s-message start\n", ws.url(), client->id(), (info->message_opcode == WS_TEXT)?"text":"binary");
// USER_PRINT_Async("ws[%s][%u] frame[%u] start[%llu]\n", ws.url(), client->id(), info->num, info->len);
USER_PRINTF("💀");
}

// USER_PRINT_Async("ws[%s][%u] frame[%u] %s[%llu - %llu]: ", ws->url(), client->id(), info->num, (info->message_opcode == WS_TEXT)?"text":"binary", info->index, info->index + len);
// USER_PRINT_Async("ws[%s][%u] frame[%u] %s[%llu - %llu]: ", ws.url(), client->id(), info->num, (info->message_opcode == WS_TEXT)?"text":"binary", info->index, info->index + len);
USER_PRINTF("💀");

if(info->opcode == WS_TEXT){
Expand All @@ -357,10 +332,10 @@ void SysModWeb::wsEvent(WebSocket * ws, WebClient * client, AwsEventType type, v
USER_PRINT_Async("%s\n",msg.c_str());

if ((info->index + len) == info->len) {
// USER_PRINT_Async("ws[%s][%u] frame[%u] end[%llu]\n", ws->url(), client->id(), info->num, info->len);
// USER_PRINT_Async("ws[%s][%u] frame[%u] end[%llu]\n", ws.url(), client->id(), info->num, info->len);
USER_PRINTF("👻");
if(info->final){
// USER_PRINT_Async("ws[%s][%u] %s-message end\n", ws->url(), client->id(), (info->message_opcode == WS_TEXT)?"text":"binary");
// USER_PRINT_Async("ws[%s][%u] %s-message end\n", ws.url(), client->id(), (info->message_opcode == WS_TEXT)?"text":"binary");
USER_PRINTF("☠️");
if(info->message_opcode == WS_TEXT)
client->text("I got your text message");
Expand Down Expand Up @@ -398,7 +373,7 @@ void SysModWeb::wsEvent(WebSocket * ws, WebClient * client, AwsEventType type, v
//pong message was received (in response to a ping request maybe)
// printClient("WS pong", client); //crashes!
// USER_PRINT_Async("WS pong\n");
// USER_PRINT_Async("ws[%s][%u] pong[%u]: %s\n", ws->url(), client->id(), len, (len)?(char*)data:"");
// USER_PRINT_Async("ws[%s][%u] pong[%u]: %s\n", ws.url(), client->id(), len, (len)?(char*)data:"");
USER_PRINT_Async("ws[%s][%u] pong[%u]: \n", ws->url(), client->id(), len);//, (len)?(char*)data:"");
}
}
Expand All @@ -413,28 +388,24 @@ void SysModWeb::sendDataWs(JsonVariant json, WebClient * client) {

//https://kcwong-joe.medium.com/passing-a-function-as-a-parameter-in-c-a132e69669f6
void SysModWeb::sendDataWs(std::function<void(AsyncWebSocketMessageBuffer *)> fill, size_t len, bool isBinary, WebClient * client) {
if (!ws) {
USER_PRINT_Async("sendDataWs no ws\n");
return;
}

xSemaphoreTake(wsMutex, portMAX_DELAY);

ws->cleanupClients(); //only if above threshold
ws.cleanupClients(); //only if above threshold

if (ws->count()) {
if (ws.count()) {
if (len > 8192)
USER_PRINTF("program error: sendDataWs BufferLen too high !!!%d\n", len);
AsyncWebSocketMessageBuffer * wsBuf = ws->makeBuffer(len); //assert failed: block_trim_free heap_tlsf.c:371 (block_is_free(block) && "block must be free"), AsyncWebSocket::makeBuffer(unsigned int)
AsyncWebSocketMessageBuffer * wsBuf = ws.makeBuffer(len); //assert failed: block_trim_free heap_tlsf.c:371 (block_is_free(block) && "block must be free"), AsyncWebSocket::makeBuffer(unsigned int)

if (wsBuf) {
wsBuf->lock();

fill(wsBuf); //function parameter

for (auto loopClient:ws->getClients()) {
for (auto loopClient:ws.getClients()) {
if (!client || client == loopClient) {
if (loopClient->status() == WS_CONNECTED && !loopClient->queueIsFull()) { //WS_MAX_QUEUED_MESSAGES / ws->count() / 2)) { //binary is lossy
if (loopClient->status() == WS_CONNECTED && !loopClient->queueIsFull()) { //WS_MAX_QUEUED_MESSAGES / ws.count() / 2)) { //binary is lossy
if ((!isBinary || loopClient->queueLength() <= 3)) {
isBinary?loopClient->binary(wsBuf): loopClient->text(wsBuf);
sendWsCounter++;
Expand All @@ -447,19 +418,19 @@ void SysModWeb::sendDataWs(std::function<void(AsyncWebSocketMessageBuffer *)> fi
else {
printClient("sendDataWs client full or not connected", loopClient);
// USER_PRINTF("sendDataWs client full or not connected\n");
ws->cleanupClients(); //only if above threshold
ws->_cleanBuffers();
ws.cleanupClients(); //only if above threshold
ws._cleanBuffers();
}
}
}
wsBuf->unlock();
ws->_cleanBuffers();
ws._cleanBuffers();
}
else {
USER_PRINT_Async("sendDataWs WS buffer allocation failed\n");
ws->closeAll(1013); //code 1013 = temporary overload, try again later
ws->cleanupClients(0); //disconnect ALL clients to release memory
ws->_cleanBuffers();
ws.closeAll(1013); //code 1013 = temporary overload, try again later
ws.cleanupClients(0); //disconnect ALL clients to release memory
ws._cleanBuffers();
}
}

Expand All @@ -469,7 +440,7 @@ void SysModWeb::sendDataWs(std::function<void(AsyncWebSocketMessageBuffer *)> fi
//add an url to the webserver to listen to
void SysModWeb::serveIndex(WebRequest *request) {

USER_PRINT_Async("Webserver: server->on serveIndex csdata %d-%d (%s)", PAGE_index, PAGE_index_L, request->url().c_str());
USER_PRINT_Async("Webserver: server.on serveIndex csdata %d-%d (%s)", PAGE_index, PAGE_index_L, request->url().c_str());

// if (captivePortal(request)) return;

Expand Down Expand Up @@ -600,7 +571,7 @@ void SysModWeb::jsonHandler(WebRequest *request, JsonVariant json) {
}

void SysModWeb::clientsToJson(JsonArray array, bool nameOnly, const char * filter) {
for (auto client:ws->getClients()) {
for (auto client:ws.getClients()) {
if (nameOnly) {
array.add(JsonString(client->remoteIP().toString().c_str(), JsonString::Copied));
} else {
Expand Down
55 changes: 30 additions & 25 deletions src/Sys/SysModWeb.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,18 +37,25 @@
class SysModWeb:public SysModule {

public:
static WebSocket *ws;// = nullptr;
static SemaphoreHandle_t wsMutex;// = xSemaphoreCreateMutex();

static unsigned8 sendWsCounter;// = 0;
static unsigned16 sendWsTBytes;// = 0;
static unsigned16 sendWsBBytes;// = 0;
static unsigned8 recvWsCounter;// = 0;
static unsigned16 recvWsBytes;// = 0;
static unsigned8 sendUDPCounter;// = 0;
static unsigned16 sendUDPBytes;// = 0;
static unsigned8 recvUDPCounter;// = 0;
static unsigned16 recvUDPBytes;// = 0;
#ifdef STARMOD_USE_Psychic
WebSocket ws = WebSocket();
WebServer server = WebServer();
#else
WebSocket ws = WebSocket("/ws");
WebServer server = WebServer(80);
#endif

SemaphoreHandle_t wsMutex = xSemaphoreCreateMutex();

unsigned8 sendWsCounter = 0;
unsigned16 sendWsTBytes = 0;
unsigned16 sendWsBBytes = 0;
unsigned8 recvWsCounter = 0;
unsigned16 recvWsBytes = 0;
unsigned8 sendUDPCounter = 0;
unsigned16 sendUDPBytes = 0;
unsigned8 recvUDPCounter = 0;
unsigned16 recvUDPBytes = 0;

SysModWeb();

Expand All @@ -60,23 +67,23 @@ class SysModWeb:public SysModule {

void connectedChanged();

static void wsEvent(WebSocket * ws, WebClient * client, AwsEventType type, void * arg, byte *data, size_t len);
void wsEvent(WebSocket * ws, WebClient * client, AwsEventType type, void * arg, byte *data, size_t len);

//send json to client or all clients
static void sendDataWs(JsonVariant json = JsonVariant(), WebClient * client = nullptr);
static void sendDataWs(std::function<void(AsyncWebSocketMessageBuffer *)> fill, size_t len, bool isBinary, WebClient * client = nullptr);
void sendDataWs(JsonVariant json = JsonVariant(), WebClient * client = nullptr);
void sendDataWs(std::function<void(AsyncWebSocketMessageBuffer *)> fill, size_t len, bool isBinary, WebClient * client = nullptr);

//add an url to the webserver to listen to
static void serveIndex(WebRequest *request);
void serveIndex(WebRequest *request);
//mdl and WLED style state and info
static void serveJson(WebRequest *request);
void serveJson(WebRequest *request);


// curl -F '[email protected]' 192.168.8.213/upload
static void serveUpload(WebRequest *request, const String& filename, size_t index, byte *data, size_t len, bool final);
void serveUpload(WebRequest *request, const String& filename, size_t index, byte *data, size_t len, bool final);
// curl -s -F "update=@/Users/ewoudwijma/Developer/GitHub/ewowi/StarMod/.pio/build/esp32dev/firmware.bin" 192.168.8.102/update /dev/null &
static void serveUpdate(WebRequest *request, const String& filename, size_t index, byte *data, size_t len, bool final);
static void serveFiles(WebRequest *request);
void serveUpdate(WebRequest *request, const String& filename, size_t index, byte *data, size_t len, bool final);
void serveFiles(WebRequest *request);

//processJsonUrl handles requests send in javascript using fetch and from a browser or curl
//try this !!!: curl -X POST "http://192.168.121.196/json" -d '{"pin2":false}' -H "Content-Type: application/json"
Expand All @@ -86,7 +93,7 @@ class SysModWeb:public SysModule {
//curl -X POST "http://192.168.8.152/json" -d '{"nrOfLeds":2000}' -H "Content-Type: application/json"

//handle "v" and processJson (on /json)
static void jsonHandler(WebRequest *request, JsonVariant json);
void jsonHandler(WebRequest *request, JsonVariant json);

//Is this an IP?
bool isIp(String str) {
Expand Down Expand Up @@ -158,17 +165,15 @@ class SysModWeb:public SysModule {
JsonObject getResponseObject();
void sendResponseObject(WebClient * client = nullptr);

static void printClient(const char * text, WebClient * client) {
void printClient(const char * text, WebClient * client) {
USER_PRINTF("%s client: %d ...%d q:%d l:%d s:%d (#:%d)\n", text, client?client->id():-1, client?client->remoteIP()[3]:-1, client->queueIsFull(), client->queueLength(), client->status(), client->server()->count());
//status: { WS_DISCONNECTED, WS_CONNECTED, WS_DISCONNECTING }
}

private:
bool modelUpdated = false;

static bool clientsChanged;// = false;;

static WebServer *server;// = nullptr;
bool clientsChanged = false;

JsonDocument *responseDocLoopTask = nullptr;
JsonDocument *responseDocAsyncTCP = nullptr;
Expand Down
2 changes: 1 addition & 1 deletion src/testOutput.txt
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ setValue var clStatus[0] value null not array, creating
setValue var clLength[0] value null not array, creating
sendDataWs client full or not connected client: 1 ...126 q:0 l:12 s:1 (#:1)
sendDataWs client full or not connected client: 1 ...126 q:0 l:12 s:1 (#:1)
αWebserver: server->on addUrl / text/html csdata 1061164428-20841 (/)α!
αWebserver: server.on addUrl / text/html csdata 1061164428-20841 (/)α!
αWS Client disconnected client: 1 ...0 q:1 l:0 s:2 (#:0)
αWS client connected client: 2 ...126 q:0 l:0 s:1 (#:1)
αWS event data client: 2 ...126 q:0 l:15 s:1 (#:1)
Expand Down

0 comments on commit f7f621c

Please sign in to comment.