Updated WebUI
This commit is contained in:
		| @@ -2,52 +2,46 @@ | ||||
|  | ||||
| AsyncWebServer webServer(80); | ||||
|  | ||||
| typedef enum | ||||
| { | ||||
|   RESPMSG_HIDE, | ||||
|   RESPMSG_SUCCESS, | ||||
|   RESPMSG_INFO, | ||||
|   RESPMSG_WARNING, | ||||
|   RESPMSG_DANGER | ||||
| } statusResponseMessage_Type_t; | ||||
| char StatusResponseMessage[64]; | ||||
| statusResponseMessage_Type_t StatusResponseMessage_Type = RESPMSG_INFO; | ||||
|  | ||||
| #ifdef CAPTIVE | ||||
| DNSServer dnsServer; | ||||
| #endif | ||||
| AsyncWebServer server(80); | ||||
| const char *PARAM_MESSAGE = "message"; | ||||
|  | ||||
| String processor(const String &var); | ||||
| void WebserverPOST_Callback(AsyncWebServerRequest *request); | ||||
| void WebserverNotFound_Callback(AsyncWebServerRequest *request); | ||||
| void Webserver_Callback(AsyncWebServerRequest *request); | ||||
| void WebserverCommands_Callback(String input); | ||||
| void WebserverFirmwareUpdate_Callback(AsyncWebServerRequest *request, const String &filename, size_t index, uint8_t *data, size_t len, bool final); | ||||
| void WebserverEERestore_Callback(AsyncWebServerRequest *request, const String &filename, size_t index, uint8_t *data, size_t len, bool final); | ||||
| void WebServerEEJSON_Callback(AsyncWebServerRequest *request); | ||||
| void GetFlashVersion(char *buff, size_t buff_size); | ||||
|  | ||||
| AsyncWebSocket webSocket("/ws"); | ||||
|  | ||||
| void WebsocketEvent_Callback(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventType type, void *arg, uint8_t *data, size_t len); | ||||
| void Websocket_HandleMessage(void *arg, uint8_t *data, size_t len); | ||||
|  | ||||
| void initWebUI() | ||||
| { | ||||
|   if (!LittleFS.begin()) | ||||
|   { | ||||
|     Serial.println("An Error has occurred while mounting LittleFS"); | ||||
|     Debug_pushMessage("An Error has occurred while mounting LittleFS\n"); | ||||
|     MaintainDTC(DTC_FLASHFS_ERROR, DTC_CRITICAL, true); | ||||
|     return; | ||||
|   } | ||||
|  | ||||
|   GetFlashVersion(globals.FlashVersion, sizeof(globals.FlashVersion)); | ||||
|  | ||||
|   if (strcmp(globals.FlashVersion, QUOTE(FLASH_FS_VERSION))) | ||||
|   char buffer[6]; | ||||
|   snprintf(buffer, sizeof(buffer), "%d.%02d", constants.Required_Flash_Version_major, constants.Required_Flash_Version_minor); | ||||
|   if (strcmp(globals.FlashVersion, buffer)) | ||||
|   { | ||||
|     MaintainDTC(DTC_FLASHFS_VERSION_ERROR, DTC_WARN, true); | ||||
|   } | ||||
|  | ||||
|   MDNS.begin(globals.DeviceName); | ||||
|   MDNS.addService("telnet", "tcp", 23); | ||||
|   MDNS.addService("http", "tcp", 80); | ||||
|  | ||||
|   webSocket.onEvent(WebsocketEvent_Callback); | ||||
|   webServer.addHandler(&webSocket); | ||||
|  | ||||
|   webServer.serveStatic("/static/", LittleFS, "/static/").setCacheControl("max-age=360000"); | ||||
|   webServer.on("/", HTTP_GET, [](AsyncWebServerRequest *request) | ||||
|                { request->redirect("/index.htm"); }); | ||||
| @@ -63,51 +57,63 @@ void initWebUI() | ||||
|   webServer.begin(); | ||||
| } | ||||
|  | ||||
| void Webserver_Process() | ||||
| { | ||||
|   webSocket.cleanupClients(); | ||||
| } | ||||
| String processor(const String &var) | ||||
| { | ||||
|   if (var == "HOSTNAME") | ||||
|     return String(globals.DeviceName); | ||||
|   if (var == "SYSTEM_STATUS") | ||||
|     return String(globals.systemStatustxt); | ||||
|   if (var == "SW_VERSION") | ||||
|   { | ||||
|     char buffer[6]; | ||||
|     snprintf(buffer, sizeof(buffer), "%d.%02d", constants.FW_Version_major, constants.FW_Version_minor); | ||||
|     return String(buffer); | ||||
|   } | ||||
|   if (var == "FS_VERSION") | ||||
|     return String(globals.FlashVersion); | ||||
|   if (var == "GIT_REV") | ||||
|     return String(constants.GitHash); | ||||
|  | ||||
|   if (var == "SHOW_DTC_TABLE") | ||||
|     return globals.systemStatus == sysStat_Error ? "" : "hidden"; | ||||
|  | ||||
|   if (var == "SHOW_RESP_MESSAGE") | ||||
|     return StatusResponseMessage_Type != RESPMSG_HIDE ? "" : "hidden"; | ||||
|  | ||||
|   if (var == "RESP_MESSAGE_TYPE") | ||||
|   { | ||||
|     switch (StatusResponseMessage_Type) | ||||
|     { | ||||
|     case RESPMSG_SUCCESS: | ||||
|       return "success"; | ||||
|     case RESPMSG_INFO: | ||||
|       return "info"; | ||||
|     case RESPMSG_WARNING: | ||||
|       return "warning"; | ||||
|     case RESPMSG_DANGER: | ||||
|       return "danger"; | ||||
|     default: | ||||
|       return "info"; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   if (var == "RESP_MESSAGE") | ||||
|     return String(StatusResponseMessage); | ||||
|  | ||||
|   if (var == "BAT_REMAIN_CAPACITY") | ||||
|     return String(globals.battery_level); | ||||
|  | ||||
|   if (var == "DEVICE_NAME") | ||||
|   if (var == "DEVICENAME") | ||||
|     return String(globals.DeviceName); | ||||
|  | ||||
|   if (var == "BATTERY_TYPE") | ||||
|     return String(ConfigData.batteryType); | ||||
|   if (var == "BAT_VOLTAGE") | ||||
|     return String((float)globals.loadvoltage_mV / 1000.0); | ||||
|  | ||||
|   if (var == "PERSISTANCE_CHECKSUM") | ||||
|   { | ||||
|     char buffer[7]; | ||||
|     sprintf(buffer, "0x%04X", PersistenceData.checksum); | ||||
|     return String(buffer); | ||||
|   } | ||||
|   if (var == "WRITE_CYCLE_COUNT") | ||||
|     return String(PersistenceData.writeCycleCounter); | ||||
|   if (var == "PERSISTENCE_MARKER") | ||||
|     return String(globals.eePersistanceAdress); | ||||
|   if (var == "EEPROM_VERSION") | ||||
|     return String(ConfigData.EEPROM_Version); | ||||
|   if (var == "CONFIG_CHECKSUM") | ||||
|   { | ||||
|     char buffer[7]; | ||||
|     sprintf(buffer, "0x%04X", ConfigData.checksum); | ||||
|     return String(buffer); | ||||
|   } | ||||
|   if (var == "DTC_TABLE") | ||||
|   { | ||||
|     String temp; | ||||
|     String temp = ""; | ||||
|     char buff_timestamp[16]; // Format: DD-hh:mm:ss:xxx | ||||
|  | ||||
|     for (uint32_t i = 0; i < MAX_DTC_STORAGE; i++) | ||||
|     { | ||||
|       if (DTCStorage[i].Number > 0) | ||||
|       if (DTCStorage[i].Number < DTC_LAST_DTC) | ||||
|       { | ||||
|         sprintf(buff_timestamp, "%02d-%02d:%02d:%02d:%03d", | ||||
|                 DTCStorage[i].timestamp / 86400000,    // Days | ||||
| @@ -116,8 +122,23 @@ String processor(const String &var) | ||||
|                 DTCStorage[i].timestamp / 1000 % 60,   // Seconds | ||||
|                 DTCStorage[i].timestamp % 1000);       // milliseconds | ||||
|  | ||||
|         temp = "<tr><td>" + String(buff_timestamp); | ||||
|         temp = temp + "<tr data-dtc=" + String(DTCStorage[i].Number); | ||||
|         temp = temp + " data-debugval=" + String(DTCStorage[i].debugVal) + "><td>" + String(buff_timestamp); | ||||
|         temp = temp + "</td><td>" + String(DTCStorage[i].Number) + "</td><td>"; | ||||
|         temp = temp + "<img src=static/img/"; | ||||
|         switch (DTCStorage[i].severity) | ||||
|         { | ||||
|         case DTC_CRITICAL: | ||||
|           temp = temp + "critical"; | ||||
|           break; | ||||
|         case DTC_WARN: | ||||
|           temp = temp + "warn"; | ||||
|           break; | ||||
|         case DTC_INFO: | ||||
|           temp = temp + "info"; | ||||
|           break; | ||||
|         } | ||||
|         temp = temp + ".png></td><td>"; | ||||
|  | ||||
|         if (DTCStorage[i].active == DTC_ACTIVE) | ||||
|           temp = temp + "active"; | ||||
| @@ -174,20 +195,15 @@ String processor(const String &var) | ||||
|   if (var == "NAME_FAC_3") | ||||
|     return FACTION_3_NAME; | ||||
|  | ||||
|   if (var == "TITLE") | ||||
|     return DEVICE_NAME; | ||||
|  | ||||
|   if (var == "BATTERY_LEVEL") | ||||
|   if (var == "BATTERY_SELECT_OPTIONS") | ||||
|   { | ||||
|     return String(globals.battery_level); | ||||
|   } | ||||
|   if (var == "BATTERY_TYPE") | ||||
|   { | ||||
|     return String(BatteryString[ConfigData.batteryType]); | ||||
|   } | ||||
|   if (var == "BATTERY_VOLTAGE") | ||||
|   { | ||||
|     return String((float)globals.loadvoltage_mV / 1000.0); | ||||
|     String temp; | ||||
|     for (uint32_t i = 0; i < BatteryString_Elements; i++) | ||||
|     { | ||||
|       String selected = ConfigData.batteryType == i ? " selected " : ""; | ||||
|       temp = temp + "<option value=\"" + i + "\"" + selected + ">" + BatteryString[i] + "</option>"; | ||||
|     } | ||||
|     return temp; | ||||
|   } | ||||
|  | ||||
|   return String(); | ||||
| @@ -196,19 +212,24 @@ String processor(const String &var) | ||||
| void Webserver_Callback(AsyncWebServerRequest *request) | ||||
| { | ||||
|   request->send(LittleFS, "/index.htm", "text/html", false, processor); | ||||
|   StatusResponseMessage_Type = RESPMSG_HIDE; | ||||
| } | ||||
|  | ||||
| void WebserverPOST_Callback(AsyncWebServerRequest *request) | ||||
| { | ||||
|   request->send(LittleFS, "/post.htm", "text/html", false, processor); | ||||
|  | ||||
|   Debug_pushMessage("POST:\n"); | ||||
|   int paramsNr = request->params(); | ||||
|   for (int i = 0; i < paramsNr; i++) | ||||
|   { | ||||
|     AsyncWebParameter *p = request->getParam(i); | ||||
|     if (p->name() == "commandInput") | ||||
|       WebserverCommands_Callback(p->value()); | ||||
|     Debug_pushMessage("%s : %s\n", p->name().c_str(), p->value().c_str()); | ||||
|  | ||||
|     // begin: POST Form Settings | ||||
|     if (p->name() == "cmdsubmit") | ||||
|       globals.requestEEAction = EE_CFG_SAVE; | ||||
|     // end: POST Form Settings | ||||
|   } | ||||
|   request->send(LittleFS, "/index.htm", "text/html", false, processor); | ||||
| } | ||||
|  | ||||
| void WebserverNotFound_Callback(AsyncWebServerRequest *request) | ||||
| @@ -216,41 +237,6 @@ void WebserverNotFound_Callback(AsyncWebServerRequest *request) | ||||
|   request->send(404, "text/html", "Not found"); | ||||
| } | ||||
|  | ||||
| void WebserverCommands_Callback(String input) | ||||
| { | ||||
|   String command = input.substring(0, input.indexOf(' ')); | ||||
|   command.toUpperCase(); | ||||
|   StatusResponseMessage_Type = RESPMSG_HIDE; | ||||
|  | ||||
|   if (command == "RESET") | ||||
|   { | ||||
|     strcpy(StatusResponseMessage, "Counter Reset done"); | ||||
|     StatusResponseMessage_Type = RESPMSG_SUCCESS; | ||||
|  | ||||
|     PersistenceData.faction_1_timer = 0; | ||||
|     PersistenceData.faction_2_timer = 0; | ||||
|     PersistenceData.faction_3_timer = 0; | ||||
|     PersistenceData.activeFaction = NONE; | ||||
|   } | ||||
|   else if (command == "BAT3S") | ||||
|   { | ||||
|     strcpy(StatusResponseMessage, "Set BatteryType to LiPo 3S"); | ||||
|     StatusResponseMessage_Type = RESPMSG_SUCCESS; | ||||
|  | ||||
|     ConfigData.batteryType = BATTERY_LIPO_3S; | ||||
|     globals.requestEEAction = EE_CFG_SAVE; | ||||
|   } | ||||
|   else if (command == "BAT2S") | ||||
|   { | ||||
|     strcpy(StatusResponseMessage, "Set BatteryType to LiPo 2S"); | ||||
|     StatusResponseMessage_Type = RESPMSG_SUCCESS; | ||||
|  | ||||
|     ConfigData.batteryType = BATTERY_LIPO_2S; | ||||
|     globals.requestEEAction = EE_CFG_SAVE; | ||||
|   } | ||||
| } | ||||
|  | ||||
|  | ||||
| void GetFlashVersion(char *buff, size_t buff_size) | ||||
| { | ||||
|   File this_file = LittleFS.open("version", "r"); | ||||
| @@ -273,7 +259,7 @@ void WebserverFirmwareUpdate_Callback(AsyncWebServerRequest *request, const Stri | ||||
|  | ||||
|   if (!index) | ||||
|   { | ||||
|     Serial.println("Update"); | ||||
|     Debug_pushMessage("Update"); | ||||
|     size_t content_len = request->contentLength(); | ||||
|     int cmd = (filename.indexOf(".fs") > -1) ? U_FS : U_FLASH; | ||||
|     Update.runAsync(true); | ||||
| @@ -289,7 +275,7 @@ void WebserverFirmwareUpdate_Callback(AsyncWebServerRequest *request, const Stri | ||||
|   } | ||||
|   else | ||||
|   { | ||||
|     Serial.printf("Progress: %d%%\n", (Update.progress() * 100) / Update.size()); | ||||
|     Debug_pushMessage("Progress: %d%%\n", (Update.progress() * 100) / Update.size()); | ||||
|   } | ||||
|  | ||||
|   if (final) | ||||
| @@ -304,8 +290,7 @@ void WebserverFirmwareUpdate_Callback(AsyncWebServerRequest *request, const Stri | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|       Serial.println("Update complete"); | ||||
|       Serial.flush(); | ||||
|       Debug_pushMessage("Update complete\n"); | ||||
|       globals.systemStatus = sysStat_Shutdown; | ||||
|     } | ||||
|   } | ||||
| @@ -313,31 +298,68 @@ void WebserverFirmwareUpdate_Callback(AsyncWebServerRequest *request, const Stri | ||||
|  | ||||
| void WebserverEERestore_Callback(AsyncWebServerRequest *request, const String &filename, size_t index, uint8_t *data, size_t len, bool final) | ||||
| { | ||||
|  | ||||
|   bool ee_done = false; | ||||
|   bool validext = false; | ||||
|   static bool validext = false; | ||||
|   static char *buffer = NULL; | ||||
|   static uint32_t read_ptr = 0; | ||||
|   DeserializationError error; | ||||
|  | ||||
|   if (!index) | ||||
|   { | ||||
|     Serial.println("EEPROM restore"); | ||||
|     validext = (filename.indexOf(".ee.json") > -1); | ||||
|     if (validext) | ||||
|     { | ||||
|       buffer = (char *)malloc(1536); | ||||
|       read_ptr = 0; | ||||
|       if (buffer == NULL) | ||||
|         Debug_pushMessage("malloc() failed for EEPROM-Restore"); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   if (validext) | ||||
|   if (buffer != NULL) | ||||
|   { | ||||
|     Serial.println("Restoring EEPROM-Stuff"); | ||||
|     memcpy(buffer + read_ptr, data, len); | ||||
|     read_ptr = read_ptr + len; | ||||
|   } | ||||
|  | ||||
|   if (final) | ||||
|   { | ||||
|     if (buffer != NULL) | ||||
|     { | ||||
|       Serial.print(buffer); | ||||
|       StaticJsonDocument<1536> doc; | ||||
|       error = deserializeJson(doc, buffer); | ||||
|       if (error) | ||||
|       { | ||||
|         Debug_pushMessage("deserializeJson() failed: %s\n", error.f_str()); | ||||
|       } | ||||
|       else | ||||
|       { | ||||
|  | ||||
|         ConfigData.batteryType = (batteryType_t)doc["config"]["batteryType"].as<uint32_t>(); | ||||
|         ConfigData.EEPROM_Version = doc["config"]["EEPROM_Version"].as<uint32_t>(); | ||||
|  | ||||
|         PersistenceData.writeCycleCounter = doc["persis"]["writeCycleCounter"].as<uint16_t>(); | ||||
|         PersistenceData.activeFaction = (factions_t)doc["persis"]["activeFaction"].as<uint32_t>(); | ||||
|         PersistenceData.faction_1_timer = doc["persis"]["faction_1_timer"].as<uint32_t>(); | ||||
|         PersistenceData.faction_2_timer = doc["persis"]["faction_2_timer"].as<uint32_t>(); | ||||
|         PersistenceData.faction_3_timer = doc["persis"]["faction_3_timer"].as<uint32_t>(); | ||||
|         PersistenceData.checksum = doc["persis"]["checksum"].as<uint32_t>(); | ||||
|  | ||||
|         ee_done = true; | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     free(buffer); | ||||
|  | ||||
|     AsyncWebServerResponse *response = request->beginResponse(302, "text/plain", "Please wait while the device reboots"); | ||||
|     response->addHeader("Refresh", "20"); | ||||
|     response->addHeader("Location", "/"); | ||||
|     request->send(response); | ||||
|  | ||||
|     if (ee_done) | ||||
|     { | ||||
|       Serial.println("Update complete"); | ||||
|       Serial.flush(); | ||||
|       Debug_pushMessage("Update complete"); | ||||
|       globals.systemStatus = sysStat_Shutdown; | ||||
|     } | ||||
|     else | ||||
| @@ -355,13 +377,16 @@ void WebServerEEJSON_Callback(AsyncWebServerRequest *request) | ||||
|   char buffer[16]; | ||||
|  | ||||
|   fwinfo["DeviceName"] = globals.DeviceName; | ||||
|   fwinfo["FW-Version"] = QUOTE(SW_VERSION); | ||||
|   sprintf(buffer, "%d.%02d", constants.Required_Flash_Version_major, constants.Required_Flash_Version_minor); | ||||
|   fwinfo["FW-Version"] = buffer; | ||||
|   fwinfo["FS-Version"] = globals.FlashVersion; | ||||
|   snprintf_P(buffer, sizeof(buffer), "%s", constants.GitHash); | ||||
|   fwinfo["Git-Hash"] = buffer; | ||||
|  | ||||
|   JsonObject config = json.createNestedObject("config"); | ||||
|  | ||||
|   config["EEPROM_Version"] = ConfigData.EEPROM_Version; | ||||
|   | ||||
|   config["batteryType"] = ConfigData.batteryType; | ||||
|   sprintf(buffer, "0x%08X", ConfigData.checksum); | ||||
|   config["checksum"] = buffer; | ||||
|  | ||||
| @@ -373,7 +398,10 @@ void WebServerEEJSON_Callback(AsyncWebServerRequest *request) | ||||
|   JsonObject persis = json.createNestedObject("persis"); | ||||
|  | ||||
|   persis["writeCycleCounter"] = PersistenceData.writeCycleCounter; | ||||
|  | ||||
|   persis["activeFaction"] = PersistenceData.activeFaction; | ||||
|   persis["faction_1_timer"] = PersistenceData.faction_1_timer; | ||||
|   persis["faction_2_timer"] = PersistenceData.faction_2_timer; | ||||
|   persis["faction_3_timer"] = PersistenceData.faction_3_timer; | ||||
|   sprintf(buffer, "0x%08X", PersistenceData.checksum); | ||||
|   persis["checksum"] = buffer; | ||||
|  | ||||
| @@ -382,4 +410,52 @@ void WebServerEEJSON_Callback(AsyncWebServerRequest *request) | ||||
|   response->addHeader("Content-disposition", "attachment; filename=backup.ee.json"); | ||||
|  | ||||
|   request->send(response); | ||||
| } | ||||
|  | ||||
| void WebsocketEvent_Callback(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventType type, void *arg, uint8_t *data, size_t len) | ||||
| { | ||||
|   switch (type) | ||||
|   { | ||||
|   case WS_EVT_CONNECT: | ||||
|     Debug_pushMessage("WebSocket client #%u connected from %s\n", client->id(), client->remoteIP().toString().c_str()); | ||||
|     break; | ||||
|   case WS_EVT_DISCONNECT: | ||||
|     Debug_pushMessage("WebSocket client #%u disconnected\n", client->id()); | ||||
|     break; | ||||
|   case WS_EVT_DATA: | ||||
|     Websocket_HandleMessage(arg, data, len); | ||||
|     break; | ||||
|   case WS_EVT_PONG: | ||||
|   case WS_EVT_ERROR: | ||||
|     break; | ||||
|   } | ||||
| } | ||||
|  | ||||
| void Websocket_HandleMessage(void *arg, uint8_t *data, size_t len) | ||||
| { | ||||
|   AwsFrameInfo *info = (AwsFrameInfo *)arg; | ||||
|   if (info->final && info->index == 0 && info->len == len && info->opcode == WS_TEXT) | ||||
|   { | ||||
|     data[len] = 0; | ||||
|  | ||||
|     Debug_pushMessage("Got WebSocket Message: %s \n", (char *)data); | ||||
|  | ||||
|     if (strcmp((char *)data, "start") == 0) | ||||
|     { | ||||
|       SetDebugportStatus(dbg_Webui, enabled); | ||||
|     } | ||||
|     else if (strcmp((char *)data, "stop") == 0) | ||||
|     { | ||||
|       SetDebugportStatus(dbg_Webui, disabled); | ||||
|     } | ||||
|     else if (strcmp((char *)data, "foo") == 0) | ||||
|     { | ||||
|       Debug_pushMessage("Got WebSocket Message 'foo' from client\n"); | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
| void Websocket_PushLiveDebug(String Message) | ||||
| { | ||||
|   webSocket.textAll(Message + "\n"); | ||||
| } | ||||
		Reference in New Issue
	
	Block a user