diff --git a/src/ESPUI.cpp b/src/ESPUI.cpp index 4ab8009..bcc16d8 100644 --- a/src/ESPUI.cpp +++ b/src/ESPUI.cpp @@ -3,141 +3,213 @@ #include // Handle Websockets Communication -void onWsEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventType type, void * arg, uint8_t *data, size_t len){ - switch(type) { - case WS_EVT_DISCONNECT: - Serial.printf("Disconnected!\n"); - break; - case WS_EVT_CONNECT: - { - Serial.println("Connected"); - ESPUI.jsonDom(client); - Serial.println("JSON Data Sent to Client!"); - } - break; - case WS_EVT_DATA: - String msg = ""; - for (size_t i = 0; i < len; i++) { - msg += (char) data[i]; - } - if(msg.startsWith("bdown:")){ - ESPUI.controls[msg.substring(6).toInt()]->callback(msg.substring(6).toInt(), B_DOWN); - }else if(msg.startsWith("bup:")){ - ESPUI.controls[msg.substring(4).toInt()]->callback(msg.substring(4).toInt(), B_UP); - }else if(msg.startsWith("pfdown:")){ - ESPUI.controls[msg.substring(7).toInt()]->callback(msg.substring(7).toInt(), P_FOR_DOWN); - }else if(msg.startsWith("pfup:")){ - ESPUI.controls[msg.substring(5).toInt()]->callback(msg.substring(5).toInt(), P_FOR_UP); - }else if(msg.startsWith("pldown:")){ - ESPUI.controls[msg.substring(7).toInt()]->callback(msg.substring(7).toInt(), P_LEFT_DOWN); - }else if(msg.startsWith("plup:")){ - ESPUI.controls[msg.substring(5).toInt()]->callback(msg.substring(5).toInt(), P_LEFT_UP); - }else if(msg.startsWith("prdown:")){ - ESPUI.controls[msg.substring(7).toInt()]->callback(msg.substring(7).toInt(), P_RIGHT_DOWN); - }else if(msg.startsWith("prup:")){ - ESPUI.controls[msg.substring(5).toInt()]->callback(msg.substring(5).toInt(), P_RIGHT_UP); - }else if(msg.startsWith("pbdown:")){ - ESPUI.controls[msg.substring(7).toInt()]->callback(msg.substring(7).toInt(), P_BACK_DOWN); - }else if(msg.startsWith("pbup:")){ - ESPUI.controls[msg.substring(5).toInt()]->callback(msg.substring(5).toInt(), P_BACK_UP); - }else if(msg.startsWith("pcdown:")){ - ESPUI.controls[msg.substring(7).toInt()]->callback(msg.substring(7).toInt(), P_CENTER_DOWN); - }else if(msg.startsWith("pcup:")){ - ESPUI.controls[msg.substring(5).toInt()]->callback(msg.substring(5).toInt(), P_CENTER_UP); - }else if(msg.startsWith("sactive:")){ - ESPUI.updateSwitcher(msg.substring(8).toInt(), true); - ESPUI.controls[msg.substring(8).toInt()]->callback(msg.substring(8).toInt(), S_ACTIVE); - }else if(msg.startsWith("sinactive:")){ - ESPUI.updateSwitcher(msg.substring(10).toInt(), false); - ESPUI.controls[msg.substring(10).toInt()]->callback(msg.substring(10).toInt(), S_INACTIVE); - } - break; +void onWsEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, + AwsEventType type, void *arg, uint8_t *data, size_t len) { + switch (type) { + case WS_EVT_DISCONNECT: + if(debug) Serial.printf("Disconnected!\n"); + break; + case WS_EVT_CONNECT: { + if(debug) Serial.println("Connected"); + ESPUI.jsonDom(client); + if(debug) Serial.println("JSON Data Sent to Client!"); + } break; + case WS_EVT_DATA: + String msg = ""; + for (size_t i = 0; i < len; i++) { + msg += (char)data[i]; } + if (msg.startsWith("bdown:")) { + Control* c = ESPUI.controls[msg.substring(6).toInt()]; + c->callback(c, B_DOWN); + } else if (msg.startsWith("bup:")) { + Control* c = ESPUI.controls[msg.substring(4).toInt()]; + c->callback(c, B_UP); + } else if (msg.startsWith("pfdown:")) { + Control* c = ESPUI.controls[msg.substring(7).toInt()]; + c->callback(c, P_FOR_DOWN); + } else if (msg.startsWith("pfup:")) { + Control* c = ESPUI.controls[msg.substring(5).toInt()]; + c->callback(c, P_FOR_UP); + } else if (msg.startsWith("pldown:")) { + Control* c = ESPUI.controls[msg.substring(7).toInt()]; + c->callback(c, P_LEFT_DOWN); + } else if (msg.startsWith("plup:")) { + Control* c = ESPUI.controls[msg.substring(5).toInt()]; + c->callback(c, P_LEFT_UP); + } else if (msg.startsWith("prdown:")) { + Control* c = ESPUI.controls[msg.substring(7).toInt()]; + c->callback(c, P_RIGHT_DOWN); + } else if (msg.startsWith("prup:")) { + Control* c = ESPUI.controls[msg.substring(5).toInt()]; + c->callback(c, P_RIGHT_UP); + } else if (msg.startsWith("pbdown:")) { + Control* c = ESPUI.controls[msg.substring(7).toInt()]; + c->callback(c, P_BACK_DOWN); + } else if (msg.startsWith("pbup:")) { + Control* c = ESPUI.controls[msg.substring(5).toInt()]; + c->callback(c, P_BACK_UP); + } else if (msg.startsWith("pcdown:")) { + Control* c = ESPUI.controls[msg.substring(7).toInt()]; + c->callback(c, P_CENTER_DOWN); + } else if (msg.startsWith("pcup:")) { + Control* c = ESPUI.controls[msg.substring(5).toInt()]; + c->callback(c, P_CENTER_UP); + } else if (msg.startsWith("sactive:")) { + Control* c = ESPUI.controls[msg.substring(8).toInt()]; + ESPUI.updateSwitcher(c->id, true); + c->callback(c, S_ACTIVE); + } else if (msg.startsWith("sinactive:")) { + Control* c = ESPUI.controls[msg.substring(10).toInt()]; + ESPUI.updateSwitcher(c->id, false); + c->callback(c, S_INACTIVE); + } + break; + } } -void ESPUIClass::label(const char* label, String value){ - Control* newL = new Control(); +void ESPUIClass::label(const char *label, String value) { + if (labelExists(label)) { + if (debug) Serial.println("UI ERROR: Element " + String(label) + " exists, skipping creating element!"); + return; + } + + Control *newL = new Control(); newL->type = UI_LABEL; newL->label = label; - if(value != "") newL->value = value; // Init with labeltext - else newL->value = String(label); + if (value != "") + newL->value = value; // Init with labeltext + else + newL->value = String(label); newL->callback = NULL; + newL->id = cIndex; controls[cIndex] = newL; cIndex++; } -void ESPUIClass::button(const char* label, void(* callBack)(int, int)){ - Control* newB = new Control(); +void ESPUIClass::button(const char *label, void (*callBack)(Control*, int)) { + if (labelExists(label)) { + if (debug) Serial.println("UI ERROR: Element " + String(label) + " exists, skipping creating element!"); + return; + } + + Control *newB = new Control(); newB->type = UI_BUTTON; newB->label = label; newB->callback = callBack; + newB->id = cIndex; controls[cIndex] = newB; cIndex++; } -void ESPUIClass::switcher(const char* label, bool startState, void(* callBack)(int, int)){ - Control* newS = new Control(); +void ESPUIClass::switcher(const char *label, bool startState, void (*callBack)(Control*, int)) { + if (labelExists(label)) { + if (debug) Serial.println("UI ERROR: Element " + String(label) + " exists, skipping creating element!"); + return; + } + + Control *newS = new Control(); newS->type = UI_SWITCHER; newS->label = label; newS->value = String(startState); newS->callback = callBack; + newS->id = cIndex; controls[cIndex] = newS; cIndex++; } -void ESPUIClass::pad(const char* label, bool center, void(* callBack)(int, int)){ - Control* newP = new Control(); - if(center)newP->type = UI_CPAD; - else newP->type = UI_PAD; +void ESPUIClass::pad(const char *label, bool center, void (*callBack)(Control*, int)) { + if (labelExists(label)) { + if (debug) Serial.println("UI ERROR: Element " + String(label) + " exists, skipping creating element!"); + return; + } + + Control *newP = new Control(); + if (center) + newP->type = UI_CPAD; + else + newP->type = UI_PAD; newP->label = label; newP->callback = callBack; + newP->id = cIndex; controls[cIndex] = newP; cIndex++; } -void ESPUIClass::print(int id, String value){ - if(idtype == UI_LABEL){ +void ESPUIClass::print(int id, String value) { + if (id < cIndex && controls[id]->type == UI_LABEL) { controls[id]->value = value; String json; StaticJsonBuffer<200> jsonBuffer; - JsonObject& root = jsonBuffer.createObject(); + JsonObject &root = jsonBuffer.createObject(); root["type"] = UPDATE_LABEL; root["value"] = value; root["id"] = String(id); root.printTo(json); this->ws->textAll(json); - }else{ - Serial.println(String("Error: ")+ String(id) +String(" is no label")); + } else { + if(debug) Serial.println(String("Error: ") + String(id) + String(" is no label")); } } -void ESPUIClass::updateSwitcher(int id, bool nValue){ - if(idtype == UI_SWITCHER){ - controls[id]->value = nValue?1:0; +void ESPUIClass::print(String label, String value) { + if (!labelExists(label)) { + if (debug) Serial.println("UI ERROR: Element does not " + String(label) + " exist, cannot update!"); + return; + } + print(getIdByLabel(label), value); +} + +void ESPUIClass::updateSwitcher(int id, bool nValue) { + if (id < cIndex && controls[id]->type == UI_SWITCHER) { + controls[id]->value = nValue ? 1 : 0; String json; StaticJsonBuffer<200> jsonBuffer; - JsonObject& root = jsonBuffer.createObject(); + JsonObject &root = jsonBuffer.createObject(); root["type"] = UPDATE_SWITCH; - root["value"] = nValue?1:0; + root["value"] = nValue ? 1 : 0; root["id"] = String(id); root.printTo(json); this->ws->textAll(json); - }else{ - Serial.println(String("Error: ")+ String(id) +String(" is no switcher")); + } else { + if(debug) Serial.println(String("Error: ") + String(id) + String(" is no switcher")); } } +void ESPUIClass::updateSwitcher(String label, bool nValue) { + if (!labelExists(label)) { + if (debug) + Serial.println("UI ERROR: Element does not " + String(label) + " exist, cannot update!"); + return; + } + updateSwitcher(getIdByLabel(label), nValue); +} + +int ESPUIClass::getIdByLabel(String label) { + for (int i = 0; i < cIndex; i++) { + if (String(controls[i]->label) == label) + return i; + } + return -1; // failed, nonexistant +} + +bool ESPUIClass::labelExists(String label) { + for (int i = 0; i < cIndex; i++) { + if (String(controls[i]->label) == label) return true; + } + return false; +} // Convert & Transfer Arduino elements to JSON elements -void ESPUIClass::jsonDom(AsyncWebSocketClient * client){ - for(int i=-1; i jsonBuffer; - JsonObject& root = jsonBuffer.createObject(); - if(i == -1){ + JsonObject &root = jsonBuffer.createObject(); + if (i == -1) { root["type"] = UI_TITEL; root["label"] = String(ui_title); - }else{ + } else { root["type"] = controls[i]->type; root["label"] = String(controls[i]->label); root["value"] = String(controls[i]->value); @@ -148,8 +220,7 @@ void ESPUIClass::jsonDom(AsyncWebSocketClient * client){ } } - -void ESPUIClass::begin(const char * _title){ +void ESPUIClass::begin(const char *_title) { ui_title = _title; server = new AsyncWebServer(80); ws = new AsyncWebSocket("/ws"); @@ -158,17 +229,16 @@ void ESPUIClass::begin(const char * _title){ server->addHandler(ws); server->serveStatic("/", SPIFFS, "/").setDefaultFile("index.htm"); - //Heap for general Servertest - server->on("/heap", HTTP_GET, [](AsyncWebServerRequest *request){ + // Heap for general Servertest + server->on("/heap", HTTP_GET, [](AsyncWebServerRequest *request) { request->send(200, "text/plain", String(ESP.getFreeHeap())); }); - server->onNotFound([](AsyncWebServerRequest *request){ - request->send(404); - }); + server->onNotFound( + [](AsyncWebServerRequest *request) { request->send(404); }); server->begin(); - Serial.println("UI Initialized"); + if(debug) Serial.println("UI Initialized"); } ESPUIClass ESPUI; diff --git a/src/ESPUI.h b/src/ESPUI.h index 64178a0..2a97372 100644 --- a/src/ESPUI.h +++ b/src/ESPUI.h @@ -3,6 +3,8 @@ #define HARDWARE "esp32" +#define debug true + //ifdef 8266 //#include "Hash.h" @@ -18,10 +20,11 @@ typedef struct Control { - unsigned int type; - const char *label; - void (*callback)(int, int); - String value; + unsigned int type; + unsigned int id; // just mirroring the id here for practical reasons + const char *label; + void (*callback)(Control*, int); + String value; } Control; // Types @@ -53,30 +56,35 @@ typedef struct Control -class ESPUIClass{ +class ESPUIClass { public: - void begin(const char* _title); // Setup servers and page +void begin(const char* _title); // Setup servers and page - // Creating Elements - void label(const char* label, String value = ""); // Create Label - void button(const char* label, void(* callBack)(int, int)); // Create Event Button - void switcher(const char* label, bool startState, void(* callBack)(int, int)); // Create Toggle Button - void pad(const char* label, bool centerButton, void(* callBack)(int, int)); // Create Pad Control +// Creating Elements +void label(const char* label, String value = ""); // Create Label +void button(const char* label, void (* callBack)(Control*, int)); // Create Event Button +void switcher(const char* label, bool startState, void (* callBack)(Control*, int)); // Create Toggle Button +void pad(const char* label, bool centerButton, void (* callBack)(Control*, int)); // Create Pad Control - // Update Elements - void print(int id, String value); - void updateSwitcher(int id, bool nValue); +// Update Elements +void print(int id, String value); +void print(String label, String value); - // Variables --- - const char* ui_title = "ESPUI"; // Store UI Title and Header Name - int cIndex; // Control index - Control* controls[25]; - void jsonDom(AsyncWebSocketClient * client); +void updateSwitcher(int id, bool nValue); +void updateSwitcher(String label, bool nValue); + +// Variables --- +const char* ui_title = "ESPUI"; // Store UI Title and Header Name +int cIndex = 0; // Control index +Control* controls[25]; +void jsonDom(AsyncWebSocketClient * client); +int getIdByLabel(String label); +bool labelExists(String label); private: - AsyncWebServer* server; - AsyncWebSocket* ws; +AsyncWebServer* server; +AsyncWebSocket* ws; }; extern ESPUIClass ESPUI;