Compare commits

...

4 Commits

8 changed files with 184 additions and 91 deletions

View File

@ -102,7 +102,6 @@ uint32_t Checksum_EEPROM(uint8_t const *data, size_t len);
void dumpEEPROM(uint16_t memoryAddress, uint16_t length); void dumpEEPROM(uint16_t memoryAddress, uint16_t length);
void MovePersistencePage_EEPROM(boolean reset); void MovePersistencePage_EEPROM(boolean reset);
uint32_t ConfigSanityCheck(bool autocorrect = false); uint32_t ConfigSanityCheck(bool autocorrect = false);
bool validateWiFiString(char *string, size_t size);
void writeSequentialToEEPROM(uint16_t memoryAddress, uint16_t length); void writeSequentialToEEPROM(uint16_t memoryAddress, uint16_t length);
void writeZeroToEEPROM(uint16_t memoryAddress, uint16_t length); void writeZeroToEEPROM(uint16_t memoryAddress, uint16_t length);

View File

@ -10,7 +10,7 @@ typedef struct Globals_s
tSystem_Status resumeStatus = sysStat_Startup; /**< Status to resume after rain mode */ tSystem_Status resumeStatus = sysStat_Startup; /**< Status to resume after rain mode */
char systemStatustxt[16] = ""; /**< Text representation of system status */ char systemStatustxt[16] = ""; /**< Text representation of system status */
EERequest_t requestEEAction = EE_IDLE; /**< EEPROM-related request */ EERequest_t requestEEAction = EE_IDLE; /**< EEPROM-related request */
char DeviceName[33]; /**< Device name */ char DeviceName[25]; /**< Device name */
char DeviceNameId[sizeof(DeviceName) + 8]; /**< Device name plus 8 chars chipID */ char DeviceNameId[sizeof(DeviceName) + 8]; /**< Device name plus 8 chars chipID */
char FlashVersion[10]; /**< Flash version */ char FlashVersion[10]; /**< Flash version */
uint16_t eePersistanceAdress; /**< EEPROM persistence address */ uint16_t eePersistanceAdress; /**< EEPROM persistence address */

View File

@ -0,0 +1,36 @@
#ifndef UTILITIES_H
#define UTILITIES_H
#include <Arduino.h>
/**
* @brief Validates whether a given string contains only characters allowed in WiFi SSIDs and passwords.
*
* This function checks each character in the provided string to ensure
* that it contains only characters allowed in WiFi SSIDs and passwords.
* It considers characters from 'A' to 'Z', 'a' to 'z', '0' to '9', as well as
* the following special characters: ! " # $ % & ' ( ) * + , - . / : ; < = > ? @ [ \ ] ^ _ ` { | } ~
*
* @param string Pointer to the string to be validated.
* @param size Size of the string including the null-terminator.
* @return true if the string contains only allowed characters or is NULL,
* false otherwise.
*/
bool validateWiFiString(char *string, size_t size);
/**
* @brief Copies a string to a buffer, replacing invalid WiFi SSID characters with a placeholder.
*
* This function checks each character in the provided input string to ensure
* that it contains only characters allowed in WiFi SSIDs and passwords. If a character
* is invalid, it replaces it with a placeholder character (e.g., '_').
* It considers characters from 'A' to 'Z', 'a' to 'z', '0' to '9', as well as
* the following special characters: ! " # $ % & ' ( ) * + , - . / : ; < = > ? @ [ \ ] ^ _ ` { | } ~
*
* @param input Pointer to the input string to be validated and copied.
* @param buffer Pointer to the buffer where the output string will be copied.
* @param bufferSize Size of the buffer including the null-terminator.
*/
void sanitizeWiFiString(const char *input, char *buffer, size_t bufferSize);
#endif // UTILITIES_H

View File

@ -9,6 +9,7 @@
#include "eeprom.h" #include "eeprom.h"
#include "debugger.h" #include "debugger.h"
#include "globals.h" #include "globals.h"
#include "utilities.h"
// Instance of I2C_eeprom for EEPROM access // Instance of I2C_eeprom for EEPROM access
I2C_eeprom ee(I2C_EE_ADDRESS, EEPROM_SIZE_BYTES); I2C_eeprom ee(I2C_EE_ADDRESS, EEPROM_SIZE_BYTES);
@ -430,48 +431,6 @@ uint32_t ConfigSanityCheck(bool autocorrect)
return setting_reset_bits; return setting_reset_bits;
} }
/**
* @brief Validates whether a given string contains only characters allowed in WiFi SSIDs and passwords.
*
* This function checks each character in the provided string to ensure
* that it contains only characters allowed in WiFi SSIDs and passwords.
* It considers characters from 'A' to 'Z', 'a' to 'z', '0' to '9', as well as
* the following special characters: ! " # $ % & ' ( ) * + , - . / : ; < = > ? @ [ \ ] ^ _ ` { | } ~
*
* @param string Pointer to the string to be validated.
* @param size Size of the string including the null-terminator.
* @return true if the string contains only allowed characters or is NULL,
* false otherwise.
*/
bool validateWiFiString(char *string, size_t size)
{
if (string == NULL)
return false;
for (size_t i = 0; i < size; i++)
{
char c = string[i];
if (c == '\0')
{
// Reached the end of the string, all characters were valid WiFi characters.
return true;
}
if (!((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') ||
(c >= '0' && c <= '9') || c == '!' || c == '"' || c == '#' ||
c == '$' || c == '%' || c == '&' || c == '\'' || c == '(' ||
c == ')' || c == '*' || c == '+' || c == ',' || c == '-' ||
c == '.' || c == '/' || c == ':' || c == ';' || c == '<' ||
c == '=' || c == '>' || c == '?' || c == '@' || c == '[' ||
c == '\\' || c == ']' || c == '^' || c == '_' || c == '`' ||
c == '{' || c == '|' || c == '}' || c == '~'))
{
// Found a character that is not a valid WiFi character.
return false;
}
}
// If the loop completes without finding a null terminator, the string is invalid.
return false;
}
/** /**
* @brief Write sequential numbers to a portion of EEPROM. * @brief Write sequential numbers to a portion of EEPROM.

View File

@ -249,7 +249,7 @@ void printParameters(struct Configuration configuration)
void Parse_LoRa_UartCommand(char input[], int size) void Parse_LoRa_UartCommand(char input[], int size)
{ {
Debug_pushMessage("Start parsing, size: %d", size); Debug_pushMessage("Start parsing, size: %d\n", size);
char delimiter[] = ";"; char delimiter[] = ";";
char *ptr; char *ptr;
char command[8]; char command[8];
@ -278,7 +278,7 @@ void Parse_LoRa_UartCommand(char input[], int size)
} }
// Hier kannst du den Wert und das Kommando verarbeiten // Hier kannst du den Wert und das Kommando verarbeiten
Debug_pushMessage("Command: %s, Value: %s", command, value); Debug_pushMessage("Command: %s, Value: %s\n", command, value);
} }
Debug_pushMessage("Parsed LoRa UART Command: %s Value: %s\n", command, value); Debug_pushMessage("Parsed LoRa UART Command: %s Value: %s\n", command, value);
@ -286,12 +286,12 @@ void Parse_LoRa_UartCommand(char input[], int size)
if (!strcmp(command, "ENABLE")) if (!strcmp(command, "ENABLE"))
{ {
globals.timer_disabled = false; globals.timer_disabled = false;
Debug_pushMessage("Enabled by LoRa"); Debug_pushMessage("Enabled by LoRa\n");
} }
else if (!strcmp(command, "DISABLE")) else if (!strcmp(command, "DISABLE"))
{ {
globals.timer_disabled = true; globals.timer_disabled = true;
Debug_pushMessage("Disabled by LoRa"); Debug_pushMessage("Disabled by LoRa\n");
} }
else if (!strcmp(command, "RESET")) else if (!strcmp(command, "RESET"))
{ {
@ -299,7 +299,7 @@ void Parse_LoRa_UartCommand(char input[], int size)
PersistenceData.faction_1_timer = 0; PersistenceData.faction_1_timer = 0;
PersistenceData.faction_2_timer = 0; PersistenceData.faction_2_timer = 0;
PersistenceData.faction_3_timer = 0; PersistenceData.faction_3_timer = 0;
Debug_pushMessage("Reset by LoRa"); Debug_pushMessage("Reset by LoRa\n");
} }
else if (!strcmp(command, "TMRSTP")) else if (!strcmp(command, "TMRSTP"))
{ {

View File

@ -19,6 +19,7 @@
#include "globals.h" #include "globals.h"
#include "dtc.h" #include "dtc.h"
#include "debugger.h" #include "debugger.h"
#include "utilities.h"
#if defined(FEATURE_ENABLE_LORA) || defined(FEATURE_ENABLE_UARTLORA) #if defined(FEATURE_ENABLE_LORA) || defined(FEATURE_ENABLE_UARTLORA)
#include "lora_net.h" #include "lora_net.h"
#endif #endif
@ -420,7 +421,7 @@ void tmrCallback_InputGetter()
if (keysPressed > 1) if (keysPressed > 1)
{ {
Debug_pushMessage("ERROR: More than one Flag active - setting no Faction active"); Debug_pushMessage("ERROR: More than one Flag active - setting no Faction active\n");
PersistenceData.activeFaction = NONE; PersistenceData.activeFaction = NONE;
return; return;
} }
@ -429,7 +430,7 @@ void tmrCallback_InputGetter()
{ {
if (PersistenceData.activeFaction != FACTION_1) if (PersistenceData.activeFaction != FACTION_1)
{ {
Debug_pushMessage("Faction 1 captured !"); Debug_pushMessage("Faction 1 captured !\n");
globals.requestEEAction = EE_PDS_SAVE; globals.requestEEAction = EE_PDS_SAVE;
} }
PersistenceData.activeFaction = FACTION_1; PersistenceData.activeFaction = FACTION_1;
@ -439,7 +440,7 @@ void tmrCallback_InputGetter()
{ {
if (PersistenceData.activeFaction != FACTION_2) if (PersistenceData.activeFaction != FACTION_2)
{ {
Debug_pushMessage("Faction 2 captured !"); Debug_pushMessage("Faction 2 captured !\n");
globals.requestEEAction = EE_PDS_SAVE; globals.requestEEAction = EE_PDS_SAVE;
} }
PersistenceData.activeFaction = FACTION_2; PersistenceData.activeFaction = FACTION_2;
@ -449,7 +450,7 @@ void tmrCallback_InputGetter()
{ {
if (PersistenceData.activeFaction != FACTION_3) if (PersistenceData.activeFaction != FACTION_3)
{ {
Debug_pushMessage("Faction 3 captured !"); Debug_pushMessage("Faction 3 captured !\n");
globals.requestEEAction = EE_PDS_SAVE; globals.requestEEAction = EE_PDS_SAVE;
} }
PersistenceData.activeFaction = FACTION_3; PersistenceData.activeFaction = FACTION_3;
@ -571,6 +572,7 @@ void wifiMaintainConnectionTicker_callback()
*/ */
void toggleWiFiAP(bool shutdown) void toggleWiFiAP(bool shutdown)
{ {
char buffer[33];
// Check if WiFi is currently active // Check if WiFi is currently active
if (WiFi.getMode() != WIFI_OFF) if (WiFi.getMode() != WIFI_OFF)
{ {
@ -588,7 +590,8 @@ void toggleWiFiAP(bool shutdown)
// Start WiFi in Access Point (AP) mode // Start WiFi in Access Point (AP) mode
WiFi.mode(WIFI_AP); WiFi.mode(WIFI_AP);
WiFi.softAPConfig(IPAddress(WIFI_AP_IP_GW), IPAddress(WIFI_AP_IP_GW), IPAddress(255, 255, 255, 0)); WiFi.softAPConfig(IPAddress(WIFI_AP_IP_GW), IPAddress(WIFI_AP_IP_GW), IPAddress(255, 255, 255, 0));
WiFi.softAP(globals.DeviceNameId, QUOTE(WIFI_AP_PASSWORD)); sanitizeWiFiString(globals.DeviceNameId, buffer, sizeof(buffer));
WiFi.softAP(buffer, QUOTE(WIFI_AP_PASSWORD));
// Stop WiFi maintenance connection ticker if enabled and display debug messages // Stop WiFi maintenance connection ticker if enabled and display debug messages
#ifdef FEATURE_ENABLE_WIFI_CLIENT #ifdef FEATURE_ENABLE_WIFI_CLIENT
@ -701,7 +704,7 @@ void ProcessKeyCombos(bool *btnState)
if (keyCount_Fac2 == 2 && keyCount_Fac3 == 0) if (keyCount_Fac2 == 2 && keyCount_Fac3 == 0)
{ {
Debug_pushMessage("KeyCombo: WiFi AP ON"); Debug_pushMessage("KeyCombo: WiFi AP ON\n");
OverrideDisplay(5000, "NET ", " ", " "); OverrideDisplay(5000, "NET ", " ", " ");
toggleWiFiAP(false); toggleWiFiAP(false);
} }

View File

@ -0,0 +1,94 @@
#include "utilities.h"
/**
* @brief Validates whether a given string contains only characters allowed in WiFi SSIDs and passwords.
*
* This function checks each character in the provided string to ensure
* that it contains only characters allowed in WiFi SSIDs and passwords.
* It considers characters from 'A' to 'Z', 'a' to 'z', '0' to '9', as well as
* the following special characters: ! " # $ % & ' ( ) * + , - . / : ; < = > ? @ [ \ ] ^ _ ` { | } ~
*
* @param string Pointer to the string to be validated.
* @param size Size of the string including the null-terminator.
* @return true if the string contains only allowed characters or is NULL,
* false otherwise.
*/
bool validateWiFiString(char *string, size_t size)
{
if (string == NULL)
return false;
for (size_t i = 0; i < size; i++)
{
char c = string[i];
if (c == '\0')
{
// Reached the end of the string, all characters were valid WiFi characters.
return true;
}
if (!((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') ||
(c >= '0' && c <= '9') || c == '!' || c == '"' || c == '#' ||
c == '$' || c == '%' || c == '&' || c == '\'' || c == '(' ||
c == ')' || c == '*' || c == '+' || c == ',' || c == '-' ||
c == '.' || c == '/' || c == ':' || c == ';' || c == '<' ||
c == '=' || c == '>' || c == '?' || c == '@' || c == '[' ||
c == '\\' || c == ']' || c == '^' || c == '_' || c == '`' ||
c == '{' || c == '|' || c == '}' || c == '~'))
{
// Found a character that is not a valid WiFi character.
return false;
}
}
// If the loop completes without finding a null terminator, the string is invalid.
return false;
}
/**
* @brief Copies a string to a buffer, replacing invalid WiFi SSID characters with a placeholder.
*
* This function checks each character in the provided input string to ensure
* that it contains only characters allowed in WiFi SSIDs and passwords. If a character
* is invalid, it replaces it with a placeholder character (e.g., '_').
* It considers characters from 'A' to 'Z', 'a' to 'z', '0' to '9', as well as
* the following special characters: ! " # $ % & ' ( ) * + , - . / : ; < = > ? @ [ \ ] ^ _ ` { | } ~
*
* @param input Pointer to the input string to be validated and copied.
* @param buffer Pointer to the buffer where the output string will be copied.
* @param bufferSize Size of the buffer including the null-terminator.
*/
void sanitizeWiFiString(const char *input, char *buffer, size_t bufferSize)
{
if (input == NULL || buffer == NULL || bufferSize == 0)
return;
size_t i;
for (i = 0; i < bufferSize - 1; i++) // Leave space for null-terminator
{
char c = input[i];
if (c == '\0')
{
// Reached the end of the input string, terminate the buffer
buffer[i] = '\0';
return;
}
if (!((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') ||
(c >= '0' && c <= '9') || c == '!' || c == '"' || c == '#' ||
c == '$' || c == '%' || c == '&' || c == '\'' || c == '(' ||
c == ')' || c == '*' || c == '+' || c == ',' || c == '-' ||
c == '.' || c == '/' || c == ':' || c == ';' || c == '<' ||
c == '=' || c == '>' || c == '?' || c == '@' || c == '[' ||
c == '\\' || c == ']' || c == '^' || c == '_' || c == '`' ||
c == '{' || c == '|' || c == '}' || c == '~'))
{
// Replace invalid character with placeholder
buffer[i] = '_';
}
else
{
// Copy valid character to buffer
buffer[i] = c;
}
}
// Null-terminate the buffer
buffer[i] = '\0';
}

View File

@ -594,7 +594,6 @@ void Websocket_RefreshClientData_DTCs(uint32_t client_id)
*/ */
void Websocket_RefreshClientData_Status(uint32_t client_id, bool send_mapping) void Websocket_RefreshClientData_Status(uint32_t client_id, bool send_mapping)
{ {
if (send_mapping) if (send_mapping)
{ {
const char mapping[] = "MAPPING_STATUS:" const char mapping[] = "MAPPING_STATUS:"
@ -613,25 +612,27 @@ void Websocket_RefreshClientData_Status(uint32_t client_id, bool send_mapping)
Debug_pushMessage("send MAPPING_STATUS WS-Client Data\n"); Debug_pushMessage("send MAPPING_STATUS WS-Client Data\n");
} }
String temp = "STATUS:"; char dataString[200] = {0}; // Maximal 200 Zeichen für den Data-String
temp.concat(String(globals.battery_level) + ";"); sprintf(dataString, "STATUS:%d;%s;%d;%ld;%ld;%ld;",
temp.concat(String(globals.systemStatustxt) + ";"); globals.battery_level,
temp.concat(String(PersistenceData.activeFaction) + ";"); globals.systemStatustxt,
temp.concat(String(PersistenceData.faction_1_timer) + ";"); PersistenceData.activeFaction,
temp.concat(String(PersistenceData.faction_2_timer) + ";"); PersistenceData.faction_1_timer,
temp.concat(String(PersistenceData.faction_3_timer) + ";"); PersistenceData.faction_2_timer,
PersistenceData.faction_3_timer);
if (client_id > 0) if (client_id > 0)
{ {
webSocket.text(client_id, temp); webSocket.text(client_id, dataString);
} }
else else
{ {
webSocket.textAll(temp); webSocket.textAll(dataString);
} }
} }
/** /**
* @brief Refreshes client data related to static configuration parameters on WebSocket clients. * @brief Refreshes client data related to static configuration parameters on WebSocket clients.
* *
@ -645,6 +646,7 @@ void Websocket_RefreshClientData_Status(uint32_t client_id, bool send_mapping)
void Websocket_RefreshClientData_Static(uint32_t client_id, bool send_mapping) void Websocket_RefreshClientData_Static(uint32_t client_id, bool send_mapping)
{ {
Debug_pushMessage("send STATIC WS-Client Data\n");
if (send_mapping) if (send_mapping)
{ {
const char mapping[] = "MAPPING_STATIC:" const char mapping[] = "MAPPING_STATIC:"
@ -664,11 +666,11 @@ void Websocket_RefreshClientData_Static(uint32_t client_id, bool send_mapping)
webSocket.text(client_id, mapping); webSocket.text(client_id, mapping);
else else
webSocket.textAll(mapping); webSocket.textAll(mapping);
Debug_pushMessage("send MAPPING_STATIC WS-Client Data\n");
} }
char dataString[200]; // Maximal 200 Zeichen für den Data-String char dataString[200] = {0}; // Maximal 200 Zeichen für den Data-String
char flash_version[6];
GetFlashVersion(flash_version, sizeof(flash_version));
sprintf(dataString, "STATIC:%s;%d;%d;%s;%s;%s;%s;%s;%d.%02d;%s;%s;", sprintf(dataString, "STATIC:%s;%d;%d;%s;%s;%s;%s;%s;%d.%02d;%s;%s;",
globals.DeviceName, globals.DeviceName,
@ -681,7 +683,7 @@ void Websocket_RefreshClientData_Static(uint32_t client_id, bool send_mapping)
ConfigData.wifi_client_password, ConfigData.wifi_client_password,
constants.FW_Version_major, constants.FW_Version_major,
constants.FW_Version_minor, constants.FW_Version_minor,
flash_version, globals.FlashVersion,
constants.GitHash); constants.GitHash);
if (client_id > 0) if (client_id > 0)