Add Waveshare LR1121 observer recipes. Adapt observer advert verification to existing transactional CLI, append-only binary preferences and Companion NVS, preserving default file lengths and WiFi credentials. Reject oversized unsigned advert tails consistently with Mesh::onRecvPacket. Keep current BLE recovery and GPS claim accounting.
452 lines
19 KiB
C++
452 lines
19 KiB
C++
#pragma once
|
|
|
|
#include <helpers/ConfigSerializer.h>
|
|
#include <helpers/MQTTObserverValidation.h>
|
|
#include <helpers/MQTTPrefsStorage.h>
|
|
|
|
#ifdef WITH_MQTT_BRIDGE
|
|
|
|
static const int32_t MQTT_PREFS_JSON_FORMAT_VERSION = 1;
|
|
typedef bool (*MQTTPrefsPresetValidator)(const char* preset);
|
|
|
|
// Format invariant inherited from observer-firmware-dev: `version` is the
|
|
// first root property. Recognizing it before any later unknown grammar lets the
|
|
// importer preserve a future file as opaque rather than misclassifying it as a
|
|
// corrupt v1 source.
|
|
|
|
// ConfigSerializer adapter for the observer preference POD. Keeping the
|
|
// serializer separate avoids making the runtime object layout part of the JSON
|
|
// format and adds no permanent per-slot serializer state to CommonCLI.
|
|
class MQTTPrefsSerializer : public ConfigSerializer {
|
|
|
|
class WifiPrefs : public ConfigSerializer {
|
|
MQTTPrefs* _prefs;
|
|
int32_t _power_save, _default_power_save;
|
|
bool _seen_ssid = false, _seen_password = false, _seen_power_save = false;
|
|
protected:
|
|
void structure() override {
|
|
defStrict("ssid", _prefs->wifi_ssid, sizeof(_prefs->wifi_ssid), _seen_ssid);
|
|
defStrict("password", _prefs->wifi_password, sizeof(_prefs->wifi_password), _seen_password);
|
|
defStrict("power_save", _power_save, _seen_power_save);
|
|
}
|
|
public:
|
|
WifiPrefs(MQTTPrefs* prefs, const MQTTPrefs* defaults)
|
|
: _prefs(prefs), _power_save(prefs->wifi_power_save),
|
|
_default_power_save(defaults->wifi_power_save) {
|
|
if (_default_power_save < 0 || _default_power_save > 2) {
|
|
_default_power_save = 1;
|
|
}
|
|
}
|
|
bool apply(bool* repaired) {
|
|
if (_power_save < 0 || _power_save > 2) {
|
|
_power_save = _default_power_save;
|
|
*repaired = true;
|
|
}
|
|
_prefs->wifi_power_save = static_cast<uint8_t>(_power_save);
|
|
return true;
|
|
}
|
|
};
|
|
|
|
class TimePrefs : public ConfigSerializer {
|
|
MQTTPrefs* _prefs;
|
|
int32_t _utc_offset, _default_utc_offset;
|
|
char _default_ntp_server[sizeof(MQTTPrefs::mqtt_ntp_server)];
|
|
bool _seen_timezone = false, _seen_utc_offset = false, _seen_ntp_server = false;
|
|
protected:
|
|
void structure() override {
|
|
defStrict("timezone", _prefs->timezone_string, sizeof(_prefs->timezone_string), _seen_timezone);
|
|
defStrict("utc_offset", _utc_offset, _seen_utc_offset);
|
|
defStrict("ntp_server", _prefs->mqtt_ntp_server, sizeof(_prefs->mqtt_ntp_server), _seen_ntp_server);
|
|
}
|
|
public:
|
|
TimePrefs(MQTTPrefs* prefs, const MQTTPrefs* defaults)
|
|
: _prefs(prefs), _utc_offset(prefs->timezone_offset),
|
|
_default_utc_offset(defaults->timezone_offset) {
|
|
if (_default_utc_offset < -12 || _default_utc_offset > 14) {
|
|
_default_utc_offset = 0;
|
|
}
|
|
memcpy(_default_ntp_server, defaults->mqtt_ntp_server, sizeof(_default_ntp_server));
|
|
if (_default_ntp_server[0] != '\0' &&
|
|
!mqttNtpHostnameValid(_default_ntp_server)) {
|
|
_default_ntp_server[0] = '\0';
|
|
}
|
|
}
|
|
bool apply(bool* repaired) {
|
|
if (_utc_offset < -12 || _utc_offset > 14) {
|
|
_utc_offset = _default_utc_offset;
|
|
*repaired = true;
|
|
}
|
|
if (_prefs->mqtt_ntp_server[0] != '\0' &&
|
|
!mqttNtpHostnameValid(_prefs->mqtt_ntp_server)) {
|
|
memcpy(_prefs->mqtt_ntp_server, _default_ntp_server, sizeof(_default_ntp_server));
|
|
*repaired = true;
|
|
}
|
|
_prefs->timezone_offset = static_cast<int8_t>(_utc_offset);
|
|
return true;
|
|
}
|
|
};
|
|
|
|
class StatusPrefs : public ConfigSerializer {
|
|
MQTTPrefs* _prefs;
|
|
int32_t _enabled, _interval_ms;
|
|
bool _seen_enabled = false, _seen_interval = false;
|
|
protected:
|
|
void structure() override {
|
|
defStrict("enabled", _enabled, _seen_enabled);
|
|
defStrict("interval_ms", _interval_ms, _seen_interval);
|
|
}
|
|
public:
|
|
explicit StatusPrefs(MQTTPrefs* prefs)
|
|
: _prefs(prefs), _enabled(prefs->mqtt_status_enabled),
|
|
_interval_ms(static_cast<int32_t>(prefs->mqtt_status_interval)) {}
|
|
void apply(bool* repaired) {
|
|
if (_enabled < 0 || _enabled > 1) { _enabled = 1; *repaired = true; }
|
|
if (_interval_ms < 60000 || _interval_ms > 3600000) {
|
|
_interval_ms = 300000;
|
|
*repaired = true;
|
|
}
|
|
_prefs->mqtt_status_enabled = static_cast<uint8_t>(_enabled);
|
|
_prefs->mqtt_status_interval = static_cast<uint32_t>(_interval_ms);
|
|
}
|
|
};
|
|
|
|
class NeighborPrefs : public ConfigSerializer {
|
|
MQTTPrefs* _prefs;
|
|
int32_t _enabled, _interval_ms;
|
|
bool _seen_enabled = false, _seen_interval = false;
|
|
protected:
|
|
void structure() override {
|
|
defStrict("enabled", _enabled, _seen_enabled);
|
|
defStrict("interval_ms", _interval_ms, _seen_interval);
|
|
}
|
|
public:
|
|
explicit NeighborPrefs(MQTTPrefs* prefs)
|
|
: _prefs(prefs), _enabled(prefs->mqtt_neighbors_enabled),
|
|
_interval_ms(static_cast<int32_t>(prefs->mqtt_neighbors_interval)) {}
|
|
void apply(bool* repaired) {
|
|
if (_enabled < 0 || _enabled > 1) { _enabled = 0; *repaired = true; }
|
|
if (_interval_ms < static_cast<int32_t>(MQTT_NEIGHBORS_MIN_INTERVAL_MS) ||
|
|
_interval_ms > static_cast<int32_t>(MQTT_NEIGHBORS_MAX_INTERVAL_MS)) {
|
|
_interval_ms = static_cast<int32_t>(MQTT_NEIGHBORS_DEFAULT_INTERVAL_MS);
|
|
*repaired = true;
|
|
}
|
|
_prefs->mqtt_neighbors_enabled = static_cast<uint8_t>(_enabled);
|
|
_prefs->mqtt_neighbors_interval = static_cast<uint32_t>(_interval_ms);
|
|
}
|
|
};
|
|
|
|
class OwnerPrefs : public ConfigSerializer {
|
|
MQTTPrefs* _prefs;
|
|
bool _seen_public_key = false, _seen_email = false;
|
|
protected:
|
|
void structure() override {
|
|
defStrict("public_key", _prefs->mqtt_owner_public_key,
|
|
sizeof(_prefs->mqtt_owner_public_key), _seen_public_key);
|
|
defStrict("email", _prefs->mqtt_email, sizeof(_prefs->mqtt_email), _seen_email);
|
|
}
|
|
public:
|
|
explicit OwnerPrefs(MQTTPrefs* prefs) : _prefs(prefs) {}
|
|
void apply(bool* repaired) {
|
|
if (_prefs->mqtt_owner_public_key[0] != '\0' &&
|
|
!mqttOwnerKeyValid(_prefs->mqtt_owner_public_key)) {
|
|
_prefs->mqtt_owner_public_key[0] = '\0';
|
|
*repaired = true;
|
|
}
|
|
}
|
|
};
|
|
|
|
class SlotPrefs : public ConfigSerializer {
|
|
MQTTPrefs* _prefs;
|
|
int _index;
|
|
int32_t _port, _filter;
|
|
MQTTPrefsPresetValidator _preset_valid;
|
|
bool _seen_preset = false, _seen_host = false, _seen_port = false;
|
|
bool _seen_username = false, _seen_password = false, _seen_token = false;
|
|
bool _seen_topic = false, _seen_audience = false, _seen_filter = false;
|
|
protected:
|
|
void structure() override {
|
|
defStrict("preset", _prefs->mqtt_slot_preset[_index],
|
|
sizeof(_prefs->mqtt_slot_preset[_index]), _seen_preset);
|
|
defStrict("host", _prefs->mqtt_slot_host[_index],
|
|
sizeof(_prefs->mqtt_slot_host[_index]), _seen_host);
|
|
defStrict("port", _port, _seen_port);
|
|
defStrict("username", _prefs->mqtt_slot_username[_index],
|
|
sizeof(_prefs->mqtt_slot_username[_index]), _seen_username);
|
|
defStrict("password", _prefs->mqtt_slot_password[_index],
|
|
sizeof(_prefs->mqtt_slot_password[_index]), _seen_password);
|
|
defStrict("token", _prefs->mqtt_slot_token[_index],
|
|
sizeof(_prefs->mqtt_slot_token[_index]), _seen_token);
|
|
defStrict("topic", _prefs->mqtt_slot_topic[_index],
|
|
sizeof(_prefs->mqtt_slot_topic[_index]), _seen_topic);
|
|
defStrict("audience", _prefs->mqtt_slot_audience[_index],
|
|
sizeof(_prefs->mqtt_slot_audience[_index]), _seen_audience);
|
|
defStrict("packet_filter", _filter, _seen_filter);
|
|
}
|
|
public:
|
|
SlotPrefs(MQTTPrefs* prefs, int index, MQTTPrefsPresetValidator preset_valid)
|
|
: _prefs(prefs), _index(index), _port(prefs->mqtt_slot_port[index]),
|
|
_filter(prefs->mqtt_slot_packet_filter[index]),
|
|
_preset_valid(preset_valid) {}
|
|
void apply(bool* repaired) {
|
|
if (_port < 0 || _port > 65535) { _port = 0; *repaired = true; }
|
|
if (_filter < 0 || _filter > 65535) { _filter = 0xffff; *repaired = true; }
|
|
const char* preset = _prefs->mqtt_slot_preset[_index];
|
|
if (strcmp(preset, "none") != 0 && strcmp(preset, "custom") != 0 &&
|
|
(_preset_valid == nullptr || !_preset_valid(preset))) {
|
|
strcpy(_prefs->mqtt_slot_preset[_index], "none");
|
|
*repaired = true;
|
|
}
|
|
_prefs->mqtt_slot_port[_index] = static_cast<uint16_t>(_port);
|
|
_prefs->mqtt_slot_packet_filter[_index] = static_cast<uint16_t>(_filter);
|
|
}
|
|
};
|
|
|
|
class MqttPrefs : public ConfigSerializer {
|
|
MQTTPrefs* _prefs;
|
|
int32_t _packets_enabled, _raw_enabled, _tx_enabled, _rx_enabled, _advert_verify;
|
|
char _default_iata[sizeof(MQTTPrefs::mqtt_iata)];
|
|
bool _seen_origin = false, _seen_iata = false, _seen_packets = false;
|
|
bool _seen_raw = false, _seen_tx = false, _seen_rx = false, _seen_advert_verify = false;
|
|
bool _seen_status = false, _seen_neighbors = false, _seen_owner = false;
|
|
bool _seen_slot1 = false, _seen_slot2 = false, _seen_slot3 = false;
|
|
bool _seen_slot4 = false, _seen_slot5 = false, _seen_slot6 = false;
|
|
StatusPrefs _status;
|
|
NeighborPrefs _neighbors;
|
|
OwnerPrefs _owner;
|
|
static_assert(MQTT_PREFS_SLOT_COUNT == 6,
|
|
"MQTTPrefsSerializer slot members and keys must be updated");
|
|
SlotPrefs _slot1, _slot2, _slot3, _slot4, _slot5, _slot6;
|
|
protected:
|
|
void structure() override {
|
|
defStrict("origin", _prefs->mqtt_origin, sizeof(_prefs->mqtt_origin), _seen_origin);
|
|
defStrict("iata", _prefs->mqtt_iata, sizeof(_prefs->mqtt_iata), _seen_iata);
|
|
defStrict("packets_enabled", _packets_enabled, _seen_packets);
|
|
defStrict("raw_enabled", _raw_enabled, _seen_raw);
|
|
defStrict("tx_enabled", _tx_enabled, _seen_tx);
|
|
defStrict("rx_enabled", _rx_enabled, _seen_rx);
|
|
defStrict("advert_verify", _advert_verify, _seen_advert_verify);
|
|
defStrict("status", _status, _seen_status);
|
|
defStrict("neighbors", _neighbors, _seen_neighbors);
|
|
defStrict("owner", _owner, _seen_owner);
|
|
defStrict("slot1", _slot1, _seen_slot1);
|
|
defStrict("slot2", _slot2, _seen_slot2);
|
|
defStrict("slot3", _slot3, _seen_slot3);
|
|
defStrict("slot4", _slot4, _seen_slot4);
|
|
defStrict("slot5", _slot5, _seen_slot5);
|
|
defStrict("slot6", _slot6, _seen_slot6);
|
|
}
|
|
public:
|
|
MqttPrefs(MQTTPrefs* prefs, const MQTTPrefs* defaults,
|
|
MQTTPrefsPresetValidator preset_valid)
|
|
: _prefs(prefs), _packets_enabled(prefs->mqtt_packets_enabled),
|
|
_raw_enabled(prefs->mqtt_raw_enabled), _tx_enabled(prefs->mqtt_tx_enabled),
|
|
_rx_enabled(prefs->mqtt_rx_enabled), _advert_verify(prefs->mqtt_advert_verify),
|
|
_status(prefs), _neighbors(prefs),
|
|
_owner(prefs), _slot1(prefs, 0, preset_valid),
|
|
_slot2(prefs, 1, preset_valid), _slot3(prefs, 2, preset_valid),
|
|
_slot4(prefs, 3, preset_valid), _slot5(prefs, 4, preset_valid),
|
|
_slot6(prefs, 5, preset_valid) {
|
|
memcpy(_default_iata, defaults->mqtt_iata, sizeof(_default_iata));
|
|
if (_default_iata[0] != '\0' && !mqttIataValid(_default_iata)) {
|
|
_default_iata[0] = '\0';
|
|
}
|
|
for (char* p = _default_iata; *p; ++p) {
|
|
if (*p >= 'a' && *p <= 'z') *p = static_cast<char>(*p - ('a' - 'A'));
|
|
}
|
|
}
|
|
void apply(bool* repaired) {
|
|
if (_packets_enabled < 0 || _packets_enabled > 1) { _packets_enabled = 1; *repaired = true; }
|
|
if (_raw_enabled < 0 || _raw_enabled > 1) { _raw_enabled = 0; *repaired = true; }
|
|
if (_tx_enabled < 0 || _tx_enabled > 2) { _tx_enabled = 2; *repaired = true; }
|
|
if (_rx_enabled < 0 || _rx_enabled > 1) { _rx_enabled = 1; *repaired = true; }
|
|
if (_advert_verify < 0 || _advert_verify > 1) { _advert_verify = 0; *repaired = true; }
|
|
_prefs->mqtt_packets_enabled = static_cast<uint8_t>(_packets_enabled);
|
|
_prefs->mqtt_raw_enabled = static_cast<uint8_t>(_raw_enabled);
|
|
_prefs->mqtt_tx_enabled = static_cast<uint8_t>(_tx_enabled);
|
|
_prefs->mqtt_rx_enabled = static_cast<uint8_t>(_rx_enabled);
|
|
_prefs->mqtt_advert_verify = static_cast<uint8_t>(_advert_verify);
|
|
if (_prefs->mqtt_iata[0] != '\0') {
|
|
if (!mqttIataValid(_prefs->mqtt_iata)) {
|
|
memcpy(_prefs->mqtt_iata, _default_iata, sizeof(_default_iata));
|
|
*repaired = true;
|
|
} else {
|
|
for (char* p = _prefs->mqtt_iata; *p; ++p) {
|
|
if (*p >= 'a' && *p <= 'z') {
|
|
*p = static_cast<char>(*p - ('a' - 'A'));
|
|
*repaired = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
_status.apply(repaired);
|
|
_neighbors.apply(repaired);
|
|
_owner.apply(repaired);
|
|
_slot1.apply(repaired); _slot2.apply(repaired); _slot3.apply(repaired);
|
|
_slot4.apply(repaired); _slot5.apply(repaired); _slot6.apply(repaired);
|
|
}
|
|
};
|
|
|
|
class SnmpPrefs : public ConfigSerializer {
|
|
MQTTPrefs* _prefs;
|
|
int32_t _enabled;
|
|
bool _seen_enabled = false, _seen_community = false;
|
|
protected:
|
|
void structure() override {
|
|
defStrict("enabled", _enabled, _seen_enabled);
|
|
defStrict("community", _prefs->snmp_community,
|
|
sizeof(_prefs->snmp_community), _seen_community);
|
|
}
|
|
public:
|
|
explicit SnmpPrefs(MQTTPrefs* prefs) : _prefs(prefs), _enabled(prefs->snmp_enabled) {}
|
|
void apply(bool* repaired) {
|
|
if (_enabled < 0 || _enabled > 1) { _enabled = 0; *repaired = true; }
|
|
_prefs->snmp_enabled = static_cast<uint8_t>(_enabled);
|
|
}
|
|
};
|
|
|
|
class RadioPrefs : public ConfigSerializer {
|
|
MQTTPrefs* _prefs;
|
|
int32_t _watchdog_min;
|
|
bool _seen_watchdog = false;
|
|
protected:
|
|
void structure() override { defStrict("watchdog_min", _watchdog_min, _seen_watchdog); }
|
|
public:
|
|
explicit RadioPrefs(MQTTPrefs* prefs)
|
|
: _prefs(prefs), _watchdog_min(prefs->radio_watchdog_minutes) {}
|
|
void apply(bool* repaired) {
|
|
if (_watchdog_min < 0 || _watchdog_min > 120) { _watchdog_min = 5; *repaired = true; }
|
|
_prefs->radio_watchdog_minutes = static_cast<uint8_t>(_watchdog_min);
|
|
}
|
|
};
|
|
|
|
class AlertPrefs : public ConfigSerializer {
|
|
MQTTPrefs* _prefs;
|
|
int32_t _enabled, _wifi_minutes, _mqtt_minutes, _rate_limit_min;
|
|
bool _seen_enabled = false, _seen_psk = false, _seen_wifi = false;
|
|
bool _seen_mqtt = false, _seen_rate = false, _seen_hashtag = false, _seen_region = false;
|
|
protected:
|
|
void structure() override {
|
|
defStrict("enabled", _enabled, _seen_enabled);
|
|
defStrict("psk_hex", _prefs->alert_psk_hex, sizeof(_prefs->alert_psk_hex), _seen_psk);
|
|
defStrict("wifi_minutes", _wifi_minutes, _seen_wifi);
|
|
defStrict("mqtt_minutes", _mqtt_minutes, _seen_mqtt);
|
|
defStrict("rate_limit_min", _rate_limit_min, _seen_rate);
|
|
defStrict("hashtag", _prefs->alert_hashtag, sizeof(_prefs->alert_hashtag), _seen_hashtag);
|
|
defStrict("region", _prefs->alert_region, sizeof(_prefs->alert_region), _seen_region);
|
|
}
|
|
public:
|
|
explicit AlertPrefs(MQTTPrefs* prefs)
|
|
: _prefs(prefs), _enabled(prefs->alert_enabled),
|
|
_wifi_minutes(prefs->alert_wifi_minutes), _mqtt_minutes(prefs->alert_mqtt_minutes),
|
|
_rate_limit_min(prefs->alert_min_interval_min) {}
|
|
void apply(bool* repaired) {
|
|
if (_enabled < 0 || _enabled > 1) { _enabled = 0; *repaired = true; }
|
|
if (_wifi_minutes < 0 || _wifi_minutes > 1440) { _wifi_minutes = 30; *repaired = true; }
|
|
if (_mqtt_minutes < 0 || _mqtt_minutes > 10080) { _mqtt_minutes = 240; *repaired = true; }
|
|
if (_rate_limit_min < 60 || _rate_limit_min > 10080) { _rate_limit_min = 60; *repaired = true; }
|
|
if (_prefs->alert_psk_hex[0] != '\0') {
|
|
const size_t len = strlen(_prefs->alert_psk_hex);
|
|
bool valid_hex = len == 32;
|
|
for (size_t i = 0; valid_hex && i < len; ++i) {
|
|
const char c = _prefs->alert_psk_hex[i];
|
|
valid_hex = (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') ||
|
|
(c >= 'a' && c <= 'f');
|
|
}
|
|
if (!valid_hex) {
|
|
_prefs->alert_psk_hex[0] = '\0';
|
|
_prefs->alert_hashtag[0] = '\0';
|
|
*repaired = true;
|
|
}
|
|
}
|
|
_prefs->alert_enabled = static_cast<uint8_t>(_enabled);
|
|
_prefs->alert_wifi_minutes = static_cast<uint16_t>(_wifi_minutes);
|
|
_prefs->alert_mqtt_minutes = static_cast<uint16_t>(_mqtt_minutes);
|
|
_prefs->alert_min_interval_min = static_cast<uint16_t>(_rate_limit_min);
|
|
}
|
|
};
|
|
|
|
class DisplayPrefs : public ConfigSerializer {
|
|
MQTTPrefs* _prefs;
|
|
int32_t _timeout_s, _flip;
|
|
bool _seen_timeout = false, _seen_flip = false;
|
|
protected:
|
|
void structure() override {
|
|
defStrict("timeout_s", _timeout_s, _seen_timeout);
|
|
defStrict("flip", _flip, _seen_flip);
|
|
}
|
|
public:
|
|
explicit DisplayPrefs(MQTTPrefs* prefs)
|
|
: _prefs(prefs), _timeout_s(prefs->display_timeout_secs), _flip(prefs->display_flip) {}
|
|
void apply(bool* repaired) {
|
|
if (_timeout_s < 0 || _timeout_s > DISPLAY_TIMEOUT_MAX_SECS) {
|
|
_timeout_s = DISPLAY_TIMEOUT_DEFAULT_SECS;
|
|
*repaired = true;
|
|
}
|
|
if (_flip < 0 || _flip > 1) { _flip = 0; *repaired = true; }
|
|
_prefs->display_timeout_secs = static_cast<uint16_t>(_timeout_s);
|
|
_prefs->display_flip = static_cast<uint8_t>(_flip);
|
|
}
|
|
};
|
|
|
|
MQTTPrefs* _prefs;
|
|
int32_t _version = MQTT_PREFS_JSON_FORMAT_VERSION;
|
|
bool _seen_version = false;
|
|
bool _seen_wifi = false, _seen_time = false, _seen_mqtt = false;
|
|
bool _seen_snmp = false, _seen_radio = false, _seen_alert = false;
|
|
bool _seen_display = false;
|
|
WifiPrefs _wifi;
|
|
TimePrefs _time;
|
|
MqttPrefs _mqtt;
|
|
SnmpPrefs _snmp;
|
|
RadioPrefs _radio;
|
|
AlertPrefs _alert;
|
|
DisplayPrefs _display;
|
|
|
|
protected:
|
|
void structure() override {
|
|
defStrict("version", _version, _seen_version); // must stay first; see above
|
|
defStrict("wifi", _wifi, _seen_wifi);
|
|
defStrict("time", _time, _seen_time);
|
|
defStrict("mqtt", _mqtt, _seen_mqtt);
|
|
defStrict("snmp", _snmp, _seen_snmp);
|
|
defStrict("radio", _radio, _seen_radio);
|
|
defStrict("alert", _alert, _seen_alert);
|
|
defStrict("display", _display, _seen_display);
|
|
}
|
|
|
|
public:
|
|
explicit MQTTPrefsSerializer(
|
|
MQTTPrefs* prefs, const MQTTPrefs* repair_defaults = nullptr,
|
|
MQTTPrefsPresetValidator preset_valid = nullptr)
|
|
: _prefs(prefs), _wifi(prefs, repair_defaults ? repair_defaults : prefs),
|
|
_time(prefs, repair_defaults ? repair_defaults : prefs),
|
|
_mqtt(prefs, repair_defaults ? repair_defaults : prefs, preset_valid), _snmp(prefs),
|
|
_radio(prefs), _alert(prefs), _display(prefs) {}
|
|
|
|
bool hasSupportedVersion() const {
|
|
return _seen_version && _version == MQTT_PREFS_JSON_FORMAT_VERSION;
|
|
}
|
|
bool hasFutureVersion() const {
|
|
return _seen_version && _version > MQTT_PREFS_JSON_FORMAT_VERSION;
|
|
}
|
|
|
|
bool normalize(bool* repaired) {
|
|
if (repaired == nullptr) return false;
|
|
*repaired = false;
|
|
_wifi.apply(repaired);
|
|
_time.apply(repaired);
|
|
_mqtt.apply(repaired);
|
|
_snmp.apply(repaired);
|
|
_radio.apply(repaired);
|
|
_alert.apply(repaired);
|
|
_display.apply(repaired);
|
|
return true;
|
|
}
|
|
|
|
bool apply(bool* repaired) {
|
|
return hasSupportedVersion() && normalize(repaired);
|
|
}
|
|
};
|
|
|
|
#endif // WITH_MQTT_BRIDGE
|