diff --git a/Software/src/webui.cpp b/Software/src/webui.cpp index 25fe640..6838c8f 100644 --- a/Software/src/webui.cpp +++ b/Software/src/webui.cpp @@ -1,3 +1,16 @@ +/** + * @file webui.cpp + * + * @brief Implementation file for web-based user interface (WebUI) functions in the ChainLube application. + * + * This file contains the implementation of functions related to the initialization and processing of the + * web-based user interface (WebUI). It includes the setup of LittleFS, handling of firmware version checks, + * initialization of mDNS, setup of web server routes, and handling of various HTTP events. + * + * @author Marcel Peterkau + * @date 09.01.2024 + */ + #include "webui.h" AsyncWebServer webServer(80); @@ -20,8 +33,20 @@ void Websocket_RefreshClientData_DTCs(uint32_t client_id); void Websocket_RefreshClientData_Status(uint32_t client_id, bool send_mapping = false); void Websocket_RefreshClientData_Static(uint32_t client_id, bool send_mapping = false); +/** + * @brief Initializes the web-based user interface (WebUI) for the ChainLube application. + * + * This function sets up the necessary components for the WebUI, including mounting LittleFS, + * performing flash version checks, initializing mDNS, and configuring the web server with + * routes and event handlers. If any errors occur during setup, appropriate diagnostic messages + * are pushed to the debugging system, and potential error conditions are recorded as Diagnostic + * Trouble Codes (DTCs). + * + * @note This function should be called during the initialization phase of the application. + */ void initWebUI() { + // Attempt to mount LittleFS if (!LittleFS.begin()) { Debug_pushMessage("An Error has occurred while mounting LittleFS\n"); @@ -29,8 +54,10 @@ void initWebUI() return; } + // Retrieve the flash version GetFlashVersion(globals.FlashVersion, sizeof(globals.FlashVersion)); + // Compare the flash version with the required 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)) @@ -38,12 +65,15 @@ void initWebUI() MaintainDTC(DTC_FLASHFS_VERSION_ERROR, true); } + // Initialize mDNS and add service MDNS.begin(globals.DeviceName); MDNS.addService("http", "tcp", 80); + // Set up WebSocket event handler and attach to web server webSocket.onEvent(WebsocketEvent_Callback); webServer.addHandler(&webSocket); + // Serve static files and define routes webServer.serveStatic("/static/", LittleFS, "/static/").setCacheControl("max-age=360000"); webServer.serveStatic("/index.htm", LittleFS, "/index.htm").setCacheControl("max-age=360000"); webServer.on("/", HTTP_GET, [](AsyncWebServerRequest *request) @@ -55,9 +85,20 @@ void initWebUI() webServer.on( "/eeRestore", HTTP_POST, [](AsyncWebServerRequest *request) {}, WebserverEERestore_Callback); + // Start the web server webServer.begin(); } +/** + * @brief Processes the web server functionality for the ChainLube application. + * + * This function performs periodic processing tasks for the web server, including cleaning up + * WebSocket clients and refreshing client data when WebSocket connections are active. It ensures + * that WebSocket client data related to Diagnostic Trouble Codes (DTCs) and system status is + * updated at regular intervals. + * + * @note This function should be called in the main loop of the application. + */ void Webserver_Process() { static uint32_t previousMillis = 0; @@ -202,11 +243,29 @@ void WebserverPOST_Callback(AsyncWebServerRequest *request) } } +/** + * @brief Callback function for handling HTTP 404 (Not Found) errors on the web server. + * + * This function is invoked when an HTTP request results in a 404 error (Not Found). It sends + * a simple "Not found" text response with an HTTP status code of 404. + * + * @param request Pointer to the AsyncWebServerRequest object representing the HTTP request. + */ void WebserverNotFound_Callback(AsyncWebServerRequest *request) { request->send(404, "text/html", "Not found"); } +/** + * @brief Reads the flash version information from a file in LittleFS. + * + * This function reads the flash version information stored in a file named "version" in the + * LittleFS filesystem. It opens the file, reads the content until a carriage return ('\r') is + * encountered, and stores the result in the provided buffer. The buffer is null-terminated. + * + * @param buff Pointer to the buffer where the flash version information will be stored. + * @param buff_size Size of the buffer. + */ void GetFlashVersion(char *buff, size_t buff_size) { File this_file = LittleFS.open("version", "r"); @@ -224,6 +283,21 @@ void GetFlashVersion(char *buff, size_t buff_size) this_file.close(); } +/** + * @brief Callback function for handling firmware updates via the web server. + * + * This function is invoked during the firmware update process when a new firmware file + * is received. It handles the update process using the ESPAsyncHTTPUpdate library. The update + * process involves checking the firmware type, initializing the update, writing data, and finalizing + * the update. If the update is successful, it triggers a system shutdown. + * + * @param request Pointer to the AsyncWebServerRequest object. + * @param filename The name of the file being updated. + * @param index The index of the file being updated. + * @param data Pointer to the data buffer. + * @param len The length of the data buffer. + * @param final Boolean indicating if this is the final chunk of data. + */ void WebserverFirmwareUpdate_Callback(AsyncWebServerRequest *request, const String &filename, size_t index, uint8_t *data, size_t len, bool final) { @@ -266,6 +340,21 @@ void WebserverFirmwareUpdate_Callback(AsyncWebServerRequest *request, const Stri } } +/** + * @brief Callback function for handling EEPROM restore via the web server. + * + * This function is invoked during the EEPROM restore process when a new EEPROM file + * is received. It handles the restore process by reading the data from the received file, + * deserializing the JSON data, and updating the configuration and persistence data accordingly. + * If the restore is successful, it triggers a system shutdown. + * + * @param request Pointer to the AsyncWebServerRequest object. + * @param filename The name of the file being restored. + * @param index The index of the file being restored. + * @param data Pointer to the data buffer. + * @param len The length of the data buffer. + * @param final Boolean indicating if this is the final chunk of data. + */ void WebserverEERestore_Callback(AsyncWebServerRequest *request, const String &filename, size_t index, uint8_t *data, size_t len, bool final) { bool ee_done = false; @@ -350,6 +439,14 @@ void WebserverEERestore_Callback(AsyncWebServerRequest *request, const String &f } } +/** + * @brief Callback function for handling EEPROM JSON request via the web server. + * + * This function is invoked when a request for EEPROM JSON data is received. It constructs a JSON + * response containing information about the firmware, configuration, and persistence data. + * + * @param request Pointer to the AsyncWebServerRequest object. + */ void WebServerEEJSON_Callback(AsyncWebServerRequest *request) { AsyncResponseStream *response = request->beginResponseStream("application/json"); @@ -413,6 +510,19 @@ void WebServerEEJSON_Callback(AsyncWebServerRequest *request) request->send(response); } +/** + * @brief Callback function for handling WebSocket events. + * + * This function is invoked when events occur in the WebSocket communication, such as client connection, + * disconnection, reception of data, and others. It dispatches the events to the appropriate handlers. + * + * @param server Pointer to the AsyncWebSocket object. + * @param client Pointer to the AsyncWebSocketClient object representing the WebSocket client. + * @param type Type of WebSocket event. + * @param arg Event-specific argument. + * @param data Pointer to the received data (if applicable). + * @param len Length of the received data. + */ void WebsocketEvent_Callback(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventType type, void *arg, uint8_t *data, size_t len) { switch (type) @@ -435,6 +545,16 @@ void WebsocketEvent_Callback(AsyncWebSocket *server, AsyncWebSocketClient *clien } } +/** + * @brief Handles WebSocket messages received from clients. + * + * This function processes WebSocket messages, such as starting or stopping debugging, + * and provides appropriate responses. + * + * @param arg Pointer to the WebSocket frame information. + * @param data Pointer to the received data. + * @param len Length of the received data. + */ void Websocket_HandleMessage(void *arg, uint8_t *data, size_t len) { AwsFrameInfo *info = (AwsFrameInfo *)arg; @@ -459,11 +579,27 @@ void Websocket_HandleMessage(void *arg, uint8_t *data, size_t len) } } +/** + * @brief Pushes live debug messages to all WebSocket clients. + * + * This function sends a live debug message to all connected WebSocket clients. + * + * @param Message The debug message to be sent. + */ void Websocket_PushLiveDebug(String Message) { webSocket.textAll("DEBUG:" + Message); } +/** + * @brief Refreshes client data related to Diagnostic Trouble Codes (DTCs) on WebSocket clients. + * + * This function constructs a DTC-related string and sends it to a specific WebSocket client or + * broadcasts it to all connected WebSocket clients. + * + * @param client_id The ID of the WebSocket client to which the data should be sent. If 0, the data + * will be broadcasted to all connected clients. + */ void Websocket_RefreshClientData_DTCs(uint32_t client_id) { String temp = "DTC:"; @@ -497,6 +633,16 @@ void Websocket_RefreshClientData_DTCs(uint32_t client_id) } } +/** + * @brief Refreshes client data related to system status and relevant parameters on WebSocket clients. + * + * This function constructs a status-related string and sends it to a specific WebSocket client or + * broadcasts it to all connected WebSocket clients. It also sends a mapping of the status parameters. + * + * @param client_id The ID of the WebSocket client to which the data should be sent. If 0, the data + * will be broadcasted to all connected clients. + * @param send_mapping Flag indicating whether to send the parameter mapping to the client(s). + */ void Websocket_RefreshClientData_Status(uint32_t client_id, bool send_mapping) { @@ -529,6 +675,16 @@ void Websocket_RefreshClientData_Status(uint32_t client_id, bool send_mapping) } } +/** + * @brief Refreshes client data related to static configuration parameters on WebSocket clients. + * + * This function constructs a static configuration-related string and sends it to a specific WebSocket client or + * broadcasts it to all connected WebSocket clients. It also sends a mapping of the static configuration parameters. + * + * @param client_id The ID of the WebSocket client to which the data should be sent. If 0, the data + * will be broadcasted to all connected clients. + * @param send_mapping Flag indicating whether to send the parameter mapping to the client(s). + */ void Websocket_RefreshClientData_Static(uint32_t client_id, bool send_mapping) {