reworked String Handling of Enums
This commit is contained in:
@@ -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
|
||||
|
@@ -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 */
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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)
|
||||
|
@@ -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);
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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());
|
||||
}
|
||||
|
||||
|
@@ -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 + ";";
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user