diff --git a/Software/include/common.h b/Software/include/common.h index ea7860e..aeecc09 100644 --- a/Software/include/common.h +++ b/Software/include/common.h @@ -68,6 +68,7 @@ // -> 6.90µl / Pulse #define DEFAULT_PUMP_DOSE 7 +// --- System status enum with sentinel --- typedef enum eSystem_Status { sysStat_Startup, @@ -76,7 +77,8 @@ typedef enum eSystem_Status sysStat_Wash, sysStat_Purge, sysStat_Error, - sysStat_Shutdown + sysStat_Shutdown, + SYSSTAT_COUNT // <- sentinel (must be last) } tSystem_Status; // Enum for different sources of speed input @@ -89,13 +91,10 @@ typedef enum SpeedSource_e SOURCE_GPS, SOURCE_CAN, SOURCE_OBD2_KLINE, - SOURCE_OBD2_CAN + SOURCE_OBD2_CAN, + SPEEDSOURCE_COUNT // <- sentinel (must be last) } SpeedSource_t; -// String representation of SpeedSource enum -extern const char *SpeedSourceString[]; -extern const size_t SpeedSourceString_Elements; - // Enum for GPS baud rates typedef enum GPSBaudRate_e { @@ -104,23 +103,29 @@ typedef enum GPSBaudRate_e BAUD_19200, BAUD_38400, BAUD_57600, - BAUD_115200 + BAUD_115200, + GPSBAUDRATE_COUNT // <- sentinel (must be last) } GPSBaudRate_t; -// String representation of GPSBaudRate enum -extern const char *GPSBaudRateString[]; -extern const size_t GPSBaudRateString_Elements; - // Enum for CAN bus sources typedef enum CANSource_e { KTM_890_ADV_R_2021, - KTM_1290_SD_R_2023 + KTM_1290_SD_R_2023, + CANSOURCE_COUNT // <- sentinel (must be last) } CANSource_t; -// String representation of CANSource enum -extern const char *CANSourceString[]; -extern const size_t CANSourceString_Elements; +// String tables (kept internal to the module) +extern const char * const SystemStatusString[SYSSTAT_COUNT]; +extern const char * const SpeedSourceString[SPEEDSOURCE_COUNT]; +extern const char * const GPSBaudRateString[GPSBAUDRATE_COUNT]; +extern const char * const CANSourceString[CANSOURCE_COUNT]; + +// Safe getters (centralized bounds check) +const char* ToString(SpeedSource_t v); +const char* ToString(GPSBaudRate_t v); +const char* ToString(CANSource_t v); +const char* ToString(tSystem_Status v); #define STARTUP_DELAY 2500 #define SHUTDOWN_DELAY_MS 2500 diff --git a/Software/include/globals.h b/Software/include/globals.h index dd52e66..02efaac 100644 --- a/Software/include/globals.h +++ b/Software/include/globals.h @@ -22,7 +22,6 @@ typedef struct Globals_s { tSystem_Status systemStatus = sysStat_Startup; /**< Current system status */ tSystem_Status resumeStatus = sysStat_Startup; /**< Status to resume after rain mode */ - char systemStatustxt[16] = ""; /**< Text representation of system status */ uint16_t purgePulses = 0; /**< Number of purge pulses */ EERequest_t requestEEAction = EE_IDLE; /**< EEPROM-related request */ char DeviceName[33]; /**< Device name */ diff --git a/Software/src/common.cpp b/Software/src/common.cpp index 6ffa341..e201b28 100644 --- a/Software/src/common.cpp +++ b/Software/src/common.cpp @@ -1,7 +1,20 @@ #include "common.h" +static const char kUnknownStr[] = "Unknown"; + +// ---- System status string table ---- +const char *const SystemStatusString[SYSSTAT_COUNT] = { + "Startup", + "Normal", + "Rain", + "Wash", + "Purge", + "Error", + "Shutdown", +}; + // String representation of SpeedSource enum -const char *SpeedSourceString[] = { +const char *const SpeedSourceString[SPEEDSOURCE_COUNT] = { #ifdef FEATURE_ENABLE_TIMER "Timer", #endif @@ -12,10 +25,8 @@ const char *SpeedSourceString[] = { "OBD2 (CAN)", }; -const size_t SpeedSourceString_Elements = sizeof(SpeedSourceString) / sizeof(SpeedSourceString[0]); - // String representation of GPSBaudRate enum -const char *GPSBaudRateString[] = { +const char *const GPSBaudRateString[GPSBAUDRATE_COUNT] = { "4800", "9600", "19200", @@ -24,12 +35,49 @@ const char *GPSBaudRateString[] = { "115200", }; -const size_t GPSBaudRateString_Elements = sizeof(GPSBaudRateString) / sizeof(GPSBaudRateString[0]); - // String representation of CANSource enum -const char *CANSourceString[] = { +const char *const CANSourceString[CANSOURCE_COUNT] = { "KTM 890 Adventure R (2021)", "KTM 1290 Superduke R (2023)", }; -const size_t CANSourceString_Elements = sizeof(CANSourceString) / sizeof(CANSourceString[0]); \ No newline at end of file +// ---- Centralized, safe getters ---- + +// ---- Local helper for range check ---- +static inline bool in_range(int v, int max_exclusive) +{ + return (v >= 0) && (v < max_exclusive); +} + +// ---- Safe getter ---- +const char *ToString(tSystem_Status v) +{ + const int i = static_cast(v); + return in_range(i, static_cast(SYSSTAT_COUNT)) + ? SystemStatusString[i] + : kUnknownStr; +} + +const char *ToString(SpeedSource_t v) +{ + const int i = static_cast(v); + return in_range(i, static_cast(SPEEDSOURCE_COUNT)) + ? SpeedSourceString[i] + : kUnknownStr; +} + +const char *ToString(GPSBaudRate_t v) +{ + const int i = static_cast(v); + return in_range(i, static_cast(GPSBAUDRATE_COUNT)) + ? GPSBaudRateString[i] + : kUnknownStr; +} + +const char *ToString(CANSource_t v) +{ + const int i = static_cast(v); + return in_range(i, static_cast(CANSOURCE_COUNT)) + ? CANSourceString[i] + : kUnknownStr; +} diff --git a/Software/src/config.cpp b/Software/src/config.cpp index c451ef7..c323835 100644 --- a/Software/src/config.cpp +++ b/Software/src/config.cpp @@ -615,21 +615,21 @@ uint32_t ConfigSanityCheck(bool autocorrect) LubeConfig.BleedingPulses = LubeConfig_defaults.BleedingPulses; } - if (!(LubeConfig.SpeedSource >= 0) || !(LubeConfig.SpeedSource < SpeedSourceString_Elements)) + if (!(LubeConfig.SpeedSource >= 0) || !(LubeConfig.SpeedSource < SPEEDSOURCE_COUNT)) { SET_BIT(setting_reset_bits, 11); if (autocorrect) LubeConfig.SpeedSource = LubeConfig_defaults.SpeedSource; } - if (!(LubeConfig.GPSBaudRate >= 0) || !(LubeConfig.GPSBaudRate < GPSBaudRateString_Elements)) + if (!(LubeConfig.GPSBaudRate >= 0) || !(LubeConfig.GPSBaudRate < GPSBAUDRATE_COUNT)) { SET_BIT(setting_reset_bits, 12); if (autocorrect) LubeConfig.GPSBaudRate = LubeConfig_defaults.GPSBaudRate; } - if (!(LubeConfig.CANSource >= 0) || !(LubeConfig.CANSource < CANSourceString_Elements)) + if (!(LubeConfig.CANSource >= 0) || !(LubeConfig.CANSource < CANSOURCE_COUNT)) { SET_BIT(setting_reset_bits, 13); if (autocorrect) diff --git a/Software/src/debugger.cpp b/Software/src/debugger.cpp index bb22dd0..61dbb29 100644 --- a/Software/src/debugger.cpp +++ b/Software/src/debugger.cpp @@ -459,7 +459,6 @@ void Debug_dumpGlobals() { Debug_pushMessage("systemStatus: %d\n", globals.systemStatus); Debug_pushMessage("resumeStatus: %d\n", globals.resumeStatus); - Debug_pushMessage("systemStatustxt: %s\n", globals.systemStatustxt); Debug_pushMessage("purgePulses: %d\n", globals.purgePulses); Debug_pushMessage("requestEEAction: %d\n", globals.requestEEAction); Debug_pushMessage("DeviceName: %s\n", globals.DeviceName); diff --git a/Software/src/lubeapp.cpp b/Software/src/lubeapp.cpp index af2be61..ac6172e 100644 --- a/Software/src/lubeapp.cpp +++ b/Software/src/lubeapp.cpp @@ -56,7 +56,6 @@ void RunLubeApp(uint32_t add_milimeters) if (lastSystemStatus != globals.systemStatus) { - strcpy_P(globals.systemStatustxt, PSTR("Startup")); LEDControl_SetBasic(LED_STARTUP_NORMAL, LED_PATTERN_BLINK); lastSystemStatus = globals.systemStatus; globals.resumeStatus = sysStat_Startup; @@ -72,7 +71,6 @@ void RunLubeApp(uint32_t add_milimeters) case sysStat_Normal: if (lastSystemStatus != globals.systemStatus) { - strcpy_P(globals.systemStatustxt, PSTR("Normal")); LEDControl_SetBasic(LED_NORMAL_COLOR, LED_PATTERN_ON); lastSystemStatus = globals.systemStatus; globals.resumeStatus = sysStat_Normal; @@ -89,7 +87,6 @@ void RunLubeApp(uint32_t add_milimeters) case sysStat_Rain: if (lastSystemStatus != globals.systemStatus) { - strcpy_P(globals.systemStatustxt, PSTR("Rain")); LEDControl_SetBasic(LED_RAIN_COLOR, LED_PATTERN_ON); lastSystemStatus = globals.systemStatus; globals.resumeStatus = sysStat_Rain; @@ -107,7 +104,6 @@ void RunLubeApp(uint32_t add_milimeters) if (lastSystemStatus != globals.systemStatus) { washModeRemainDistance = LubeConfig.WashMode_Distance; - strcpy_P(globals.systemStatustxt, PSTR("Wash")); LEDControl_SetBasic(LED_WASH_COLOR, LED_PATTERN_BREATH); lastSystemStatus = globals.systemStatus; } @@ -134,7 +130,6 @@ void RunLubeApp(uint32_t add_milimeters) if (lastSystemStatus != globals.systemStatus) { globals.purgePulses = LubeConfig.BleedingPulses; - strcpy_P(globals.systemStatustxt, PSTR("Purge")); LEDControl_SetBasic(LED_PURGE_COLOR, LED_PATTERN_BLINK); lastSystemStatus = globals.systemStatus; } @@ -161,7 +156,6 @@ void RunLubeApp(uint32_t add_milimeters) if (lastSystemStatus != globals.systemStatus) { - strcpy_P(globals.systemStatustxt, PSTR("Error")); LEDControl_SetBasic(LED_ERROR_COLOR, LED_PATTERN_BLINK_FAST); lastSystemStatus = globals.systemStatus; } @@ -173,7 +167,6 @@ void RunLubeApp(uint32_t add_milimeters) if (lastSystemStatus != globals.systemStatus) { - strcpy_P(globals.systemStatustxt, PSTR("Shutdown")); LEDControl_SetBasic(LED_SHUTDOWN_COLOR, LED_PATTERN_BREATH_REVERSE); lastSystemStatus = globals.systemStatus; } diff --git a/Software/src/main.cpp b/Software/src/main.cpp index 287cd67..7a14562 100644 --- a/Software/src/main.cpp +++ b/Software/src/main.cpp @@ -398,7 +398,7 @@ void Display_Process() DistRemain = DistRemain - (PersistenceData.TravelDistance_highRes_mm / 1000); // Display relevant information on the OLED screen based on system status - u8x8.printf(PSTR("Mode: %10s\n"), globals.systemStatustxt); + u8x8.printf(PSTR("Mode: %10s\n"), ToString(globals.systemStatus)); if (globals.systemStatus == sysStat_Error) { // Display the last Diagnostic Trouble Code (DTC) in case of an error @@ -412,7 +412,8 @@ void Display_Process() u8x8.printf(PSTR("WiFi: %10s\n"), (WiFi.getMode() == WIFI_AP ? "AP" : WiFi.getMode() == WIFI_OFF ? "OFF" : WiFi.getMode() == WIFI_STA ? "CLIENT" : "UNKNOWN")); - u8x8.printf(PSTR("Source: %8s\n"), SpeedSourceString[LubeConfig.SpeedSource]); + u8x8.printf(PSTR("Source: %8s\n"), ToString(LubeConfig.SpeedSource)); + u8x8.printf("%s\n", WiFi.localIP().toString().c_str()); } diff --git a/Software/src/webui.cpp b/Software/src/webui.cpp index d930f35..b4926cf 100644 --- a/Software/src/webui.cpp +++ b/Software/src/webui.cpp @@ -337,89 +337,145 @@ 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) +void WebserverEERestore_Callback(AsyncWebServerRequest *request, + const String &filename, + size_t index, + uint8_t *data, + size_t len, + bool final) { + constexpr size_t kBufCap = 1536; + bool ee_done = false; static bool validext = false; - static char *buffer = NULL; + static char *buffer = nullptr; static uint32_t read_ptr = 0; DeserializationError error; + // kleines Helferlein zum sicheren Kopieren & Terminieren + auto safe_copy = [](char *dst, size_t dst_sz, const char *src) + { + if (!dst || dst_sz == 0) + return; + if (!src) + { + dst[0] = '\0'; + return; + } + strncpy(dst, src, dst_sz - 1); + dst[dst_sz - 1] = '\0'; + }; + + // Grenzen/Hilfen für Enum-Ranges (Sentinel bevorzugt, sonst *_Elements) + const int maxSpeedSrc = static_cast(SPEEDSOURCE_COUNT); + const int maxGPSBaud = static_cast(GPSBAUDRATE_COUNT); + const int maxCANSrc = static_cast(CANSOURCE_COUNT); + if (!index) { validext = (filename.indexOf(".ee.json") > -1); if (validext) { - buffer = (char *)malloc(1536); + buffer = (char *)malloc(kBufCap); read_ptr = 0; - if (buffer == NULL) + if (!buffer) + { Debug_pushMessage("malloc() failed for EEPROM-Restore\n"); + } } } - if (buffer != NULL && len > 0) + // Chunked receive mit Cap/Trunkierungsschutz + if (buffer && len > 0) { - memcpy(buffer + read_ptr, data, len); - read_ptr = read_ptr + len; + size_t remain = (read_ptr < kBufCap) ? (kBufCap - read_ptr) : 0; + size_t to_copy = (len <= remain) ? len : remain; + if (to_copy > 0) + { + memcpy(buffer + read_ptr, data, to_copy); + read_ptr += to_copy; + } + else + { + Debug_pushMessage("EEPROM-Restore input exceeds buffer, truncating\n"); + } } if (final) { - if (buffer != NULL) + if (buffer) { - // Ensure zero-termination just in case - if (read_ptr >= 1536) - read_ptr = 1535; + // Null-terminieren + if (read_ptr == kBufCap) + read_ptr = kBufCap - 1; buffer[read_ptr] = '\0'; - Serial.print(buffer); - JsonDocument json; + // Parse + JsonDocument json; // entspricht deinem bisherigen Stil error = deserializeJson(json, buffer); if (error) { Debug_pushMessage("deserializeJson() failed: %s\n", error.f_str()); } - else + else if (validext) { + // ---- Konfiguration sicher in RAM übernehmen ---- + // clamp-Helfer passend zu deinen Sanity-Grenzen + auto clamp_u32 = [](uint32_t v, uint32_t lo, uint32_t hi) + { return (v < lo) ? lo : (v > hi ? hi : v); }; + auto clamp_u16 = [](uint16_t v, uint16_t lo, uint16_t hi) + { return (v < lo) ? lo : (v > hi ? hi : v); }; + auto clamp_u8 = [](uint8_t v, uint8_t lo, uint8_t hi) + { return (v < lo) ? lo : (v > hi ? hi : v); }; - LubeConfig.DistancePerLube_Default = json["config"]["DistancePerLube_Default"].as(); - LubeConfig.DistancePerLube_Rain = json["config"]["DistancePerLube_Rain"].as(); - LubeConfig.tankCapacity_ml = json["config"]["tankCapacity_ml"].as(); - LubeConfig.amountPerDose_microL = json["config"]["amountPerDose_microL"].as(); - LubeConfig.TankRemindAtPercentage = json["config"]["TankRemindAtPercentage"].as(); - LubeConfig.PulsePerRevolution = json["config"]["PulsePerRevolution"].as(); - LubeConfig.TireWidth_mm = json["config"]["TireWidth_mm"].as(); - LubeConfig.TireWidthHeight_Ratio = json["config"]["TireWidthHeight_Ratio"].as(); - LubeConfig.RimDiameter_Inch = json["config"]["RimDiameter_Inch"].as(); - LubeConfig.DistancePerRevolution_mm = json["config"]["DistancePerRevolution_mm"].as(); - LubeConfig.BleedingPulses = json["config"]["BleedingPulses"].as(); - LubeConfig.SpeedSource = (SpeedSource_t)json["config"]["SpeedSource"].as(); - LubeConfig.GPSBaudRate = (GPSBaudRate_t)json["config"]["GPSBaudRate"].as(); - LubeConfig.CANSource = (CANSource_t)json["config"]["CANSource"].as(); + // config.* + LubeConfig.DistancePerLube_Default = clamp_u32(json["config"]["DistancePerLube_Default"].as(), 0, 50000); + LubeConfig.DistancePerLube_Rain = clamp_u32(json["config"]["DistancePerLube_Rain"].as(), 0, 50000); + LubeConfig.tankCapacity_ml = clamp_u32(json["config"]["tankCapacity_ml"].as(), 0, 5000); + LubeConfig.amountPerDose_microL = clamp_u32(json["config"]["amountPerDose_microL"].as(), 0, 100); + LubeConfig.TankRemindAtPercentage = clamp_u8(json["config"]["TankRemindAtPercentage"].as(), 0, 100); + LubeConfig.PulsePerRevolution = clamp_u8(json["config"]["PulsePerRevolution"].as(), 0, 255); + LubeConfig.TireWidth_mm = clamp_u32(json["config"]["TireWidth_mm"].as(), 0, 500); + LubeConfig.TireWidthHeight_Ratio = clamp_u32(json["config"]["TireWidthHeight_Ratio"].as(), 0, 150); + LubeConfig.RimDiameter_Inch = clamp_u32(json["config"]["RimDiameter_Inch"].as(), 0, 30); + LubeConfig.DistancePerRevolution_mm = clamp_u32(json["config"]["DistancePerRevolution_mm"].as(), 0, 10000); + LubeConfig.BleedingPulses = clamp_u16(json["config"]["BleedingPulses"].as(), 0, 1000); + LubeConfig.WashMode_Distance = json["config"]["WashMode_Distance"].as(); // ggf. Grenzen anpassen + LubeConfig.WashMode_Interval = json["config"]["WashMode_Interval"].as(); // ggf. Grenzen anpassen LubeConfig.LED_Mode_Flash = json["config"]["LED_Mode_Flash"].as(); LubeConfig.LED_Max_Brightness = json["config"]["LED_Max_Brightness"].as(); LubeConfig.LED_Min_Brightness = json["config"]["LED_Min_Brightness"].as(); - strncpy(LubeConfig.wifi_ap_ssid, json["config"]["wifi_ap_ssid"].as(), sizeof(LubeConfig.wifi_ap_ssid)); - strncpy(LubeConfig.wifi_ap_password, json["config"]["wifi_ap_password"].as(), sizeof(LubeConfig.wifi_ap_password)); - strncpy(LubeConfig.wifi_client_ssid, json["config"]["wifi_client_ssid"].as(), sizeof(LubeConfig.wifi_client_ssid)); - strncpy(LubeConfig.wifi_client_password, json["config"]["wifi_client_password"].as(), sizeof(LubeConfig.wifi_client_password)); + // Enums nur nach Range-Check übernehmen + { + int v = json["config"]["SpeedSource"].as(); + if (v >= 0 && v < maxSpeedSrc) + LubeConfig.SpeedSource = (SpeedSource_t)v; + else + Debug_pushMessage("Restore: invalid SpeedSource=%d\n", v); + } + { + int v = json["config"]["GPSBaudRate"].as(); + if (v >= 0 && v < maxGPSBaud) + LubeConfig.GPSBaudRate = (GPSBaudRate_t)v; + else + Debug_pushMessage("Restore: invalid GPSBaudRate=%d\n", v); + } + { + int v = json["config"]["CANSource"].as(); + if (v >= 0 && v < maxCANSrc) + LubeConfig.CANSource = (CANSource_t)v; + else + Debug_pushMessage("Restore: invalid CANSource=%d\n", v); + } + + // Strings sicher kopieren (0-terminiert) + safe_copy(LubeConfig.wifi_ap_ssid, sizeof(LubeConfig.wifi_ap_ssid), json["config"]["wifi_ap_ssid"]); + safe_copy(LubeConfig.wifi_ap_password, sizeof(LubeConfig.wifi_ap_password), json["config"]["wifi_ap_password"]); + safe_copy(LubeConfig.wifi_client_ssid, sizeof(LubeConfig.wifi_client_ssid), json["config"]["wifi_client_ssid"]); + safe_copy(LubeConfig.wifi_client_password, sizeof(LubeConfig.wifi_client_password), json["config"]["wifi_client_password"]); + + // persis.* PersistenceData.writeCycleCounter = json["persis"]["writeCycleCounter"].as(); PersistenceData.tankRemain_microL = json["persis"]["tankRemain_microL"].as(); PersistenceData.TravelDistance_highRes_mm = json["persis"]["TravelDistance_highRes_mm"].as(); @@ -427,24 +483,33 @@ void WebserverEERestore_Callback(AsyncWebServerRequest *request, const String &f PersistenceData.odometer = json["persis"]["odometer"].as(); PersistenceData.checksum = json["persis"]["checksum"].as(); + // Optional: Sanity-Autokorrektur im RAM (keine EEPROM-Writes hier!) + { + uint32_t sanity = ConfigSanityCheck(true); + if (sanity > 0) + { + MaintainDTC(DTC_EEPROM_CFG_SANITY, true, sanity); + Debug_pushMessage("Restore: ConfigSanity corrected (mask=0x%08lX)\n", sanity); + } + } + ee_done = true; } - } - if (buffer) - { free(buffer); - buffer = NULL; + buffer = nullptr; } - AsyncWebServerResponse *response = request->beginResponse(302, "text/plain", "Please wait while the device reboots"); + // Browser zurückleiten & ggf. Shutdown + 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) { - Debug_pushMessage("Update complete\n"); + Debug_pushMessage("EEPROM restore complete\n"); globals.systemStatus = sysStat_Shutdown; } } @@ -648,24 +713,24 @@ void Websocket_HandleSettings(uint8_t *data) } else if (strcmp(identifier, "speedsource") == 0) { - int index = findIndexByString(value, SpeedSourceString, (int)SpeedSourceString_Elements); - if (validIndex(index, (int)SpeedSourceString_Elements)) + int index = findIndexByString(value, SpeedSourceString, (int)SPEEDSOURCE_COUNT); + if (validIndex(index, (int)SPEEDSOURCE_COUNT)) speedsourcePreselect = (SpeedSource_t)index; else Debug_pushMessage("Invalid speedsource '%s'\n", value); } else if (strcmp(identifier, "cansource") == 0) { - int index = findIndexByString(value, CANSourceString, (int)CANSourceString_Elements); - if (validIndex(index, (int)CANSourceString_Elements)) + int index = findIndexByString(value, CANSourceString, (int)CANSOURCE_COUNT); + if (validIndex(index, (int)CANSOURCE_COUNT)) LubeConfig.CANSource = (CANSource_t)index; else Debug_pushMessage("Invalid cansource '%s'\n", value); } else if (strcmp(identifier, "gpsbaud") == 0) { - int index = findIndexByString(value, GPSBaudRateString, (int)GPSBaudRateString_Elements); - if (validIndex(index, (int)GPSBaudRateString_Elements)) + int index = findIndexByString(value, GPSBaudRateString, (int)GPSBAUDRATE_COUNT); + if (validIndex(index, (int)GPSBAUDRATE_COUNT)) LubeConfig.GPSBaudRate = (GPSBaudRate_t)index; else Debug_pushMessage("Invalid gpsbaud '%s'\n", value); @@ -801,7 +866,7 @@ void Websocket_RefreshClientData_Status(uint32_t client_id, bool send_mapping) String temp = "STATUS:"; - temp.concat(String(nz(globals.systemStatustxt)) + ";"); + temp.concat(String(ToString(globals.systemStatus)) + ";"); // Guard against division by zero (capacity==0) uint32_t cap = LubeConfig.tankCapacity_ml; @@ -856,26 +921,26 @@ void Websocket_RefreshClientData_Static(uint32_t client_id, bool send_mapping) temp += String(LubeConfig.RimDiameter_Inch) + ";"; // speedsource + Optionen - temp += tableStr(SpeedSourceString, (int)LubeConfig.SpeedSource, (int)SpeedSourceString_Elements) + ";"; + temp += String(ToString(LubeConfig.SpeedSource)) + ";"; { String csv; - appendCsv(csv, SpeedSourceString, SpeedSourceString_Elements); + appendCsv(csv, SpeedSourceString, SPEEDSOURCE_COUNT); temp += csv + ";"; } // gpsbaud + Optionen - temp += tableStr(GPSBaudRateString, (int)LubeConfig.GPSBaudRate, (int)GPSBaudRateString_Elements) + ";"; + temp += String(ToString(LubeConfig.GPSBaudRate)) + ";"; { String csv; - appendCsv(csv, GPSBaudRateString, GPSBaudRateString_Elements); + appendCsv(csv, GPSBaudRateString, GPSBAUDRATE_COUNT); temp += csv + ";"; } // cansource + Optionen - temp += tableStr(CANSourceString, (int)LubeConfig.CANSource, (int)CANSourceString_Elements) + ";"; + temp += String(ToString(LubeConfig.CANSource)) + ";"; { String csv; - appendCsv(csv, CANSourceString, CANSourceString_Elements); + appendCsv(csv, CANSourceString, CANSOURCE_COUNT); temp += csv + ";"; }