|
|
|
@@ -12,22 +12,15 @@
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include "debugger.h"
|
|
|
|
|
#include <map>
|
|
|
|
|
#include <functional>
|
|
|
|
|
#include <vector>
|
|
|
|
|
#include "utilities.h"
|
|
|
|
|
#include <pgmspace.h>
|
|
|
|
|
|
|
|
|
|
DebugStatus_t DebuggerStatus[dbg_cntElements];
|
|
|
|
|
|
|
|
|
|
// Funktionszeiger
|
|
|
|
|
typedef void (*CommandFunction)();
|
|
|
|
|
|
|
|
|
|
// Struktur zur Zuordnung von Commands zu Funktionen
|
|
|
|
|
struct CommandMapping
|
|
|
|
|
{
|
|
|
|
|
const char *command;
|
|
|
|
|
CommandFunction function;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
void processCmdDebug(const char *command);
|
|
|
|
|
void processCmdDebug(String command);
|
|
|
|
|
void Debug_formatCFG();
|
|
|
|
|
void Debug_formatPersistence();
|
|
|
|
|
void Debug_printSystemInfo();
|
|
|
|
@@ -39,93 +32,9 @@ void Debug_ShowDTCs();
|
|
|
|
|
void Debug_dumpGlobals();
|
|
|
|
|
void Debug_printHelp();
|
|
|
|
|
void Debug_Reboot();
|
|
|
|
|
void Debug_setBatteryType(int batterytype);
|
|
|
|
|
const char *uint32_to_binary_string(uint32_t num);
|
|
|
|
|
|
|
|
|
|
// Adapter-Functions for Debug-Commands
|
|
|
|
|
void adapterCheckEEPOM() { Debug_CheckEEPOM(false); }
|
|
|
|
|
void adapterCheckEEPOMFix() { Debug_CheckEEPOM(true); }
|
|
|
|
|
void adapterDumpEEPROM1k() { dumpEEPROM(0, 1024); }
|
|
|
|
|
void adapterDumpEEPROMAll() { dumpEEPROM(0, EEPROM_SIZE_BYTES); }
|
|
|
|
|
void adapterKillEEPROM() { writeSequentialToEEPROM(0, 1024); }
|
|
|
|
|
void adapterZeroEEPROM() { writeZeroToEEPROM(0, 1024); }
|
|
|
|
|
void adapterResetPageEEPROM() { MovePersistencePage_EEPROM(true); }
|
|
|
|
|
void adapterSaveEEPROM() { globals.requestEEAction = EE_ALL_SAVE; }
|
|
|
|
|
void adapterSetDebugPort() { SetDebugportStatus(dbg_Serial, enabled); }
|
|
|
|
|
void adapterCritDTC() { MaintainDTC(DTC_FAKE_DTC_CRIT, true, millis()); }
|
|
|
|
|
void adapterWarnDTC() { MaintainDTC(DTC_FAKE_DTC_WARN, true, millis()); }
|
|
|
|
|
void adapterInfoDTC() { MaintainDTC(DTC_FAKE_DTC_INFO, true, millis()); }
|
|
|
|
|
void adapterNotifyError() { Websocket_PushNotification("Debug Error Notification", error); }
|
|
|
|
|
void adapterNotifyWarning() { Websocket_PushNotification("Debug Warning Notification", warning); }
|
|
|
|
|
void adapterNotifySuccess() { Websocket_PushNotification("Debug Success Notification", success); }
|
|
|
|
|
void adapterNotifyInfo() { Websocket_PushNotification("Debug Info Notification", info); }
|
|
|
|
|
|
|
|
|
|
// Definition der Command-Mapping-Tabelle
|
|
|
|
|
const CommandMapping commandMappings[] = {
|
|
|
|
|
{"help", Debug_printHelp},
|
|
|
|
|
{"reboot", Debug_Reboot},
|
|
|
|
|
{"sysinfo", Debug_printSystemInfo},
|
|
|
|
|
{"netinfo", Debug_printWifiInfo},
|
|
|
|
|
{"formatCFG", Debug_formatCFG},
|
|
|
|
|
{"formatPDS", Debug_formatPersistence},
|
|
|
|
|
{"checkEE", adapterCheckEEPOM},
|
|
|
|
|
{"checkEEfix", adapterCheckEEPOMFix},
|
|
|
|
|
{"dumpEE1k", adapterDumpEEPROM1k},
|
|
|
|
|
{"dumpEE", adapterDumpEEPROMAll},
|
|
|
|
|
{"killEE", adapterKillEEPROM},
|
|
|
|
|
{"zeroEE", adapterZeroEEPROM},
|
|
|
|
|
{"resetPageEE", adapterResetPageEEPROM},
|
|
|
|
|
{"dumpCFG", Debug_dumpConfig},
|
|
|
|
|
{"dumpPDS", Debug_dumpPersistance},
|
|
|
|
|
{"saveEE", adapterSaveEEPROM},
|
|
|
|
|
{"dumpGlobals", Debug_dumpGlobals},
|
|
|
|
|
{"sdbg", adapterSetDebugPort},
|
|
|
|
|
{"dtc_show", Debug_ShowDTCs},
|
|
|
|
|
{"dtc_clear", ClearAllDTC},
|
|
|
|
|
{"dtc_crit", adapterCritDTC},
|
|
|
|
|
{"dtc_warn", adapterWarnDTC},
|
|
|
|
|
{"dtc_info", adapterInfoDTC},
|
|
|
|
|
{"notify_error", adapterNotifyError},
|
|
|
|
|
{"notify_warning", adapterNotifyWarning},
|
|
|
|
|
{"notify_success", adapterNotifySuccess},
|
|
|
|
|
{"notify_info", adapterNotifyInfo},
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const size_t NUM_COMMANDS = sizeof(commandMappings) / sizeof(commandMappings[0]);
|
|
|
|
|
|
|
|
|
|
const char helpText[][64] PROGMEM = {
|
|
|
|
|
"help - Print this help text",
|
|
|
|
|
"sysinfo - System Info",
|
|
|
|
|
"reboot - System Reboot",
|
|
|
|
|
"netinfo - WiFi Info",
|
|
|
|
|
"formatPDS - Format Persistence EEPROM Data",
|
|
|
|
|
"formatCFG - Format Configuration EEPROM Data",
|
|
|
|
|
"checkEE - Check EEPROM with checksum",
|
|
|
|
|
"checkEEfix - Check and fix EEPROM with checksum",
|
|
|
|
|
"dumpEE1k - Dump the first 1kb of EEPROM to Serial",
|
|
|
|
|
"dumpEE - Dump the whole EEPROM to Serial",
|
|
|
|
|
"killEE - Kill the first 1024 bytes of EEPROM",
|
|
|
|
|
"zeroEE - Zero the first 1024 bytes of EEPROM",
|
|
|
|
|
"resetPageEE - Reset the PersistenceData Page",
|
|
|
|
|
"dumpCFG - Print Config struct",
|
|
|
|
|
"dumpPDS - Print PersistenceStruct",
|
|
|
|
|
"saveEE - Save EE-Data",
|
|
|
|
|
"dumpGlobals - Print globals",
|
|
|
|
|
"sdbg - Set debug port status",
|
|
|
|
|
"dtc_show - Show all DTCs",
|
|
|
|
|
"dtc_clear - Clear all DTCs",
|
|
|
|
|
"dtc_crit - Maintain critical DTC",
|
|
|
|
|
"dtc_warn - Maintain warning DTC",
|
|
|
|
|
"dtc_info - Maintain info DTC",
|
|
|
|
|
"notify_error - Send error notification",
|
|
|
|
|
"notify_warning - Send warning notification",
|
|
|
|
|
"notify_success - Send success notification",
|
|
|
|
|
"notify_info - Send info notification"};
|
|
|
|
|
|
|
|
|
|
const size_t NUM_HELP_LINES = sizeof(helpText) / sizeof(helpText[0]);
|
|
|
|
|
|
|
|
|
|
// Überprüfen, ob die Anzahl der Commands und Hilfetext-Zeilen übereinstimmen
|
|
|
|
|
static_assert(NUM_COMMANDS == NUM_HELP_LINES, "Number of commands and help text lines do not match!");
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Initializes the debugger by setting the initial status for different debug ports.
|
|
|
|
|
* Serial debug output is turned off.
|
|
|
|
@@ -180,7 +89,7 @@ void Debug_Process()
|
|
|
|
|
InputProcessed = CMD_ABORT;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 0x21 ... 0x7E: // it's a real letter or sign and not some control-chars
|
|
|
|
|
case 0x20 ... 0x7E: // it's a real letter or sign and not some control-chars
|
|
|
|
|
inputBuffer[inputCnt] = inputChar;
|
|
|
|
|
inputCnt++;
|
|
|
|
|
Serial.write(inputChar);
|
|
|
|
@@ -191,10 +100,10 @@ void Debug_Process()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Check for input buffer overflow
|
|
|
|
|
if (inputCnt > sizeof(inputBuffer))
|
|
|
|
|
if (inputCnt >= sizeof(inputBuffer) - 1)
|
|
|
|
|
{
|
|
|
|
|
inputBuffer[sizeof(inputBuffer) - 1] = '\0';
|
|
|
|
|
inputCnt = 0;
|
|
|
|
|
inputBuffer[sizeof(inputBuffer) - 1] = 0; // terminate the String
|
|
|
|
|
InputProcessed = CMD_OVERFLOW;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@@ -207,7 +116,7 @@ void Debug_Process()
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case CMD_COMPLETE:
|
|
|
|
|
processCmdDebug(inputBuffer);
|
|
|
|
|
processCmdDebug(String(inputBuffer));
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case CMD_OVERFLOW:
|
|
|
|
@@ -244,6 +153,27 @@ void SetDebugportStatus(DebugPorts_t port, DebugStatus_t status)
|
|
|
|
|
Debug_pushMessage("Enabled DebugPort %s\n", sDebugPorts[port]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Debug_log(LogLevel level, const char *format, ...)
|
|
|
|
|
{
|
|
|
|
|
if ((DebuggerStatus[dbg_Serial] == enabled) || (DebuggerStatus[dbg_Webui] == enabled))
|
|
|
|
|
{
|
|
|
|
|
char buff[128];
|
|
|
|
|
va_list arg;
|
|
|
|
|
va_start(arg, format);
|
|
|
|
|
vsnprintf(buff, sizeof(buff), format, arg);
|
|
|
|
|
va_end(arg);
|
|
|
|
|
|
|
|
|
|
if (DebuggerStatus[dbg_Serial] == enabled)
|
|
|
|
|
{
|
|
|
|
|
Serial.print(buff);
|
|
|
|
|
}
|
|
|
|
|
if (DebuggerStatus[dbg_Webui] == enabled)
|
|
|
|
|
{
|
|
|
|
|
Websocket_PushLiveDebug(String(buff));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Pushes a formatted debug message to the enabled debug ports (Serial or WebUI).
|
|
|
|
|
*
|
|
|
|
@@ -277,27 +207,134 @@ void Debug_pushMessage(const char *format, ...)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Processes a debug command and performs corresponding actions.
|
|
|
|
|
*
|
|
|
|
|
* @param command The debug command to be processed.
|
|
|
|
|
*/
|
|
|
|
|
void processCmdDebug(const char *command)
|
|
|
|
|
// === splitArgs Helper ===
|
|
|
|
|
std::vector<String> splitArgs(const String &input)
|
|
|
|
|
{
|
|
|
|
|
bool commandFound = false;
|
|
|
|
|
for (size_t i = 0; i < NUM_COMMANDS; ++i)
|
|
|
|
|
std::vector<String> tokens;
|
|
|
|
|
int start = 0, end = 0;
|
|
|
|
|
while ((end = input.indexOf(' ', start)) != -1)
|
|
|
|
|
{
|
|
|
|
|
if (strcmp(command, commandMappings[i].command) == 0)
|
|
|
|
|
{
|
|
|
|
|
commandMappings[i].function();
|
|
|
|
|
commandFound = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (!commandFound)
|
|
|
|
|
{
|
|
|
|
|
Debug_pushMessage("unknown Command\n");
|
|
|
|
|
tokens.push_back(input.substring(start, end));
|
|
|
|
|
start = end + 1;
|
|
|
|
|
}
|
|
|
|
|
if (start < input.length())
|
|
|
|
|
tokens.push_back(input.substring(start));
|
|
|
|
|
return tokens;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// === getArg helper ===
|
|
|
|
|
String getArg(const std::vector<String> &args, size_t index, const String &defaultVal = "")
|
|
|
|
|
{
|
|
|
|
|
if (index < args.size())
|
|
|
|
|
return args[index];
|
|
|
|
|
return defaultVal;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// === Command Handler Map ===
|
|
|
|
|
typedef std::function<void(const String &args)> DebugCmdHandler;
|
|
|
|
|
|
|
|
|
|
static const std::map<String, DebugCmdHandler> &getCmdMap()
|
|
|
|
|
{
|
|
|
|
|
static const std::map<String, DebugCmdHandler> cmdMap = {
|
|
|
|
|
{"help", [](const String &)
|
|
|
|
|
{
|
|
|
|
|
Debug_log(LOG_INFO, "Available commands:\n");
|
|
|
|
|
for (const auto &entry : getCmdMap())
|
|
|
|
|
Debug_log(LOG_INFO, " - %s\n", entry.first.c_str());
|
|
|
|
|
}},
|
|
|
|
|
{"sysinfo", [](const String &)
|
|
|
|
|
{ Debug_printSystemInfo(); }},
|
|
|
|
|
{"netinfo", [](const String &)
|
|
|
|
|
{ Debug_printWifiInfo(); }},
|
|
|
|
|
{"formatCFG", [](const String &)
|
|
|
|
|
{ Debug_formatCFG(); }},
|
|
|
|
|
{"formatPDS", [](const String &)
|
|
|
|
|
{ Debug_formatPersistence(); }},
|
|
|
|
|
{"checkEE", [](const String &)
|
|
|
|
|
{ Debug_CheckEEPOM(false); }},
|
|
|
|
|
{"checkEEfix", [](const String &)
|
|
|
|
|
{ Debug_CheckEEPOM(true); }},
|
|
|
|
|
{"dumpEE1k", [](const String &)
|
|
|
|
|
{ dumpEEPROM(0, 1024); }},
|
|
|
|
|
{"dumpEE", [](const String &args)
|
|
|
|
|
{
|
|
|
|
|
int start = 0, len = EEPROM_SIZE_BYTES;
|
|
|
|
|
auto tokens = splitArgs(args);
|
|
|
|
|
if (tokens.size() >= 2)
|
|
|
|
|
{
|
|
|
|
|
start = tokens[0].toInt();
|
|
|
|
|
len = tokens[1].toInt();
|
|
|
|
|
}
|
|
|
|
|
dumpEEPROM(start, len);
|
|
|
|
|
}},
|
|
|
|
|
{"resetPageEE", [](const String &)
|
|
|
|
|
{ MovePersistencePage_EEPROM(true); }},
|
|
|
|
|
{"dumpCFG", [](const String &)
|
|
|
|
|
{ Debug_dumpConfig(); }},
|
|
|
|
|
{"dumpPDS", [](const String &)
|
|
|
|
|
{ Debug_dumpPersistance(); }},
|
|
|
|
|
{"saveEE", [](const String &)
|
|
|
|
|
{ globals.requestEEAction = EE_ALL_SAVE; }},
|
|
|
|
|
{"dumpGlobals", [](const String &)
|
|
|
|
|
{ Debug_dumpGlobals(); }},
|
|
|
|
|
{"sdbg", [](const String &)
|
|
|
|
|
{ SetDebugportStatus(dbg_Serial, enabled); }},
|
|
|
|
|
{"dtc_show", [](const String &)
|
|
|
|
|
{ Debug_ShowDTCs(); }},
|
|
|
|
|
{"dtc_clear", [](const String &)
|
|
|
|
|
{ ClearAllDTC(); }},
|
|
|
|
|
{"dtc_crit", [](const String &)
|
|
|
|
|
{ MaintainDTC(DTC_FAKE_DTC_CRIT, true, millis()); }},
|
|
|
|
|
{"dtc_warn", [](const String &)
|
|
|
|
|
{ MaintainDTC(DTC_FAKE_DTC_WARN, true, millis()); }},
|
|
|
|
|
{"dtc_info", [](const String &)
|
|
|
|
|
{ MaintainDTC(DTC_FAKE_DTC_INFO, true, millis()); }},
|
|
|
|
|
{"notify_error", [](const String &)
|
|
|
|
|
{ Websocket_PushNotification("Debug Error Notification", error); }},
|
|
|
|
|
{"notify_warning", [](const String &)
|
|
|
|
|
{ Websocket_PushNotification("Debug Warning Notification", warning); }},
|
|
|
|
|
{"notify_success", [](const String &)
|
|
|
|
|
{ Websocket_PushNotification("Debug Success Notification", success); }},
|
|
|
|
|
{"notify_info", [](const String &)
|
|
|
|
|
{ Websocket_PushNotification("Debug Info Notification", info); }},
|
|
|
|
|
{"reboot", [](const String &)
|
|
|
|
|
{ Debug_Reboot(); }},
|
|
|
|
|
{"toggle_wifi", [](const String &)
|
|
|
|
|
{ globals.toggle_wifi = true; }},
|
|
|
|
|
{"dtc_add", [](const String &args)
|
|
|
|
|
{
|
|
|
|
|
auto tokens = splitArgs(args);
|
|
|
|
|
if (!tokens.empty())
|
|
|
|
|
{
|
|
|
|
|
int code = tokens[0].toInt();
|
|
|
|
|
MaintainDTC((DTCNum_t)code, true, millis());
|
|
|
|
|
}
|
|
|
|
|
}},
|
|
|
|
|
{"set_battery", [](const String &args)
|
|
|
|
|
{
|
|
|
|
|
auto tokens = splitArgs(args);
|
|
|
|
|
if (!tokens.empty())
|
|
|
|
|
{
|
|
|
|
|
int batteryType = tokens[0].toInt();
|
|
|
|
|
Debug_setBatteryType(batteryType);
|
|
|
|
|
}
|
|
|
|
|
}}};
|
|
|
|
|
return cmdMap;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void processCmdDebug(String input)
|
|
|
|
|
{
|
|
|
|
|
input.trim();
|
|
|
|
|
int splitIndex = input.indexOf(' ');
|
|
|
|
|
String command = splitIndex == -1 ? input : input.substring(0, splitIndex);
|
|
|
|
|
String args = splitIndex == -1 ? "" : input.substring(splitIndex + 1);
|
|
|
|
|
|
|
|
|
|
auto &cmdMap = getCmdMap();
|
|
|
|
|
auto it = cmdMap.find(command);
|
|
|
|
|
if (it != cmdMap.end())
|
|
|
|
|
it->second(args);
|
|
|
|
|
else
|
|
|
|
|
Debug_log(LOG_WARN, "Unknown command: '%s'\n", command.c_str());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
@@ -409,11 +446,31 @@ void Debug_dumpPersistance()
|
|
|
|
|
void Debug_printWifiInfo()
|
|
|
|
|
{
|
|
|
|
|
char buffer[33];
|
|
|
|
|
GenerateDeviceSpecificPassword(QUOTE(WIFI_PASS_SEED), buffer, sizeof(buffer));
|
|
|
|
|
GenerateDeviceSpecificPassword(QUOTE(WIFI_PASS_SEED), buffer, sizeof(buffer));
|
|
|
|
|
Debug_pushMessage("IP Adress: %s\n", WiFi.localIP().toString().c_str());
|
|
|
|
|
Debug_pushMessage("WiFi AP Pw: %s\n", buffer);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Debug_setBatteryType(int batterytype)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
switch (batterytype)
|
|
|
|
|
{
|
|
|
|
|
case 2:
|
|
|
|
|
ConfigData.batteryType = BATTERY_LIPO_2S;
|
|
|
|
|
break;
|
|
|
|
|
case 3:
|
|
|
|
|
ConfigData.batteryType = BATTERY_LIPO_3S;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
ConfigData.batteryType = BATTERY_UNDEFINED;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Debug_pushMessage("Set BatteryType to : %d\n", batterytype);
|
|
|
|
|
globals.requestEEAction = EE_CFG_SAVE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Checks the EEPROM data integrity by calculating and comparing checksums.
|
|
|
|
|
* Prints the result to the debug output.
|
|
|
|
@@ -471,7 +528,7 @@ void Debug_ShowDTCs()
|
|
|
|
|
char buff_active[9];
|
|
|
|
|
|
|
|
|
|
// Header for the DTC display
|
|
|
|
|
Debug_pushMessage("\n timestamp | DTC-Nr. | status | debugval\n");
|
|
|
|
|
Debug_pushMessage("\n timestamp | DTC-Nr. | status | severity\n");
|
|
|
|
|
|
|
|
|
|
// Iterate through DTCStorage and display each entry
|
|
|
|
|
for (uint32_t i = 0; i < MAX_DTC_STORAGE; i++)
|
|
|
|
@@ -495,25 +552,11 @@ void Debug_ShowDTCs()
|
|
|
|
|
strcpy(buff_active, "none");
|
|
|
|
|
|
|
|
|
|
// Display DTC information
|
|
|
|
|
Debug_pushMessage("%s %7d %8s %8d\n", buff_timestamp, DTCStorage[i].Number, buff_active, DTCStorage[i].debugVal);
|
|
|
|
|
Debug_pushMessage("%s %7d %8s %8d\n", buff_timestamp, DTCStorage[i].Number, buff_active);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Prints the help information stored in PROGMEM.
|
|
|
|
|
*/
|
|
|
|
|
void Debug_printHelp()
|
|
|
|
|
{
|
|
|
|
|
char buffer[64];
|
|
|
|
|
for (size_t i = 0; i < NUM_HELP_LINES; ++i)
|
|
|
|
|
{
|
|
|
|
|
strncpy_P(buffer, helpText[i], sizeof(buffer));
|
|
|
|
|
buffer[sizeof(buffer) - 1] = '\0'; // Sicherstellen, dass der String nullterminiert ist
|
|
|
|
|
Serial.println(buffer);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Initiates a system reboot by setting the system status to shutdown.
|
|
|
|
|
*
|
|
|
|
|