reworked String Handling of Enums

This commit is contained in:
2025-08-24 14:10:27 +02:00
parent f735ea7b0d
commit 9cb3a61184
8 changed files with 214 additions and 104 deletions

View File

@@ -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

View File

@@ -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 */

View File

@@ -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]);
// ---- 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<int>(v);
return in_range(i, static_cast<int>(SYSSTAT_COUNT))
? SystemStatusString[i]
: kUnknownStr;
}
const char *ToString(SpeedSource_t v)
{
const int i = static_cast<int>(v);
return in_range(i, static_cast<int>(SPEEDSOURCE_COUNT))
? SpeedSourceString[i]
: kUnknownStr;
}
const char *ToString(GPSBaudRate_t v)
{
const int i = static_cast<int>(v);
return in_range(i, static_cast<int>(GPSBAUDRATE_COUNT))
? GPSBaudRateString[i]
: kUnknownStr;
}
const char *ToString(CANSource_t v)
{
const int i = static_cast<int>(v);
return in_range(i, static_cast<int>(CANSOURCE_COUNT))
? CANSourceString[i]
: kUnknownStr;
}

View File

@@ -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)

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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());
}

View File

@@ -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<int>(SPEEDSOURCE_COUNT);
const int maxGPSBaud = static_cast<int>(GPSBAUDRATE_COUNT);
const int maxCANSrc = static_cast<int>(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<uint32_t>();
LubeConfig.DistancePerLube_Rain = json["config"]["DistancePerLube_Rain"].as<uint32_t>();
LubeConfig.tankCapacity_ml = json["config"]["tankCapacity_ml"].as<uint32_t>();
LubeConfig.amountPerDose_microL = json["config"]["amountPerDose_microL"].as<uint32_t>();
LubeConfig.TankRemindAtPercentage = json["config"]["TankRemindAtPercentage"].as<uint8_t>();
LubeConfig.PulsePerRevolution = json["config"]["PulsePerRevolution"].as<uint8_t>();
LubeConfig.TireWidth_mm = json["config"]["TireWidth_mm"].as<uint32_t>();
LubeConfig.TireWidthHeight_Ratio = json["config"]["TireWidthHeight_Ratio"].as<uint32_t>();
LubeConfig.RimDiameter_Inch = json["config"]["RimDiameter_Inch"].as<uint32_t>();
LubeConfig.DistancePerRevolution_mm = json["config"]["DistancePerRevolution_mm"].as<uint32_t>();
LubeConfig.BleedingPulses = json["config"]["BleedingPulses"].as<uint16_t>();
LubeConfig.SpeedSource = (SpeedSource_t)json["config"]["SpeedSource"].as<int>();
LubeConfig.GPSBaudRate = (GPSBaudRate_t)json["config"]["GPSBaudRate"].as<int>();
LubeConfig.CANSource = (CANSource_t)json["config"]["CANSource"].as<int>();
// config.*
LubeConfig.DistancePerLube_Default = clamp_u32(json["config"]["DistancePerLube_Default"].as<uint32_t>(), 0, 50000);
LubeConfig.DistancePerLube_Rain = clamp_u32(json["config"]["DistancePerLube_Rain"].as<uint32_t>(), 0, 50000);
LubeConfig.tankCapacity_ml = clamp_u32(json["config"]["tankCapacity_ml"].as<uint32_t>(), 0, 5000);
LubeConfig.amountPerDose_microL = clamp_u32(json["config"]["amountPerDose_microL"].as<uint32_t>(), 0, 100);
LubeConfig.TankRemindAtPercentage = clamp_u8(json["config"]["TankRemindAtPercentage"].as<uint8_t>(), 0, 100);
LubeConfig.PulsePerRevolution = clamp_u8(json["config"]["PulsePerRevolution"].as<uint8_t>(), 0, 255);
LubeConfig.TireWidth_mm = clamp_u32(json["config"]["TireWidth_mm"].as<uint32_t>(), 0, 500);
LubeConfig.TireWidthHeight_Ratio = clamp_u32(json["config"]["TireWidthHeight_Ratio"].as<uint32_t>(), 0, 150);
LubeConfig.RimDiameter_Inch = clamp_u32(json["config"]["RimDiameter_Inch"].as<uint32_t>(), 0, 30);
LubeConfig.DistancePerRevolution_mm = clamp_u32(json["config"]["DistancePerRevolution_mm"].as<uint32_t>(), 0, 10000);
LubeConfig.BleedingPulses = clamp_u16(json["config"]["BleedingPulses"].as<uint16_t>(), 0, 1000);
LubeConfig.WashMode_Distance = json["config"]["WashMode_Distance"].as<uint16_t>(); // ggf. Grenzen anpassen
LubeConfig.WashMode_Interval = json["config"]["WashMode_Interval"].as<uint16_t>(); // ggf. Grenzen anpassen
LubeConfig.LED_Mode_Flash = json["config"]["LED_Mode_Flash"].as<bool>();
LubeConfig.LED_Max_Brightness = json["config"]["LED_Max_Brightness"].as<uint8_t>();
LubeConfig.LED_Min_Brightness = json["config"]["LED_Min_Brightness"].as<uint8_t>();
strncpy(LubeConfig.wifi_ap_ssid, json["config"]["wifi_ap_ssid"].as<const char *>(), sizeof(LubeConfig.wifi_ap_ssid));
strncpy(LubeConfig.wifi_ap_password, json["config"]["wifi_ap_password"].as<const char *>(), sizeof(LubeConfig.wifi_ap_password));
strncpy(LubeConfig.wifi_client_ssid, json["config"]["wifi_client_ssid"].as<const char *>(), sizeof(LubeConfig.wifi_client_ssid));
strncpy(LubeConfig.wifi_client_password, json["config"]["wifi_client_password"].as<const char *>(), sizeof(LubeConfig.wifi_client_password));
// Enums nur nach Range-Check übernehmen
{
int v = json["config"]["SpeedSource"].as<int>();
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<int>();
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<int>();
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<uint16_t>();
PersistenceData.tankRemain_microL = json["persis"]["tankRemain_microL"].as<uint32_t>();
PersistenceData.TravelDistance_highRes_mm = json["persis"]["TravelDistance_highRes_mm"].as<uint32_t>();
@@ -427,24 +483,33 @@ void WebserverEERestore_Callback(AsyncWebServerRequest *request, const String &f
PersistenceData.odometer = json["persis"]["odometer"].as<uint32_t>();
PersistenceData.checksum = json["persis"]["checksum"].as<uint32_t>();
// 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 + ";";
}