Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions SmartFuseBox/Dht11SensorHandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -186,8 +186,6 @@ class Dht11SensorHandler : public BaseSensor, public BroadcastLoggerSupport

uint64_t update() override
{
sendDebug("Reading DHT11 sensor...", _name);

float temperature = 0.0f;
float humidity = 0.0f;
int result = readDht11(_sensorPin, temperature, humidity);
Expand Down
25 changes: 19 additions & 6 deletions SmartFuseBox/INetworkCommandHandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,14 +47,27 @@ class INetworkCommandHandler : public NetworkJsonVisitor
* @param bufferSize Size of response buffer
* @return CommandResult with success/status
*/
virtual CommandResult handleRequest(const char* method,
virtual CommandResult handleRequest(const char* method,
const char* command,
StringKeyValue* params,
StringKeyValue* params,
uint8_t paramCount,
char* responseBuffer,
size_t bufferSize) = 0;

virtual ~INetworkCommandHandler() = default;
char* responseBuffer,
size_t bufferSize) = 0;

/**
* @brief Optionally stream an HTML response directly to the client.
*
* Handlers that produce HTML (rather than JSON) should override this method,
* write a complete HTTP response (headers + body) to @p client and return true.
* The default implementation returns false, which causes the caller to fall
* back to the standard JSON path via handleRequest().
*
* @param client The WiFi client to write to.
* @return true if the response was handled and written; false otherwise.
*/
virtual bool generateHtml(IWifiClient& client) const { return false; }

virtual ~INetworkCommandHandler() = default;

uint8_t formatJsonResponse(char* buffer, size_t size, bool success, const char* message = nullptr)
{
Expand Down
10 changes: 5 additions & 5 deletions SmartFuseBox/Local.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,30 +61,30 @@


// ─── Display Support ───────────────────────────────────────────────────────
// Enable support for Nextion displays.
// Enable support for Nextion displays (approx 52kb).
#define NEXTION_DISPLAY_DEVICE

// ─── Optional Features ────────────────────────────────────────────────────────
// Remove the trailing underscore to enable each feature.

// SD card support (experimental)
// SD card support (experimental) (approx 32kb)
#define SD_CARD_SUPPORT

#if defined(SD_CARD_SUPPORT)
// Read config.txt from SD card at boot. Requires SD_CARD_SUPPORT.
#define CARD_CONFIG_LOADER_
#endif

// MQTT home-assistant discovery (requires WIFI_SUPPORT — enforced in BoardConfig.h)
// MQTT home-assistant discovery (requires WIFI_SUPPORT — enforced in BoardConfig.h) (approx 40kb)
#define MQTT_SUPPORT

// OTA auto-update via GitHub releases (requires ESP32 + WIFI_SUPPORT — enforced in BoardConfig.h).
// When enabled, the device checks for a new release every 24 hours and broadcasts the result.
// Auto-applying the update is OFF by default; use the F12:apply=1 command or set the
// OtaFlagAutoApply bit in SystemHeader::reserved[0] to enable automatic installs.
// OtaFlagAutoApply bit in SystemHeader::reserved[0] to enable automatic installs. (approx 165kb)
#define OTA_AUTO_UPDATE

// Bluetooth BLE (mutually exclusive with WIFI_SUPPORT on Arduino Uno R4)
// Bluetooth BLE (mutually exclusive with WIFI_SUPPORT on Arduino Uno R4) (approx 144kb)
#define BLUETOOTH_SUPPORT_

// Led Manager on arduino R4 Wifi, experimental at present time
Expand Down
7 changes: 0 additions & 7 deletions SmartFuseBox/PageSystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,13 +73,6 @@ void PageSystem::refresh(unsigned long now)

if (now - _lastRefreshTime >= RefreshSystemIntervalMs)
{
SerialCommandManager* compMgr = getCommandMgrComputer();

if (compMgr)
{
compMgr->sendDebug(F("Sending F2/F3"), F("SystemPage"));
}

_lastRefreshTime = now;

setFuseBoxCpu(SystemCpuMonitor::getCpuUsage());
Expand Down
27 changes: 17 additions & 10 deletions SmartFuseBox/RelayCommandHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -112,17 +112,24 @@ bool RelayCommandHandler::handleCommand(SerialCommandManager* sender, const char
}

CommandResult result = _relayController->setRelayState(relayIndex, state > 0);
RelayResult status = static_cast<RelayResult>(result.status);

if (status == RelayResult::InvalidIndex)
{
sendAckErr(sender, command, F("Invalid relay index"), &params[0]);
return true;
}
else if (status == RelayResult::Reserved)
{
sendAckErr(sender, command, F("Relay is reserved for sound system"), &params[0]);
return true;
if (!result.success)
{
RelayResult status = static_cast<RelayResult>(result.status);

if (status == RelayResult::InvalidIndex)
{
sendAckErr(sender, command, F("Invalid relay index"), &params[0]);
return true;
}
else if (status == RelayResult::Reserved)
{
sendAckErr(sender, command, F("Relay is reserved for sound system"), &params[0]);
return true;
}

sendAckErr(sender, command, F("Failed to set relay state"), &params[0]);
return true;
}

broadcastRelayStatus(command, &params[0]);
Expand Down
8 changes: 2 additions & 6 deletions SmartFuseBox/RelayNetworkHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,13 +66,9 @@ CommandResult RelayNetworkHandler::handleRequest(const char* method,
}

CommandResult result = _relayController->setRelayState(relayIndex, state > 0);
RelayResult status = static_cast<RelayResult>(result.status);

if (status == RelayResult::InvalidIndex)
{
return CommandResult::error(InvalidCommandParameters);
}
else if (status == RelayResult::Reserved)

if (!result.success)
{
return CommandResult::error(InvalidCommandParameters);
}
Expand Down
5 changes: 3 additions & 2 deletions SmartFuseBox/SmartFuseBox.vcxproj

Large diffs are not rendered by default.

9 changes: 6 additions & 3 deletions SmartFuseBox/SmartFuseBoxApp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,10 +75,11 @@ SmartFuseBoxApp::SmartFuseBoxApp(SerialCommandManager* commandMgrComputer)
_soundNetworkHandler(&_soundController),
_warningNetworkHandler(&_warningManager),
_systemNetworkHandler(&_wifiController),
_sensorNetworkHandler(nullptr)
_sensorNetworkHandler(nullptr),
_webIndexNetworkHandler(nullptr)

#if defined(SD_CARD_SUPPORT)
, _sdCardLogger(&_sensorCommandHandler, &_warningManager)
, _sdCardLogger(&_sensorCommandHandler, &_warningManager)
#endif

, _sensorManager(nullptr)
Expand Down Expand Up @@ -235,6 +236,8 @@ void SmartFuseBoxApp::setup(RemoteSensor** remoteSensors, uint8_t remoteSensorCo
_sensorManager = new SensorManager(allHandlers, totalCount);

_sensorNetworkHandler = new SensorNetworkHandler(_sensorController);
_webIndexNetworkHandler = new WebIndexNetworkHandler(&_relayController, _sensorController);

_relayController.setup();

// middleware
Expand Down Expand Up @@ -443,7 +446,7 @@ void SmartFuseBoxApp::configureWifiSupport(Config* config)
// network command handlers
INetworkCommandHandler* networkHandlers[] = { &_relayNetworkHandler, &_soundNetworkHandler, &_warningNetworkHandler,
&_systemNetworkHandler, _sensorNetworkHandler, &_configNetworkHandler, &_schedulerNetworkHandler,
&_externalSensorNetworkHandler,
&_externalSensorNetworkHandler, _webIndexNetworkHandler,
&_wifiCommandBridge
};
size_t networkHandlerCount = sizeof(networkHandlers) / sizeof(networkHandlers[0]);
Expand Down
2 changes: 2 additions & 0 deletions SmartFuseBox/SmartFuseBoxApp.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
#include "SensorNetworkHandler.h"
#include "WarningNetworkHandler.h"
#include "SchedulerNetworkHandler.h"
#include "WebIndexNetworkHandler.h"
#include "WifiCommandBridge.h"

#if defined(SD_CARD_SUPPORT)
Expand Down Expand Up @@ -129,6 +130,7 @@ class SmartFuseBoxApp
WarningNetworkHandler _warningNetworkHandler;
SystemNetworkHandler _systemNetworkHandler;
SensorNetworkHandler* _sensorNetworkHandler;
WebIndexNetworkHandler* _webIndexNetworkHandler;

#if defined(SD_CARD_SUPPORT)
SdCardLogger _sdCardLogger;
Expand Down
76 changes: 76 additions & 0 deletions SmartFuseBox/SystemFunctions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -472,6 +472,82 @@ void SystemFunctions::sanitizeJsonString(const char* input, char* output, size_t
output[outPos] = '\0';
}

void SystemFunctions::escapeHtml(const char* input, char* output, size_t outputSize)
{
if (!output || outputSize == 0)
return;

output[0] = '\0';

if (!input)
return;

size_t outPos = 0;
const size_t limit = outputSize - 1;

while (*input != '\0' && outPos < limit)
{
char c = *input++;

// Escape special HTML characters
if (c == '&')
{
// &amp; (5 chars)
if (outPos + 5 > limit) break;
output[outPos++] = '&';
output[outPos++] = 'a';
output[outPos++] = 'm';
output[outPos++] = 'p';
output[outPos++] = ';';
}
else if (c == '<')
{
// &lt; (4 chars)
if (outPos + 4 > limit) break;
output[outPos++] = '&';
output[outPos++] = 'l';
output[outPos++] = 't';
output[outPos++] = ';';
}
else if (c == '>')
{
// &gt; (4 chars)
if (outPos + 4 > limit) break;
output[outPos++] = '&';
output[outPos++] = 'g';
output[outPos++] = 't';
output[outPos++] = ';';
}
else if (c == '"')
{
// &quot; (6 chars)
if (outPos + 6 > limit) break;
output[outPos++] = '&';
output[outPos++] = 'q';
output[outPos++] = 'u';
output[outPos++] = 'o';
output[outPos++] = 't';
output[outPos++] = ';';
}
else if (c == '\'')
{
// &#39; (5 chars)
if (outPos + 5 > limit) break;
output[outPos++] = '&';
output[outPos++] = '#';
output[outPos++] = '3';
output[outPos++] = '9';
output[outPos++] = ';';
}
else
{
output[outPos++] = c;
}
}

output[outPos] = '\0';
}

bool SystemFunctions::progmemToBuffer(const char* progmemStr, char* buffer, size_t bufferSize)
{
if (!progmemStr || !buffer || bufferSize == 0)
Expand Down
18 changes: 18 additions & 0 deletions SmartFuseBox/SystemFunctions.h
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,24 @@ class SystemFunctions
*/
static void sanitizeJsonString(const char* input, char* output, size_t outputSize);

/**
* @brief Escape a string for safe embedding in HTML content.
*
* Applies HTML entity escaping for the five special characters:
* - `&` -> `&amp;`
* - `<` -> `&lt;`
* - `>` -> `&gt;`
* - `"` -> `&quot;`
* - `'` -> `&#39;`
* The output is always null-terminated. Characters whose escape sequence
* would not fit in the remaining buffer are silently dropped.
*
* @param input Source string (RAM)
* @param output Destination buffer
* @param outputSize Size of destination buffer including null terminator
*/
static void escapeHtml(const char* input, char* output, size_t outputSize);

static bool progmemToBuffer(const char* progmemStr, char* buffer, size_t bufferSize);

static TimeParts msToTimeParts(uint64_t ms);
Expand Down
1 change: 0 additions & 1 deletion SmartFuseBox/WarningCommandHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ bool WarningCommandHandler::handleCommand(SerialCommandManager* sender, const ch
if (!warningManager)
{
sendAckErr(sender, command, F("Warning manager not configured"));
sendDebugMessage(F("Warning manager not available"), F("WarningCommandHandler"));
return false;
}

Expand Down
Loading
Loading