Skip to content

Commit a80b665

Browse files
authored
Minor fixes and updates (#182)
* Minor fixes and updates
1 parent 4de78c2 commit a80b665

16 files changed

Lines changed: 329 additions & 32 deletions

SmartFuseBox/Config.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -141,8 +141,7 @@ constexpr uint8_t ConfigLinkedRelayCount = 2;
141141

142142
struct SystemConfig {
143143
int8_t timezoneOffset;
144-
bool rebootOnSave; // if true, device reboots after C0 persists config
145-
uint8_t reserved1[3];
144+
uint8_t reserved1[4];
146145
int8_t reserved2[4];
147146
} __attribute__((packed));
148147

SmartFuseBox/ConfigCommandHandler.cpp

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "ConfigCommandHandler.h"
2020
#include "ConfigController.h"
2121
#include "SystemFunctions.h"
22+
#include "MessageBus.h"
2223

2324
#if defined(CARD_CONFIG_LOADER)
2425
#include "SdCardConfigLoader.h"
@@ -35,7 +36,8 @@ ConfigCommandHandler::ConfigCommandHandler(
3536
ConfigController* configController)
3637
:
3738
_wifiController(wifiController),
38-
_configController(configController)
39+
_configController(configController),
40+
_messageBus(nullptr)
3941
#if defined(CARD_CONFIG_LOADER)
4042
, _sdCardConfigLoader(nullptr)
4143
#endif
@@ -45,6 +47,11 @@ ConfigCommandHandler::ConfigCommandHandler(
4547
#endif
4648
{}
4749

50+
void ConfigCommandHandler::setMessageBus(MessageBus* messageBus)
51+
{
52+
_messageBus = messageBus;
53+
}
54+
4855
#if defined(MQTT_SUPPORT)
4956
void ConfigCommandHandler::setMqttConfigHandler(MQTTConfigCommandHandler* mqttConfigHandler)
5057
{
@@ -65,6 +72,29 @@ bool ConfigCommandHandler::handleCommand(SerialCommandManager* sender, const cha
6572
if (SystemFunctions::commandMatches(command, ConfigSaveSettings))
6673
{
6774
result = _configController->save();
75+
76+
if (result == ConfigResult::Success)
77+
{
78+
const char* rebootStr = getParamValue(params, paramCount, "reboot");
79+
if (rebootStr && SystemFunctions::parseBooleanValue(rebootStr))
80+
{
81+
if (SystemFunctions::canReboot() && _messageBus != nullptr)
82+
{
83+
char rebootVal[] = "pending";
84+
StringKeyValue rebootParam = makeParam("reboot", rebootVal);
85+
sendAckOk(sender, command, &rebootParam);
86+
_messageBus->publish<RebootRequested>();
87+
return true;
88+
}
89+
else
90+
{
91+
char rebootVal[] = "required";
92+
StringKeyValue rebootParam = makeParam("reboot", rebootVal);
93+
sendAckOk(sender, command, &rebootParam);
94+
return true;
95+
}
96+
}
97+
}
6898
}
6999
else if (SystemFunctions::commandMatches(command, ConfigGetSettings))
70100
{

SmartFuseBox/ConfigCommandHandler.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525

2626
// Forward declarations
2727
class ConfigController;
28+
class MessageBus;
2829

2930
#if defined(CARD_CONFIG_LOADER)
3031
class SdCardConfigLoader;
@@ -40,6 +41,7 @@ class ConfigCommandHandler : public virtual BaseCommandHandler, public BaseConfi
4041
private:
4142
IWifiController* _wifiController;
4243
ConfigController* _configController;
44+
MessageBus* _messageBus;
4345

4446
#if defined(CARD_CONFIG_LOADER)
4547
SdCardConfigLoader* _sdCardConfigLoader;
@@ -55,6 +57,8 @@ class ConfigCommandHandler : public virtual BaseCommandHandler, public BaseConfi
5557
IWifiController* wifiController,
5658
ConfigController* configController);
5759

60+
void setMessageBus(MessageBus* messageBus);
61+
5862
#if defined(CARD_CONFIG_LOADER)
5963
void setSdCardConfigLoader(SdCardConfigLoader* sdCardConfigLoader);
6064
#endif

SmartFuseBox/ConfigManager.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ void ConfigManager::migrateV4toV5()
192192
memset(_cfg.auth.reserved, 0x00, sizeof(_cfg.auth.reserved));
193193

194194
_cfg.version = ConfigVersion5;
195-
_cfg.system.rebootOnSave = false;
195+
memset(_cfg.system.reserved1, 0x00, sizeof(_cfg.system.reserved1));
196196
_cfg.sdCard.csPin = PinDisabled;
197197
}
198198

@@ -316,7 +316,6 @@ void ConfigManager::resetToDefaults()
316316
strncpy(_cfg.location.homePort, "Unknown", ConfigHomePortLength - 1);
317317
_cfg.location.homePort[ConfigHomePortLength - 1] = '\0';
318318
_cfg.system.timezoneOffset = 0; // UTC
319-
_cfg.system.rebootOnSave = false;
320319

321320
_cfg.network.bluetoothEnabled = false;
322321

SmartFuseBox/Dht11SensorHandler.h

Lines changed: 77 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "WarningManager.h"
2626
#include "WarningType.h"
2727
#include "BaseSensor.h"
28+
#include "Environment.h"
2829

2930
constexpr uint64_t TempHumidityCheckMs = 2500;
3031

@@ -48,8 +49,14 @@ class Dht11SensorHandler : public BaseSensor, public BroadcastLoggerSupport
4849
#if defined(MQTT_SUPPORT)
4950
char _slugTemp[32];
5051
char _slugHumidity[32];
52+
char _slugDewPoint[32];
53+
char _slugComfort[32];
54+
char _slugCondensation[40];
5155
char _nameTemp[48];
5256
char _nameHumidity[48];
57+
char _nameDewPoint[48];
58+
char _nameComfort[48];
59+
char _nameCondensation[48];
5360
#endif
5461

5562
protected:
@@ -232,8 +239,14 @@ class Dht11SensorHandler : public BaseSensor, public BroadcastLoggerSupport
232239
#if defined(MQTT_SUPPORT)
233240
snprintf(_slugTemp, sizeof(_slugTemp), "%s_temperature", _safeSlug);
234241
snprintf(_slugHumidity, sizeof(_slugHumidity), "%s_humidity", _safeSlug);
242+
snprintf(_slugDewPoint, sizeof(_slugDewPoint), "%s_dew_point", _safeSlug);
243+
snprintf(_slugComfort, sizeof(_slugComfort), "%s_comfort", _safeSlug);
244+
snprintf(_slugCondensation, sizeof(_slugCondensation), "%s_condensation_risk", _safeSlug);
235245
snprintf(_nameTemp, sizeof(_nameTemp), "%s Temperature", _name);
236246
snprintf(_nameHumidity, sizeof(_nameHumidity), "%s Humidity", _name);
247+
snprintf(_nameDewPoint, sizeof(_nameDewPoint), "%s Dew Point", _name);
248+
snprintf(_nameComfort, sizeof(_nameComfort), "%s Comfort", _name);
249+
snprintf(_nameCondensation, sizeof(_nameCondensation), "%s Condensation Risk", _name);
237250
#endif
238251
}
239252

@@ -254,8 +267,25 @@ class Dht11SensorHandler : public BaseSensor, public BroadcastLoggerSupport
254267
dtostrf(_temperatureOffset, 1, 1, celsiusOffset);
255268
dtostrf(_humidityOffset, 1, 1, humidityOffset);
256269

257-
int written = snprintf(buffer, size, "\"name\":\"%s\",\"SensorPin\":%u,\"temperature\":%s,\"tempOffset\":%s,\"humidity\":%s,\"humOffset\":%s",
258-
_name, _sensorPin, celsius, celsiusOffset, humidity, humidityOffset);
270+
double dewPt = Environment::dewPoint(_celsius, _humidity);
271+
char dewPointStr[8];
272+
dtostrf(dewPt, 1, 1, dewPointStr);
273+
274+
char comfortBuf[24];
275+
strncpy_P(comfortBuf, Environment::getComfortDescription(_celsius, _humidity, dewPt), sizeof(comfortBuf));
276+
comfortBuf[sizeof(comfortBuf) - 1] = '\0';
277+
278+
CondensationRisk risk = Environment::condensationRisk(_celsius, dewPt, false);
279+
char riskBuf[8];
280+
strncpy_P(riskBuf, Environment::getCondensationRiskLabel(risk), sizeof(riskBuf));
281+
riskBuf[sizeof(riskBuf) - 1] = '\0';
282+
283+
char safeName[64];
284+
SystemFunctions::sanitizeJsonString(_name, safeName, sizeof(safeName));
285+
286+
int written = snprintf(buffer, size,
287+
"\"name\":\"%s\",\"SensorPin\":%u,\"temperature\":%s,\"tempOffset\":%s,\"humidity\":%s,\"humOffset\":%s,\"dew_point\":%s,\"comfort\":\"%s\",\"condensation_risk\":\"%s\"",
288+
safeName, _sensorPin, celsius, celsiusOffset, humidity, humidityOffset, dewPointStr, comfortBuf, riskBuf);
259289

260290
if (written < 0 || (size_t)written >= size)
261291
{
@@ -282,28 +312,62 @@ class Dht11SensorHandler : public BaseSensor, public BroadcastLoggerSupport
282312
#if defined(MQTT_SUPPORT)
283313
uint8_t getMqttChannelCount() const override
284314
{
285-
return 2;
315+
return 5;
286316
}
287317

288318
MqttSensorChannel getMqttChannel(uint8_t channelIndex) const override
289319
{
290-
if (channelIndex == 0)
320+
switch (channelIndex)
291321
{
292-
return { _nameTemp, _slugTemp, "temperature", "temperature", "\xc2\xb0""C", false };
322+
case 0:
323+
return { _nameTemp, _slugTemp, "temperature", "temperature", "\xc2\xb0""C", false };
324+
case 1:
325+
return { _nameHumidity, _slugHumidity, "humidity", "humidity", "%", false };
326+
case 2:
327+
return { _nameDewPoint, _slugDewPoint, "humidity", "temperature", "\xc2\xb0""C", false };
328+
case 3:
329+
return { _nameComfort, _slugComfort, "humidity", nullptr, nullptr, false };
330+
case 4:
331+
return { _nameCondensation, _slugCondensation, "humidity", nullptr, nullptr, false };
332+
default:
333+
return { _nameHumidity, _slugHumidity, "humidity", "humidity", "%", false };
293334
}
294-
295-
return { _nameHumidity, _slugHumidity, "humidity", "humidity", "%", false };
296335
}
297336

298337
void getMqttValue(uint8_t channelIndex, char* buffer, size_t size) const override
299338
{
300-
if (channelIndex == 0)
301-
{
302-
dtostrf(_celsius, 1, 1, buffer);
303-
}
304-
else
339+
switch (channelIndex)
305340
{
306-
snprintf(buffer, size, "%u", static_cast<uint8_t>(_humidity));
341+
case 0:
342+
dtostrf(_celsius, 1, 1, buffer);
343+
break;
344+
case 1:
345+
snprintf(buffer, size, "%u", static_cast<uint8_t>(_humidity));
346+
break;
347+
case 2:
348+
{
349+
double dewPt = Environment::dewPoint(_celsius, _humidity);
350+
dtostrf(dewPt, 1, 1, buffer);
351+
break;
352+
}
353+
case 3:
354+
{
355+
double dewPt = Environment::dewPoint(_celsius, _humidity);
356+
strncpy_P(buffer, Environment::getComfortDescription(_celsius, _humidity, dewPt), size);
357+
buffer[size - 1] = '\0';
358+
break;
359+
}
360+
case 4:
361+
{
362+
double dewPt = Environment::dewPoint(_celsius, _humidity);
363+
CondensationRisk risk = Environment::condensationRisk(_celsius, dewPt, false);
364+
strncpy_P(buffer, Environment::getCondensationRiskLabel(risk), size);
365+
buffer[size - 1] = '\0';
366+
break;
367+
}
368+
default:
369+
if (size > 0) buffer[0] = '\0';
370+
break;
307371
}
308372
}
309373
#endif

SmartFuseBox/Environment.h

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ constexpr char comfortHumid[] PROGMEM = "Humid";
2626
constexpr char comfortDry[] PROGMEM = "Dry";
2727
constexpr char comfortFair[] PROGMEM = "Fair";
2828

29+
constexpr char condensationLow[] PROGMEM = "Low";
30+
constexpr char condensationWatch[] PROGMEM = "Watch";
31+
constexpr char condensationHigh[] PROGMEM = "High";
32+
2933
enum class CondensationRisk
3034
{
3135
Low,
@@ -62,4 +66,51 @@ class Environment
6266
if (delta <= 2.0) return CondensationRisk::Watch;
6367
return CondensationRisk::Low;
6468
}
69+
70+
/**
71+
* @brief Return a PROGMEM comfort description string based on temperature, humidity and dew point.
72+
*
73+
* @param tempC Air temperature in degrees Celsius
74+
* @param humidity Relative humidity (0-100 %)
75+
* @param dewPoint Pre-calculated dew point in degrees Celsius
76+
* @return PROGMEM string pointer — copy with strncpy_P before use
77+
*/
78+
static const char* getComfortDescription(double tempC, double humidity, double dewPoint)
79+
{
80+
if (tempC < 10 && humidity > 70)
81+
return comfortColdDamp;
82+
83+
if (tempC < 12)
84+
return comfortCold;
85+
86+
if (tempC > 26 && humidity > 65)
87+
return comfortHotHumid;
88+
89+
if (dewPoint > 18)
90+
return comfortHumid;
91+
92+
if (tempC >= 18 && tempC <= 24 && humidity < 65)
93+
return comfortComfortable;
94+
95+
return comfortFair;
96+
}
97+
98+
/**
99+
* @brief Return a PROGMEM label string for a CondensationRisk value.
100+
*
101+
* @param risk Condensation risk level
102+
* @return PROGMEM string pointer — copy with strncpy_P before use
103+
*/
104+
static const char* getCondensationRiskLabel(CondensationRisk risk)
105+
{
106+
switch (risk)
107+
{
108+
case CondensationRisk::High:
109+
return condensationHigh;
110+
case CondensationRisk::Watch:
111+
return condensationWatch;
112+
default:
113+
return condensationLow;
114+
}
115+
}
65116
};

SmartFuseBox/MessageBus.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,11 @@ struct MqttMessageReceived
167167
using Callback = std::function<void(const char* topic, const char* payload)>;
168168
};
169169

170+
struct RebootRequested
171+
{
172+
using Callback = std::function<void()>;
173+
};
174+
170175
class MessageBus {
171176
private:
172177
template<typename Event>

SmartFuseBox/PageVhfRadio.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ void PageVhfRadio::onEnterPage()
7474
char wrappedBuffer[134];
7575
SystemFunctions::wrapTextAtWordBoundary(callSignBuf, wrappedBuffer, sizeof(wrappedBuffer), 30);
7676

77-
sendText(ControlCallSign, callSignBuf);
77+
sendText(ControlCallSign, wrappedBuffer);
7878
}
7979

8080
void PageVhfRadio::begin()

SmartFuseBox/SensorNetworkHandler.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,9 +97,11 @@ void SensorNetworkHandler::formatStatusJson(char* buffer, size_t size)
9797
}
9898

9999
// Write sensor entry (removed duplicate and fixed format)
100+
char safeName[64];
101+
SystemFunctions::sanitizeJsonString(sensor->getSensorName(), safeName, sizeof(safeName));
100102
int n = snprintf(buffer + written, size - written,
101103
"\"%s\":{\"uid\":%d,\"idType\":%d,\"type\":%d,%s}",
102-
sensor->getSensorName(),
104+
safeName,
103105
sensor->getUid(),
104106
static_cast<uint8_t>(sensor->getSensorIdType()),
105107
static_cast<uint8_t>(sensor->getSensorType()),

SmartFuseBox/SmartFuseBox.vcxproj

Lines changed: 2 additions & 2 deletions
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)