#include "QDPweb.h" #include #ifdef DEBUG_MODE #define debugPrintln(...) Serial.println(__VA_ARGS__) #else #define debugPrintln(...) #endif AsyncWebSocket ws("/dashws"); // Handle Websocket Requests void QDPwebClass::onWsEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventType type, void * arg, uint8_t *data, size_t len){ if(type == WS_EVT_CONNECT){ debugPrintln("[WEBSOCKET] Client connection received"); } else if(type == WS_EVT_DISCONNECT){ debugPrintln("[WEBSOCKET] Client disconnected"); } else if(type == WS_EVT_DATA){ AwsFrameInfo *info = (AwsFrameInfo*)arg; if (info->final && info->index == 0 && info->len == len) { String message = ""; if (info->opcode == WS_TEXT) { for (size_t i=0; ilen; i++) message += (char)data[i]; } else { char buff[3]; for (size_t i=0; ilen; i++) { sprintf(buff, "%02x ", (uint8_t) data[i]); message += buff ; } } debugPrintln("[WEBSOCKET] Message Received: "+message); StaticJsonDocument<500> doc; DeserializationError err = deserializeJson(doc, message); if (err) { debugPrintln(F("deserializeJson() failed: ")); debugPrintln(err.c_str()); }else{ JsonObject object = doc.as(); String command = object["command"]; if(command != ""){ if(command == "getLayout"){ debugPrintln("[WEBSOCKET] Got getLayout Command from Client "+String(client->id())); String result = ""; QDPweb.generateLayoutResponse(result); ws.text(client->id(), result); }else if(command == "getStats"){ debugPrintln("[WEBSOCKET] Got getStats Command from Client "+String(client->id())); String result = ""; QDPweb.generateStatsResponse(result); ws.text(client->id(), result); }else if(command == "reboot"){ String result = ""; QDPweb.generateRebootResponse(result); ws.text(client->id(), result); #if defined(ESP8266) ESP.restart(); #elif defined(ESP32) esp_task_wdt_init(1,true); esp_task_wdt_add(NULL); while(true); #endif }else if(command == "buttonClicked"){ if(QDPweb._buttonClickFunc != NULL){ const char* buttonId = object["id"]; for(int i=0; i < BUTTON_CARD_LIMIT; i++){ if(QDPweb.button_card_id[i] == buttonId){ QDPweb._buttonClickFunc(buttonId); return; } } debugPrintln("buttonClicked Command didn't match any ID in our records! Rouge Request..."); } } else if (command == "sliderChanged"){ if(QDPweb._sliderChangedFunc != NULL){ const char* sliderId = object["id"]; int sliderValue = object["value"]; for(int i=0; i < SLIDER_CARD_LIMIT; i++){ if(QDPweb.slider_card_id[i] == sliderId){ QDPweb._sliderChangedFunc(sliderId, sliderValue); // Send Confirmation QDPweb.slider_card_value[i] = sliderValue; ws.textAll("{\"response\": \"updateSliderCard\", \"id\": \""+(String)sliderId+"\", \"value\": "+sliderValue+"}"); return; } } debugPrintln("sliderChanged Command didn't match any ID in our records! Rouge Request..."); } } }else{ debugPrintln("[WEBSOCKET] Invalid Command"); } } } } } ////////////////////// // Public Functions // ////////////////////// void QDPwebClass::init(AsyncWebServer& server){ server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){ // Send File AsyncWebServerResponse *response = request->beginResponse_P(200, "text/html", DASH_HTML, DASH_HTML_SIZE); response->addHeader("Content-Encoding","gzip"); request->send(response); }); #ifdef DEBUG_MODE server.on("/debug", HTTP_GET, [&](AsyncWebServerRequest *request){ String json = ""; generateLayoutResponse(json); request->send(200, "application/json", json); }); #endif ws.onEvent(onWsEvent); server.addHandler(&ws); } ///////////////// // Number Card // ///////////////// // Add Number Card with Custom Value void QDPwebClass::addNumberCard(const char* _id, const char* _name, int _value){ if(_id != NULL){ for(int i=0; i < NUMBER_CARD_LIMIT; i++){ if(number_card_id[i] == ""){ debugPrintln("[DASH] Found an empty slot in Number Cards. Inserted New Card at Index ["+String(i)+"]."); number_card_id[i] = _id; number_card_name[i] = _name; number_card_value[i] = _value; ws.textAll("{\"response\": \"updateLayout\"}"); break; } } return; }else{ return; } } // Update Number Card with Custom Value void QDPwebClass::updateNumberCard(const char* _id, int _value){ for(int i=0; i < NUMBER_CARD_LIMIT; i++){ if(number_card_id[i] == _id){ debugPrintln("[DASH] Updated Number Card at Index ["+String(i)+"]."); number_card_value[i] = _value; DynamicJsonDocument doc(250); JsonObject object = doc.to(); object["response"] = "updateNumberCard"; object["id"] = number_card_id[i]; object["value"] = number_card_value[i]; size_t len = measureJson(doc); AsyncWebSocketMessageBuffer * buffer = ws.makeBuffer(len); if (buffer) { serializeJson(doc, (char *)buffer->get(), len + 1); ws.textAll(buffer); }else{ debugPrintln("[DASH] Websocket Buffer Error"); } break; } } return; } ////////////////////// // Temperature Card // ////////////////////// // Add Temperature Card with Custom Value void QDPwebClass::addTemperatureCard(const char* _id, const char* _name, int _type, int _value){ if(_id != NULL && _type >= 0 && _type <= TEMPERATURE_CARD_TYPES){ for(int i=0; i < TEMPERATURE_CARD_LIMIT; i++){ if(temperature_card_id[i] == ""){ debugPrintln("[DASH] Found an empty slot in Temperature Cards. Inserted New Card at Index ["+String(i)+"]."); temperature_card_id[i] = _id; temperature_card_name[i] = _name; temperature_card_type[i] = _type; temperature_card_value[i] = _value; ws.textAll("{\"response\": \"updateLayout\"}"); break; } } return; }else{ return; } } // Update Temperature Card with custom value void QDPwebClass::updateTemperatureCard(const char* _id, int _value){ for(int i=0; i < TEMPERATURE_CARD_LIMIT; i++){ if(temperature_card_id[i] == _id){ debugPrintln("[DASH] Updated Temperature Card at Index ["+String(i)+"]."); temperature_card_value[i] = _value; DynamicJsonDocument doc(250); JsonObject object = doc.to(); object["response"] = "updateTemperatureCard"; object["id"] = temperature_card_id[i]; object["value"] = temperature_card_value[i]; size_t len = measureJson(doc); AsyncWebSocketMessageBuffer * buffer = ws.makeBuffer(len); if (buffer) { serializeJson(doc, (char *)buffer->get(), len + 1); ws.textAll(buffer); }else{ debugPrintln("[DASH] Websocket Buffer Error"); } break; } } return; } /////////////////// // Humidity Card // /////////////////// // Add Humidity Card with Custom Value void QDPwebClass::addHumidityCard(const char* _id, const char* _name, int _value){ if(_id != NULL){ for(int i=0; i < HUMIDITY_CARD_LIMIT; i++){ if(humidity_card_id[i] == ""){ debugPrintln("[DASH] Found an empty slot in Humidity Cards. Inserted New Card at Index ["+String(i)+"]."); humidity_card_id[i] = _id; humidity_card_name[i] = _name; humidity_card_value[i] = _value; ws.textAll("{\"response\": \"updateLayout\"}"); break; } } return; }else{ return; } } // Update Humidity Card with Custom Value void QDPwebClass::updateHumidityCard(const char* _id, int _value){ for(int i=0; i < HUMIDITY_CARD_LIMIT; i++){ if(humidity_card_id[i] == _id){ debugPrintln("[DASH] Updated Humidity Card at Index ["+String(i)+"]."); humidity_card_value[i] = _value; DynamicJsonDocument doc(250); JsonObject object = doc.to(); object["response"] = "updateHumidityCard"; object["id"] = humidity_card_id[i]; object["value"] = humidity_card_value[i]; size_t len = measureJson(doc); AsyncWebSocketMessageBuffer * buffer = ws.makeBuffer(len); if (buffer) { serializeJson(doc, (char *)buffer->get(), len + 1); ws.textAll(buffer); }else{ debugPrintln("[DASH] Websocket Buffer Error"); } break; } } return; } ///////////////// // Status Card // ///////////////// // Add Status Card with Custom Value void QDPwebClass::addStatusCard(const char* _id, const char* _name, int _value){ if(_id != NULL && _value >= 0 && _value <= STATUS_CARD_TYPES){ for(int i=0; i < STATUS_CARD_LIMIT; i++){ if(status_card_id[i] == ""){ debugPrintln("[DASH] Found an empty slot in Status Cards. Inserted New Card at Index ["+String(i)+"]."); status_card_id[i] = _id; status_card_name[i] = _name; status_card_value[i] = _value; ws.textAll("{\"response\": \"updateLayout\"}"); break; } } return; }else{ return; } } // Add Status Card with Custom Boolean Value void QDPwebClass::addStatusCard(const char* _id, const char* _name, bool _value){ addStatusCard(_id, _name, _value ? 1 : 0); } // Update Status Card with Custom Value void QDPwebClass::updateStatusCard(const char* _id, int _value){ if(_value >= 0 && _value <= STATUS_CARD_TYPES){ for(int i=0; i < STATUS_CARD_LIMIT; i++){ if(status_card_id[i] == _id){ debugPrintln("[DASH] Updated Status Card at Index ["+String(i)+"]."); status_card_value[i] = _value; DynamicJsonDocument doc(250); JsonObject object = doc.to(); object["response"] = "updateStatusCard"; object["id"] = status_card_id[i]; object["value"] = status_card_value[i]; size_t len = measureJson(doc); AsyncWebSocketMessageBuffer * buffer = ws.makeBuffer(len); if (buffer) { serializeJson(doc, (char *)buffer->get(), len + 1); ws.textAll(buffer); }else{ debugPrintln("[DASH] Websocket Buffer Error"); } break; } } return; }else{ return; } } // Update Status Card with Custom Value void QDPwebClass::updateStatusCard(const char* _id, bool _value){ updateStatusCard(_id, _value ? 1 : 0); } ///////////////// // Button Card // ///////////////// // Add Button Card void QDPwebClass::addButtonCard(const char* _id, const char* _name){ if(_id != NULL){ for(int i=0; i < BUTTON_CARD_LIMIT; i++){ if(button_card_id[i] == ""){ debugPrintln("[DASH] Found an empty slot in Button Cards. Inserted New Card at Index ["+String(i)+"]."); button_card_id[i] = _id; button_card_name[i] = _name; break; } } return; }else{ return; } } ///////////////// // Slider Card // ///////////////// // Add Slider Card void QDPwebClass::addSliderCard(const char* _id, const char* _name, int _type){ if(_id != NULL && _type >= 0 && _type <= SLIDER_CARD_TYPES){ for(int i=0; i < SLIDER_CARD_LIMIT; i++){ if(slider_card_id[i] == ""){ debugPrintln("[DASH] Found an empty slot in Slider Cards. Inserted New Card at Index ["+String(i)+"]."); slider_card_id[i] = _id; slider_card_name[i] = _name; slider_card_type[i] = _type; slider_card_value[i] = 0; ws.textAll("{\"response\": \"updateLayout\"}"); break; } } return; }else{ return; } } // Update Slider Card with Custom Value void QDPwebClass::updateSliderCard(const char* _id, int _value){ for(int i=0; i < SLIDER_CARD_LIMIT; i++){ if(slider_card_id[i] == _id){ debugPrintln("[DASH] Updated Slider Card at Index ["+String(i)+"]."); slider_card_value[i] = _value; DynamicJsonDocument doc(250); JsonObject object = doc.to(); object["response"] = "updateSliderCard"; object["id"] = slider_card_id[i]; object["value"] = slider_card_value[i]; size_t len = measureJson(doc); AsyncWebSocketMessageBuffer * buffer = ws.makeBuffer(len); if (buffer) { serializeJson(doc, (char *)buffer->get(), len + 1); ws.textAll(buffer); }else{ debugPrintln("[DASH] Websocket Buffer Error (updateSliderCard())"); } break; } } return; } //////////////// // Line Chart // //////////////// // Add Line Chart void QDPwebClass::addLineChart(const char* _id, const char* _name, int _x_axis_value[], int _x_axis_size, const char* _y_axis_name, int _y_axis_value[], int _y_axis_size){ if(_id != NULL){ for(int i=0; i < LINE_CHART_LIMIT; i++){ if(line_chart_id[i] == ""){ debugPrintln("[DASH] Found an empty slot in Line Charts. Inserted New Chart at Index ["+String(i)+"]."); line_chart_id[i] = _id; line_chart_name[i] = _name; line_chart_x_axis_type[i] = false; line_chart_x_axis_size[i] = _x_axis_size; line_chart_y_axis_size[i] = _y_axis_size; line_chart_y_axis_name[i] = _y_axis_name; for(int v=0; v < _x_axis_size; v++){ line_chart_x_axis_value_int[i][v] = _x_axis_value[v]; } for(int v=0; v < _y_axis_size; v++){ line_chart_y_axis_value[i][v] = _y_axis_value[v]; } ws.textAll("{\"response\": \"updateLayout\"}"); break; } } return; }else{ return; } } // Add Line Chart void QDPwebClass::addLineChart(const char* _id, const char* _name, String _x_axis_value[], int _x_axis_size, const char* _y_axis_name, int _y_axis_value[], int _y_axis_size){ if(_id != NULL){ for(int i=0; i < LINE_CHART_LIMIT; i++){ if(line_chart_id[i] == ""){ debugPrintln("[DASH] Found an empty slot in Line Charts. Inserted New Chart at Index ["+String(i)+"]."); line_chart_id[i] = _id; line_chart_name[i] = _name; line_chart_x_axis_type[i] = true; line_chart_x_axis_size[i] = _x_axis_size; line_chart_y_axis_size[i] = _y_axis_size; line_chart_y_axis_name[i] = _y_axis_name; for(int v=0; v < _x_axis_size; v++){ line_chart_x_axis_value_string[i][v] = _x_axis_value[v]; } for(int v=0; v < _y_axis_size; v++){ line_chart_y_axis_value[i][v] = _y_axis_value[v]; } ws.textAll("{\"response\": \"updateLayout\"}"); break; } } return; }else{ return; } } // Update Line Chart of Int x Axis void QDPwebClass::updateLineChart(const char* _id, int _x_axis_value[], int _x_axis_size, int _y_axis_value[], int _y_axis_size){ for(int i=0; i < LINE_CHART_LIMIT; i++){ if(line_chart_id[i] == _id){ debugPrintln("[DASH] Updated Line Chart at Index ["+String(i)+"]."); if(line_chart_x_axis_type[i] == false){ DynamicJsonDocument doc(1000); JsonObject object = doc.to(); object["response"] = "updateLineChart"; object["id"] = line_chart_id[i]; line_chart_x_axis_size[i] = _x_axis_size; line_chart_y_axis_size[i] = _y_axis_size; JsonArray xaxis = object.createNestedArray("x_axis_value"); for(int v=0; v < _x_axis_size; v++){ line_chart_x_axis_value_int[i][v] = _x_axis_value[v]; xaxis.add(line_chart_x_axis_value_int[i][v]); } JsonArray yaxis = object.createNestedArray("y_axis_value"); for(int v=0; v < _y_axis_size; v++){ line_chart_y_axis_value[i][v] = _y_axis_value[v]; yaxis.add(line_chart_y_axis_value[i][v]); } size_t len = measureJson(doc); AsyncWebSocketMessageBuffer * buffer = ws.makeBuffer(len); if (buffer) { serializeJson(doc, (char *)buffer->get(), len + 1); ws.textAll(buffer); }else{ debugPrintln("[DASH] Websocket Buffer Error"); } } break; } } return; } // Update Line Chart of String x Axis void QDPwebClass::updateLineChart(const char* _id, String _x_axis_value[], int _x_axis_size, int _y_axis_value[], int _y_axis_size){ for(int i=0; i < LINE_CHART_LIMIT; i++){ if(line_chart_id[i] == _id){ debugPrintln("[DASH] Updated Line Chart at Index ["+String(i)+"]."); if(line_chart_x_axis_type[i] == true){ DynamicJsonDocument doc(1000); JsonObject object = doc.to(); object["response"] = "updateLineChart"; object["id"] = line_chart_id[i]; line_chart_x_axis_size[i] = _x_axis_size; line_chart_y_axis_size[i] = _y_axis_size; JsonArray xaxis = object.createNestedArray("x_axis_value"); for(int v=0; v < _x_axis_size; v++){ line_chart_x_axis_value_string[i][v] = _x_axis_value[v]; xaxis.add(line_chart_x_axis_value_string[i][v]); } JsonArray yaxis = object.createNestedArray("y_axis_value"); for(int v=0; v < _y_axis_size; v++){ line_chart_y_axis_value[i][v] = _y_axis_value[v]; yaxis.add(line_chart_y_axis_value[i][v]); } size_t len = measureJson(doc); AsyncWebSocketMessageBuffer * buffer = ws.makeBuffer(len); if (buffer) { serializeJson(doc, (char *)buffer->get(), len + 1); ws.textAll(buffer); }else{ debugPrintln("[DASH] Websocket Buffer Error"); } } break; } } return; } ///////////////// // Gauge Chart // ///////////////// // Add Gauge Card with Default Value void QDPwebClass::addGaugeChart(const char* _id, const char* _name, int _value){ if(_id != NULL){ for(int i=0; i < GAUGE_CHART_LIMIT; i++){ if(gauge_chart_id[i] == ""){ debugPrintln("[DASH] Found an empty slot in Gauge Cards. Inserted New Card at Index ["+String(i)+"]."); gauge_chart_id[i] = _id; gauge_chart_name[i] = _name; gauge_chart_value[i] = _value; ws.textAll("{\"response\": \"updateLayout\"}"); break; } } return; }else{ return; } } // Update Gauge Card with Custom Value void QDPwebClass::updateGaugeChart(const char* _id, int _value){ for(int i=0; i < GAUGE_CHART_LIMIT; i++){ if(gauge_chart_id[i] == _id){ debugPrintln("[DASH] Updated Gauge Chart at Index ["+String(i)+"]."); gauge_chart_value[i] = _value; DynamicJsonDocument doc(250); JsonObject object = doc.to(); object["response"] = "updateGaugeChart"; object["id"] = gauge_chart_id[i]; object["value"] = gauge_chart_value[i]; size_t len = measureJson(doc); AsyncWebSocketMessageBuffer * buffer = ws.makeBuffer(len); if (buffer) { serializeJson(doc, (char *)buffer->get(), len + 1); ws.textAll(buffer); }else{ debugPrintln("[DASH] Websocket Buffer Error"); } break; } } return; } /////////////////////// // Private Functions // /////////////////////// void QDPwebClass::generateLayoutResponse(String& result){ debugPrintln("Free HEAP = before = JSON Serialization: "+String(ESP.getFreeHeap())); size_t CAPACITY = getTotalResponseCapacity(); DynamicJsonDocument doc(CAPACITY+1000); JsonObject root = doc.to(); root["response"] = "getLayout"; root["version"] = "1"; root["size"] = CAPACITY+1000; // Add Stats JsonObject stats = root.createNestedObject("statistics"); if(stats_enabled){ stats["enabled"] = true; stats["hardware"] = HARDWARE; #if defined(ESP8266) stats["chipId"] = String(ESP.getChipId()); stats["sketchHash"] = ESP.getSketchMD5(); stats["macAddress"] = String(WiFi.macAddress()); stats["freeHeap"] = ESP.getFreeHeap(); stats["wifiMode"] = int(WiFi.getMode()); #elif defined(ESP32) stats["chipId"] = ESP.getEfuseMac(); stats["sketchHash"] = ESP.getSketchMD5(); stats["macAddress"] = String(WiFi.macAddress()); stats["freeHeap"] = ESP.getFreeHeap(); stats["wifiMode"] = int(WiFi.getMode()); #endif }else{ stats["enabled"] = false; } // Add Cards JsonArray cards = root.createNestedArray("cards"); for(int i=0; i < NUMBER_CARD_LIMIT; i++){ if(number_card_id[i] != ""){ DynamicJsonDocument carddoc(250); JsonObject jsoncard = carddoc.to(); jsoncard["id"] = number_card_id[i]; jsoncard["card_type"] = "number"; jsoncard["name"] = number_card_name[i]; jsoncard["value"] = number_card_value[i]; cards.add(jsoncard); } } for(int i=0; i < TEMPERATURE_CARD_LIMIT; i++){ if(temperature_card_id[i] != ""){ DynamicJsonDocument carddoc(250); JsonObject jsoncard = carddoc.to(); jsoncard["id"] = temperature_card_id[i]; jsoncard["card_type"] = "temperature"; jsoncard["name"] = temperature_card_name[i]; jsoncard["value_type"] = temperature_card_type[i]; jsoncard["value"] = temperature_card_value[i]; cards.add(jsoncard); } } for(int i=0; i < HUMIDITY_CARD_LIMIT; i++){ if(humidity_card_id[i] != ""){ DynamicJsonDocument carddoc(250); JsonObject jsoncard = carddoc.to(); jsoncard["id"] = humidity_card_id[i]; jsoncard["card_type"] = "humidity"; jsoncard["name"] = humidity_card_name[i]; jsoncard["value"] = humidity_card_value[i]; cards.add(jsoncard); } } for(int i=0; i < STATUS_CARD_LIMIT; i++){ if(status_card_id[i] != ""){ DynamicJsonDocument carddoc(250); JsonObject jsoncard = carddoc.to(); jsoncard["id"] = status_card_id[i]; jsoncard["card_type"] = "status"; jsoncard["name"] = status_card_name[i]; jsoncard["value"] = status_card_value[i]; cards.add(jsoncard); } } for(int i=0; i < BUTTON_CARD_LIMIT; i++){ if(button_card_id[i] != ""){ DynamicJsonDocument carddoc(250); JsonObject jsoncard = carddoc.to(); jsoncard["id"] = button_card_id[i]; jsoncard["card_type"] = "button"; jsoncard["name"] = button_card_name[i]; cards.add(jsoncard); } } for(int i=0; i < LINE_CHART_LIMIT; i++){ if(line_chart_id[i] != ""){ DynamicJsonDocument carddoc(1000); JsonObject jsoncard = carddoc.to(); jsoncard["id"] = line_chart_id[i]; jsoncard["card_type"] = "lineChart"; jsoncard["name"] = line_chart_name[i]; JsonArray xaxis = jsoncard.createNestedArray("x_axis_value"); if(line_chart_x_axis_type[i]){ // If type = String for(int v = 0; v < line_chart_x_axis_size[i]; v++){ xaxis.add(line_chart_x_axis_value_string[i][v]); } }else{ // If type = Integer for(int v = 0; v < line_chart_x_axis_size[i]; v++){ xaxis.add(line_chart_x_axis_value_int[i][v]); } } jsoncard["y_axis_name"] = line_chart_y_axis_name[i]; JsonArray yaxis = jsoncard.createNestedArray("y_axis_value"); for(int v=0; v < line_chart_y_axis_size[i]; v++){ yaxis.add(line_chart_y_axis_value[i][v]); } cards.add(jsoncard); } } for(int i=0; i < GAUGE_CHART_LIMIT; i++){ if(gauge_chart_id[i] != ""){ DynamicJsonDocument carddoc(250); JsonObject jsoncard = carddoc.to(); jsoncard["id"] = gauge_chart_id[i]; jsoncard["card_type"] = "gaugeChart"; jsoncard["value"] = gauge_chart_value[i]; jsoncard["name"] = gauge_chart_name[i]; cards.add(jsoncard); } } for(int i=0; i < SLIDER_CARD_LIMIT; i++){ if(slider_card_id[i] != ""){ DynamicJsonDocument carddoc(250); JsonObject jsoncard = carddoc.to(); jsoncard["id"] = slider_card_id[i]; jsoncard["card_type"] = "slider"; jsoncard["name"] = slider_card_name[i]; jsoncard["value"] = slider_card_value[i]; jsoncard["type"] = slider_card_type[i]; cards.add(jsoncard); } } serializeJson(doc, result); debugPrintln("Free HEAP = after = JSON Serialization: "+String(ESP.getFreeHeap())); return; } void QDPwebClass::generateStatsResponse(String& result){ debugPrintln("Free HEAP = before = JSON Serialization: "+String(ESP.getFreeHeap())); DynamicJsonDocument doc(500); JsonObject stats = doc.to(); if(stats_enabled){ stats["response"] = "getStats"; stats["enabled"] = true; stats["hardware"] = HARDWARE; #if defined(ESP8266) stats["chipId"] = String(ESP.getChipId()); stats["sketchHash"] = ESP.getSketchMD5(); stats["macAddress"] = String(WiFi.macAddress()); stats["freeHeap"] = ESP.getFreeHeap(); stats["wifiMode"] = int(WiFi.getMode()); #elif defined(ESP32) stats["chipId"] = ESP.getEfuseMac(); stats["sketchHash"] = ESP.getSketchMD5(); stats["macAddress"] = String(WiFi.macAddress()); stats["freeHeap"] = ESP.getFreeHeap(); stats["wifiMode"] = int(WiFi.getMode()); #endif }else{ stats["enabled"] = false; } serializeJson(doc, result); debugPrintln("Free HEAP = after = JSON Serialization: "+String(ESP.getFreeHeap())); return; } void QDPwebClass::generateRebootResponse(String& result){ debugPrintln("Free HEAP = before = JSON Serialization: "+String(ESP.getFreeHeap())); DynamicJsonDocument doc(200); JsonObject obj = doc.to(); obj["response"] = "reboot"; if(stats_enabled){ obj["done"] = true; }else{ obj["done"] = false; } serializeJson(doc, result); debugPrintln("Free HEAP = after = JSON Serialization: "+String(ESP.getFreeHeap())); return; } size_t QDPwebClass::getTotalResponseCapacity(){ size_t capacity = 0 + JSON_OBJECT_SIZE(3) + JSON_OBJECT_SIZE(10); size_t totalCards = 0; for(int i=0; i < NUMBER_CARD_LIMIT; i++){ if(number_card_id[i] != ""){ capacity += JSON_OBJECT_SIZE(3); totalCards++; } } for(int i=0; i < TEMPERATURE_CARD_LIMIT; i++){ if(temperature_card_id[i] != ""){ capacity += JSON_OBJECT_SIZE(5); totalCards++; } } for(int i=0; i < HUMIDITY_CARD_LIMIT; i++){ if(humidity_card_id[i] != ""){ capacity += JSON_OBJECT_SIZE(4); totalCards++; } } for(int i=0; i < STATUS_CARD_LIMIT; i++){ if(status_card_id[i] != ""){ capacity += JSON_OBJECT_SIZE(4); totalCards++; } } for(int i=0; i < BUTTON_CARD_LIMIT; i++){ if(button_card_id[i] != ""){ capacity += JSON_OBJECT_SIZE(3); totalCards++; } } for(int i=0; i < LINE_CHART_LIMIT; i++){ if(line_chart_id[i] != ""){ capacity += JSON_OBJECT_SIZE(4) + JSON_ARRAY_SIZE(line_chart_x_axis_size[i]) + JSON_ARRAY_SIZE(line_chart_y_axis_size[i]); totalCards++; } } for(int i=0; i < GAUGE_CHART_LIMIT; i++){ if(gauge_chart_id[i] != ""){ capacity += JSON_OBJECT_SIZE(3); totalCards++; } } for(int i=0; i < SLIDER_CARD_LIMIT; i++){ if(slider_card_id[i] != ""){ capacity += JSON_OBJECT_SIZE(5); totalCards++; } } capacity += JSON_ARRAY_SIZE(totalCards); return capacity; } size_t QDPwebClass::getNumberCardsLen(){ size_t total = 0; for(int i=0; i < NUMBER_CARD_LIMIT; i++){ if(number_card_id[i] != ""){ total++; } } return total; } size_t QDPwebClass::getTemperatureCardsLen(){ size_t total = 0; for(int i=0; i < TEMPERATURE_CARD_LIMIT; i++){ if(temperature_card_id[i] != ""){ total++; } } return total; } size_t QDPwebClass::getHumidityCardsLen(){ size_t total = 0; for(int i=0; i < HUMIDITY_CARD_LIMIT; i++){ if(humidity_card_id[i] != ""){ total++; } } return total; } size_t QDPwebClass::getStatusCardsLen(){ size_t total = 0; for(int i=0; i < STATUS_CARD_LIMIT; i++){ if(status_card_id[i] != ""){ total++; } } return total; } size_t QDPwebClass::getButtonCardsLen(){ size_t total = 0; for(int i=0; i < BUTTON_CARD_LIMIT; i++){ if(button_card_id[i] != ""){ total++; } } return total; } size_t QDPwebClass::getLineChartsLen(){ size_t total = 0; for(int i=0; i < LINE_CHART_LIMIT; i++){ if(line_chart_id[i] != ""){ total++; } } return total; } size_t QDPwebClass::getGaugeChartsLen(){ size_t total = 0; for(int i=0; i < GAUGE_CHART_LIMIT; i++){ if(gauge_chart_id[i] != ""){ total++; } } return total; } size_t QDPwebClass::getSliderCardsLen(){ size_t total = 0; for(int i=0; i < SLIDER_CARD_LIMIT; i++){ if(slider_card_id[i] != ""){ total++; } } return total; } QDPwebClass QDPweb;