From fd986c93615a9181c7a80a636212e7e4af3468cc Mon Sep 17 00:00:00 2001 From: Odyno Date: Thu, 8 May 2025 23:36:39 +0200 Subject: [PATCH 1/2] Refactor RF Configuration Management - Introduced RFConfiguration class to encapsulate RF settings and operations. - Replaced direct usage of RFConfig structure with iRFConfig instance throughout the codebase. - Updated methods for loading, saving, and managing RF configurations to use the new RFConfiguration class. - Removed obsolete RFConfig structure and related functions. - Enhanced frequency validation and management in the new RFConfiguration class. - Updated web UI handling to reflect changes in RF configuration management. - Improved logging and error handling during RF configuration updates. --- main/actuatorSomfy.cpp | 2 +- main/commonRF.cpp | 183 +++----------- main/config_RF.h | 16 +- main/gatewayPilight.cpp | 4 +- main/gatewayRF.cpp | 19 +- main/gatewayRF2.cpp | 6 +- main/gatewayRTL_433.cpp | 4 +- main/rf/RFConfiguration.cpp | 474 ++++++++++++++++++++++++++++++++++++ main/rf/RFConfiguration.h | 154 ++++++++++++ main/rf/RFReceiver.h | 15 ++ main/webUI.cpp | 50 ++-- 11 files changed, 721 insertions(+), 206 deletions(-) create mode 100644 main/rf/RFConfiguration.cpp create mode 100644 main/rf/RFConfiguration.h create mode 100644 main/rf/RFReceiver.h diff --git a/main/actuatorSomfy.cpp b/main/actuatorSomfy.cpp index e2e5293592..536d439b94 100644 --- a/main/actuatorSomfy.cpp +++ b/main/actuatorSomfy.cpp @@ -58,7 +58,7 @@ void setupSomfy() { void XtoSomfy(const char* topicOri, JsonObject& jsonData) { if (cmpToMainTopic(topicOri, subjectMQTTtoSomfy)) { THEENGS_LOG_TRACE(F("MQTTtoSomfy json data analysis" CR)); - float txFrequency = jsonData["frequency"] | RFConfig.frequency; + float txFrequency = jsonData["frequency"] | iRFConfig.getFrequency(); # ifdef ZradioCC1101 // set Receive off and Transmitt on disableCurrentReceiver(); ELECHOUSE_cc1101.SetTx(txFrequency); diff --git a/main/commonRF.cpp b/main/commonRF.cpp index 1f5b05c8bb..3bc746ee9e 100644 --- a/main/commonRF.cpp +++ b/main/commonRF.cpp @@ -29,6 +29,8 @@ # ifdef ZradioCC1101 # include # endif +# include + # include "TheengsCommon.h" # include "config_RF.h" @@ -37,10 +39,23 @@ extern rtl_433_ESP rtl_433; # endif -RFConfig_s RFConfig; -void RFConfig_init(); -void RFConfig_load(); +int currentReceiver = ACTIVE_NONE; +extern void enableActiveReceiver(); +extern void disableCurrentReceiver(); + +class ZCommonRFWrapper : public RFReceiver { +public: + ZCommonRFWrapper() : RFReceiver() {} + void enable() override { enableActiveReceiver(); } + void disable() override { disableCurrentReceiver(); } + + int getReceiverID() const override { return currentReceiver; } +}; + +ZCommonRFWrapper iRFReceiver; +RFConfiguration iRFConfig(iRFReceiver); +//TODO review void initCC1101() { # ifdef ZradioCC1101 //receiving with CC1101 // Loop on getCC1101() until it returns true and break after 10 attempts @@ -54,7 +69,7 @@ void initCC1101() { if (ELECHOUSE_cc1101.getCC1101()) { THEENGS_LOG_NOTICE(F("C1101 spi Connection OK" CR)); ELECHOUSE_cc1101.Init(); - ELECHOUSE_cc1101.SetRx(RFConfig.frequency); + ELECHOUSE_cc1101.SetRx(iRFConfig.getFrequency()); break; } else { THEENGS_LOG_ERROR(F("C1101 spi Connection Error" CR)); @@ -68,23 +83,10 @@ void initCC1101() { } void setupCommonRF() { - RFConfig_init(); - RFConfig_load(); + iRFConfig.reInit(); + iRFConfig.loadFromStorage(); } -bool validFrequency(float mhz) { - // CC1101 valid frequencies 300-348 MHZ, 387-464MHZ and 779-928MHZ. - if (mhz >= 300 && mhz <= 348) - return true; - if (mhz >= 387 && mhz <= 464) - return true; - if (mhz >= 779 && mhz <= 928) - return true; - return false; -} - -int currentReceiver = ACTIVE_NONE; - # if !defined(ZgatewayRFM69) && !defined(ZactuatorSomfy) // Check if a receiver is available bool validReceiver(int receiver) { @@ -138,13 +140,13 @@ void disableCurrentReceiver() { break; # endif default: - THEENGS_LOG_ERROR(F("ERROR: unsupported receiver %d" CR), RFConfig.activeReceiver); + THEENGS_LOG_ERROR(F("ERROR: unsupported receiver %d" CR), iRFConfig.getActiveReceiver()); } } void enableActiveReceiver() { - THEENGS_LOG_TRACE(F("enableActiveReceiver: %d" CR), RFConfig.activeReceiver); - switch (RFConfig.activeReceiver) { + THEENGS_LOG_TRACE(F("enableActiveReceiver: %d" CR), iRFConfig.getActiveReceiver()); + switch (iRFConfig.getActiveReceiver()) { # ifdef ZgatewayPilight case ACTIVE_PILIGHT: initCC1101(); @@ -155,7 +157,7 @@ void enableActiveReceiver() { # ifdef ZgatewayRF case ACTIVE_RF: initCC1101(); - enableRFReceive(RFConfig.frequency, RF_RECEIVER_GPIO, RF_EMITTER_GPIO); + enableRFReceive(iRFConfig.getFrequency(), RF_RECEIVER_GPIO, RF_EMITTER_GPIO); currentReceiver = ACTIVE_RF; break; # endif @@ -177,7 +179,7 @@ void enableActiveReceiver() { THEENGS_LOG_ERROR(F("ERROR: no receiver selected" CR)); break; default: - THEENGS_LOG_ERROR(F("ERROR: unsupported receiver %d" CR), RFConfig.activeReceiver); + THEENGS_LOG_ERROR(F("ERROR: unsupported receiver %d" CR), iRFConfig.getActiveReceiver()); } } @@ -185,10 +187,13 @@ String stateRFMeasures() { //Publish RTL_433 state StaticJsonDocument jsonBuffer; JsonObject RFdata = jsonBuffer.to(); - RFdata["active"] = RFConfig.activeReceiver; + + // load the configuration + iRFConfig.toJson(RFdata); + + // load the current state # if defined(ZradioCC1101) || defined(ZradioSX127x) - RFdata["frequency"] = RFConfig.frequency; - if (RFConfig.activeReceiver == ACTIVE_RTL) { + if (iRFConfig.getActiveReceiver() == ACTIVE_RTL) { # ifdef ZgatewayRTL_433 RFdata["rssithreshold"] = (int)getRTLrssiThreshold(); RFdata["rssi"] = (int)getRTLCurrentRSSI(); @@ -211,134 +216,12 @@ String stateRFMeasures() { return output; } -void RFConfig_fromJson(JsonObject& RFdata) { - bool success = false; - if (RFdata.containsKey("frequency") && validFrequency(RFdata["frequency"])) { - Config_update(RFdata, "frequency", RFConfig.frequency); - THEENGS_LOG_NOTICE(F("RF Receive mhz: %F" CR), RFConfig.frequency); - success = true; - } - if (RFdata.containsKey("active")) { - THEENGS_LOG_NOTICE(F("RF receiver active: %d" CR), RFConfig.activeReceiver); - Config_update(RFdata, "active", RFConfig.activeReceiver); - success = true; - } -# ifdef ZgatewayRTL_433 - if (RFdata.containsKey("rssithreshold")) { - THEENGS_LOG_NOTICE(F("RTL_433 RSSI Threshold : %d " CR), RFConfig.rssiThreshold); - Config_update(RFdata, "rssithreshold", RFConfig.rssiThreshold); - rtl_433.setRSSIThreshold(RFConfig.rssiThreshold); - success = true; - } -# if defined(RF_SX1276) || defined(RF_SX1278) - if (RFdata.containsKey("ookthreshold")) { - Config_update(RFdata, "ookthreshold", RFConfig.newOokThreshold); - THEENGS_LOG_NOTICE(F("RTL_433 ookThreshold %d" CR), RFConfig.newOokThreshold); - rtl_433.setOOKThreshold(RFConfig.newOokThreshold); - success = true; - } -# endif - if (RFdata.containsKey("status")) { - THEENGS_LOG_NOTICE(F("RF get status:" CR)); - rtl_433.getStatus(); - success = true; - } - if (!success) { - THEENGS_LOG_ERROR(F("MQTTtoRF Fail json" CR)); - } -# endif - disableCurrentReceiver(); - enableActiveReceiver(); -# ifdef ESP32 - if (RFdata.containsKey("erase") && RFdata["erase"].as()) { - // Erase config from NVS (non-volatile storage) - preferences.begin(Gateway_Short_Name, false); - if (preferences.isKey("RFConfig")) { - int result = preferences.remove("RFConfig"); - THEENGS_LOG_NOTICE(F("RF config erase result: %d" CR), result); - preferences.end(); - return; // Erase prevails on save, so skipping save - } else { - THEENGS_LOG_NOTICE(F("RF config not found" CR)); - preferences.end(); - } - } - if (RFdata.containsKey("save") && RFdata["save"].as()) { - StaticJsonDocument jsonBuffer; - JsonObject jo = jsonBuffer.to(); - jo["frequency"] = RFConfig.frequency; - jo["active"] = RFConfig.activeReceiver; -// Don't save those for now, need to be tested -# ifdef ZgatewayRTL_433 -//jo["rssithreshold"] = RFConfig.rssiThreshold; -//jo["ookthreshold"] = RFConfig.newOokThreshold; -# endif - // Save config into NVS (non-volatile storage) - String conf = ""; - serializeJson(jsonBuffer, conf); - preferences.begin(Gateway_Short_Name, false); - int result = preferences.putString("RFConfig", conf); - preferences.end(); - THEENGS_LOG_NOTICE(F("RF Config_save: %s, result: %d" CR), conf.c_str(), result); - } -# endif -} - -void RFConfig_init() { - RFConfig.frequency = RF_FREQUENCY; - RFConfig.activeReceiver = ACTIVE_RECEIVER; - RFConfig.rssiThreshold = 0; - RFConfig.newOokThreshold = 0; -} - -void RFConfig_load() { -# ifdef ESP32 - StaticJsonDocument jsonBuffer; - preferences.begin(Gateway_Short_Name, true); - if (preferences.isKey("RFConfig")) { - auto error = deserializeJson(jsonBuffer, preferences.getString("RFConfig", "{}")); - preferences.end(); - if (error) { - THEENGS_LOG_ERROR(F("RF Config deserialization failed: %s, buffer capacity: %u" CR), error.c_str(), jsonBuffer.capacity()); - return; - } - if (jsonBuffer.isNull()) { - THEENGS_LOG_WARNING(F("RF Config is null" CR)); - return; - } - JsonObject jo = jsonBuffer.as(); - RFConfig_fromJson(jo); - THEENGS_LOG_NOTICE(F("RF Config loaded" CR)); - } else { - preferences.end(); - THEENGS_LOG_NOTICE(F("RF Config not found using default" CR)); - enableActiveReceiver(); - } -# else - enableActiveReceiver(); -# endif -} - void XtoRFset(const char* topicOri, JsonObject& RFdata) { if (cmpToMainTopic(topicOri, subjectMQTTtoRFset)) { THEENGS_LOG_TRACE(F("MQTTtoRF json set" CR)); - /* - * Configuration modifications priorities: - * First `init=true` and `load=true` commands are executed (if both are present, INIT prevails on LOAD) - * Then parameters included in json are taken in account - * Finally `erase=true` and `save=true` commands are executed (if both are present, ERASE prevails on SAVE) - */ - if (RFdata.containsKey("init") && RFdata["init"].as()) { - // Restore the default (initial) configuration - RFConfig_init(); - } else if (RFdata.containsKey("load") && RFdata["load"].as()) { - // Load the saved configuration, if not initialised - RFConfig_load(); - } + iRFConfig.loadFromMessage(RFdata); - // Load config from json if available - RFConfig_fromJson(RFdata); stateRFMeasures(); } } diff --git a/main/config_RF.h b/main/config_RF.h index 44602d45d7..c166a4b005 100644 --- a/main/config_RF.h +++ b/main/config_RF.h @@ -25,11 +25,11 @@ */ #ifndef config_RF_h #define config_RF_h +#pragma once -#include "TheengsCommon.h" +#include #ifdef ZgatewayRF -extern void setupRF(); extern void RFtoX(); extern void XtoRF(const char* topicOri, const char* datacallback); extern void XtoRF(const char* topicOri, JsonObject& RFdata); @@ -137,6 +137,9 @@ const char parameters[51][4][24] = { # define DISCOVERY_TRACE_LOG(...) # endif #endif + +extern RFConfiguration iRFConfig; + /*-------------------RF topics & parameters----------------------*/ //433Mhz MQTT Subjects and keys #define subjectMQTTtoRF "/commands/MQTTto433" @@ -198,13 +201,6 @@ const char parameters[51][4][24] = { * 4 = ZgatewayRF2 */ -struct RFConfig_s { - float frequency; - int rssiThreshold; - int newOokThreshold; - int activeReceiver; -}; - #define ACTIVE_NONE -1 #define ACTIVE_RECERROR 0 #define ACTIVE_PILIGHT 1 @@ -224,8 +220,6 @@ struct RFConfig_s { # define ACTIVE_RECEIVER ACTIVE_NONE #endif -extern RFConfig_s RFConfig; - /*-------------------CC1101 DefaultTXPower----------------------*/ //Adjust the default TX-Power for sending radio if ZradioCC1101 is used. //The following settings are possible depending on the frequency band. (-30 -20 -15 -10 -6 0 5 7 10 11 12) Default is max! diff --git a/main/gatewayPilight.cpp b/main/gatewayPilight.cpp index ef9f2cd8ba..50fcbc1b99 100644 --- a/main/gatewayPilight.cpp +++ b/main/gatewayPilight.cpp @@ -218,7 +218,7 @@ void XtoPilight(const char* topicOri, JsonObject& Pilightdata) { const char* protocol = Pilightdata["protocol"]; THEENGS_LOG_NOTICE(F("MQTTtoPilight protocol: %s" CR), protocol); const char* raw = Pilightdata["raw"]; - float txFrequency = Pilightdata["frequency"] | RFConfig.frequency; + float txFrequency = Pilightdata["frequency"] | iRFConfig.getFrequency(); bool success = false; disableCurrentReceiver(); initCC1101(); @@ -307,7 +307,7 @@ extern void disablePilightReceive() { }; extern void enablePilightReceive() { - THEENGS_LOG_NOTICE(F("Switching to Pilight Receiver: %F" CR), RFConfig.frequency); + THEENGS_LOG_NOTICE(F("Switching to Pilight Receiver: %F" CR), iRFConfig.getFrequency()); THEENGS_LOG_NOTICE(F("RF_EMITTER_GPIO: %d " CR), RF_EMITTER_GPIO); THEENGS_LOG_NOTICE(F("RF_RECEIVER_GPIO: %d " CR), RF_RECEIVER_GPIO); THEENGS_LOG_TRACE(F("gatewayPilight command topic: %s%s%s" CR), mqtt_topic, gateway_name, subjectMQTTtoPilight); diff --git a/main/gatewayRF.cpp b/main/gatewayRF.cpp index 54c113b231..f0b03d832f 100644 --- a/main/gatewayRF.cpp +++ b/main/gatewayRF.cpp @@ -30,6 +30,7 @@ #ifdef ZgatewayRF # include "TheengsCommon.h" # include "config_RF.h" + # ifdef ZradioCC1101 # include extern void initCC1101(); @@ -201,12 +202,12 @@ void RFtoX() { # endif # ifdef ZradioCC1101 // set Receive off and Transmitt on - RFdata["frequency"] = RFConfig.frequency; + RFdata["frequency"] = iRFConfig.getFrequency(); # endif mySwitch.resetAvailable(); - if (!isAduplicateSignal(MQTTvalue) && MQTTvalue != 0) { // conditions to avoid duplications of RF -->MQTT + if (MQTTvalue != 0 && !isAduplicateSignal(MQTTvalue) && !iRFConfig.inBlackList(MQTTvalue) && iRFConfig.inWhiteList(MQTTvalue)) { // conditions to avoid duplications of RF -->MQTT # if defined(ZmqttDiscovery) && defined(RF_on_HAS_as_DeviceTrigger) if (SYSConfig.discovery) announceGatewayTriggerTypeToHASS(MQTTvalue); @@ -253,8 +254,8 @@ void RFtoX() { void XtoRF(const char* topicOri, const char* datacallback) { # ifdef ZradioCC1101 // set Receive off and Transmitt on disableCurrentReceiver(); - ELECHOUSE_cc1101.SetTx(RFConfig.frequency); - THEENGS_LOG_NOTICE(F("[RF] Transmit frequency: %F" CR), RFConfig.frequency); + ELECHOUSE_cc1101.SetTx(iRFConfig.getFrequency()); + THEENGS_LOG_NOTICE(F("[RF] Transmit frequency: %F" CR), iRFConfig.getFrequency()); # endif mySwitch.disableReceive(); mySwitch.enableTransmit(RF_EMITTER_GPIO); @@ -304,7 +305,7 @@ void XtoRF(const char* topicOri, const char* datacallback) { pub(subjectGTWRFtoMQTT, datacallback); // we acknowledge the sending by publishing the value to an acknowledgement topic, for the moment even if it is a signal repetition we acknowledge also } # ifdef ZradioCC1101 // set Receive on and Transmitt off - ELECHOUSE_cc1101.SetRx(RFConfig.frequency); + ELECHOUSE_cc1101.SetRx(iRFConfig.getFrequency()); mySwitch.disableTransmit(); mySwitch.enableReceive(RF_RECEIVER_GPIO); # endif @@ -328,7 +329,7 @@ void XtoRF(const char* topicOri, const char* datacallback) { * - "length": The number of bits in the RF signal (optional, default is 24). * - "repeat": The number of times the RF signal should be repeated (optional, default is RF_EMITTER_REPEAT). * - "txpower": The transmission power for CC1101 (optional, default is RF_CC1101_TXPOWER). - * - "frequency": The transmission frequency for CC1101 (optional, default is RFConfig.frequency). + * - "frequency": The transmission frequency for CC1101 (optional, default is iRFConfig.getFrequency()). * * The function logs the transmission details and acknowledges the sending by publishing the value to an acknowledgement topic. * It also restores the default repeat transmit value after sending the signal. @@ -349,7 +350,7 @@ void XtoRF(const char* topicOri, JsonObject& RFdata) { int txPower = RFdata["txpower"] | RF_CC1101_TXPOWER; ELECHOUSE_cc1101.setPA((int)txPower); THEENGS_LOG_NOTICE(F("[RF] CC1101 TX Power: %d" CR), txPower); - float txFrequency = RFdata["frequency"] | RFConfig.frequency; + float txFrequency = RFdata["frequency"] | iRFConfig.getFrequency(); ELECHOUSE_cc1101.SetTx(txFrequency); THEENGS_LOG_NOTICE(F("[RF] Transmit frequency: %F" CR), txFrequency); # endif @@ -391,14 +392,14 @@ void disableRFReceive() { * initializes the RF transmitter on the specified GPIO pin. It also sets the RF frequency * and logs the configuration details. * - * @param rfFrequency The frequency for the RF communication in MHz. Default is RFConfig.frequency. + * @param rfFrequency The frequency for the RF communication in MHz. Default is iRFConfig.getFrequency(). * @param rfReceiverGPIO The GPIO pin number for the RF receiver. Default is RF_RECEIVER_GPIO. * @param rfEmitterGPIO The GPIO pin number for the RF transmitter. Default is RF_EMITTER_GPIO. * * @note If RF_DISABLE_TRANSMIT is defined, the RF transmitter will be disabled. */ void enableRFReceive( - float rfFrequency = RFConfig.frequency, + float rfFrequency = iRFConfig.getFrequency(), int rfReceiverGPIO = RF_RECEIVER_GPIO, int rfEmitterGPIO = RF_EMITTER_GPIO) { THEENGS_LOG_NOTICE(F("[RF] Enable RF Receiver: %fMhz, RF_EMITTER_GPIO: %d, RF_RECEIVER_GPIO: %d" CR), rfFrequency, rfEmitterGPIO, rfReceiverGPIO); diff --git a/main/gatewayRF2.cpp b/main/gatewayRF2.cpp index e2286f7b45..c8cb070464 100644 --- a/main/gatewayRF2.cpp +++ b/main/gatewayRF2.cpp @@ -150,7 +150,7 @@ void XtoRF2(const char* topicOri, const char* datacallback) { int txPower = RF_CC1101_TXPOWER; ELECHOUSE_cc1101.setPA((int)txPower); THEENGS_LOG_NOTICE(F("[RF] CC1101 TX Power: %d" CR), txPower); - float txFrequency = RFConfig.frequency; + float txFrequency = iRFConfig.getFrequency(); ELECHOUSE_cc1101.SetTx(txFrequency); THEENGS_LOG_NOTICE(F("[RF] Transmit frequency: %F" CR), txFrequency); # endif @@ -252,7 +252,7 @@ void XtoRF2(const char* topicOri, const char* datacallback) { } } # ifdef ZradioCC1101 - ELECHOUSE_cc1101.SetRx(RFConfig.frequency); // set Receive on + ELECHOUSE_cc1101.SetRx(iRFConfig.getFrequency()); // set Receive on # endif enableActiveReceiver(); } @@ -273,7 +273,7 @@ void XtoRF2(const char* topicOri, JsonObject& RF2data) { // json object decoding int txPower = RF2data["txpower"] | RF_CC1101_TXPOWER; ELECHOUSE_cc1101.setPA((int)txPower); THEENGS_LOG_NOTICE(F("[RF] CC1101 TX Power: %d" CR), txPower); - float txFrequency = RF2data["frequency"] | RFConfig.frequency; + float txFrequency = RF2data["frequency"] | iRFConfig.getFrequency(); ELECHOUSE_cc1101.SetTx(txFrequency); THEENGS_LOG_NOTICE(F("[RF] Transmit frequency: %F" CR), txFrequency); # endif diff --git a/main/gatewayRTL_433.cpp b/main/gatewayRTL_433.cpp index b9eacd8936..965e889dce 100644 --- a/main/gatewayRTL_433.cpp +++ b/main/gatewayRTL_433.cpp @@ -327,8 +327,8 @@ void RTL_433Loop() { } extern void enableRTLreceive() { - THEENGS_LOG_NOTICE(F("Enable RTL_433 Receiver: %FMhz" CR), RFConfig.frequency); - rtl_433.initReceiver(RF_MODULE_RECEIVER_GPIO, RFConfig.frequency); + THEENGS_LOG_NOTICE(F("Enable RTL_433 Receiver: %FMhz" CR), iRFConfig.getFrequency()); + rtl_433.initReceiver(RF_MODULE_RECEIVER_GPIO, iRFConfig.getFrequency()); rtl_433.enableReceiver(); } diff --git a/main/rf/RFConfiguration.cpp b/main/rf/RFConfiguration.cpp new file mode 100644 index 0000000000..5edb3824b7 --- /dev/null +++ b/main/rf/RFConfiguration.cpp @@ -0,0 +1,474 @@ +#include "RFConfiguration.h" + +#include + +#ifdef ZgatewayRTL_433 +# include +extern rtl_433_ESP rtl_433; +#endif + +// Constructor +RFConfiguration::RFConfiguration(RFReceiver& receiver) : iRFReceiver(receiver), whiteList(nullptr), whiteListSize(0), blackList(nullptr), blackListSize(0) { + reInit(); +} + +// Destructor +RFConfiguration::~RFConfiguration() { + delete[] whiteList; + delete[] blackList; +} + +// Getters and Setters +float RFConfiguration::getFrequency() const { + return frequency; +} + +void RFConfiguration::setFrequency(float freq) { + frequency = freq; +} + +int RFConfiguration::getRssiThreshold() const { + return rssiThreshold; +} + +void RFConfiguration::setRssiThreshold(int threshold) { + rssiThreshold = threshold; +} + +int RFConfiguration::getNewOokThreshold() const { + return newOokThreshold; +} + +void RFConfiguration::setNewOokThreshold(int threshold) { + newOokThreshold = threshold; +} + +int RFConfiguration::getActiveReceiver() const { + return activeReceiver; +} + +void RFConfiguration::setActiveReceiver(int receiver) { + activeReceiver = receiver; +} + +bool RFConfiguration::isWhitelistIgnored() const { + return ignoreWhitelist; +} + +void RFConfiguration::setIgnoreWhitelist(bool ignore) { + ignoreWhitelist = ignore; +} + +bool RFConfiguration::isBlacklistIgnored() const { + return ignoreBlacklist; +} + +void RFConfiguration::setIgnoreBlacklist(bool ignore) { + ignoreBlacklist = ignore; +} + +// Utility methods +void RFConfiguration::clearWhiteList() { + delete[] whiteList; + whiteList = nullptr; + whiteListSize = 0; +} + +void RFConfiguration::clearBlackList() { + delete[] blackList; + blackList = nullptr; + blackListSize = 0; +} + +/** + * @brief Initializes the RFConfiguration with default values. + * + * This function sets up the RFConfiguration by assigning default values + * to its members, including frequency, active receiver, RSSI threshold, + * and new OOK threshold. It also clears and shrinks the whiteList and + * blackList containers to ensure they are empty and optimized for memory usage. + * + * @note This function should be called during the initialization phase + * to ensure the RFConfiguration is properly configured. + */ +void RFConfiguration::reInit() { + frequency = RF_FREQUENCY; + activeReceiver = ACTIVE_RECEIVER; + rssiThreshold = 0; + newOokThreshold = 0; + ignoreWhitelist = false; + ignoreBlacklist = false; + clearWhiteList(); + clearBlackList(); +} + +/** + * @brief Erases the RF configuration from non-volatile storage (NVS). + * + * This function removes the RF configuration stored in NVS. It checks if + * the configuration exists and, if so, removes it. If the configuration + * is not found, a notice is logged. + * + * @note This function is only available on ESP32 platforms. + */ +void RFConfiguration::eraseStorage() { +#ifdef ESP32 + // Erase config from NVS (non-volatile storage) + preferences.begin(Gateway_Short_Name, false); + if (preferences.isKey("RFConfig")) { + int result = preferences.remove("RFConfig"); + Log.notice(F("RF config erase result: %d" CR), result); + } else { + Log.notice(F("RF config not found" CR)); + } + preferences.end(); +#else + Log.warning(F("RF Config Erase not support with this board" CR)); +#endif +} + +/** + * @brief Saves the RF configuration to non-volatile storage (NVS). + * + * This function serializes the RF configuration data into a JSON object + * and saves it to NVS. The saved configuration includes frequency, active + * receiver, and other relevant parameters. + * + * @note This function is only available on ESP32 platforms. + * @note Ensure that the `JSON_MSG_BUFFER` is large enough to hold the + * serialized configuration data to avoid deserialization errors. + */ +void RFConfiguration::saveOnStorage() { +#ifdef ESP32 + StaticJsonDocument jsonBuffer; + JsonObject jo = jsonBuffer.to(); + toJson(jo); +# ifdef ZgatewayRTL_433 + // FROM ORIGINAL CONFIGURATION: + // > Don't save those for now, need to be tested + jo.remove("rssithreshold"); + jo.remove("ookthreshold"); +# endif + // Save config into NVS (non-volatile storage) + String conf = ""; + serializeJson(jsonBuffer, conf); + preferences.begin(Gateway_Short_Name, false); + int result = preferences.putString("RFConfig", conf); + preferences.end(); + Log.notice(F("RF Config_save: %s, result: %d" CR), conf.c_str(), result); +#else + Log.warning(F("RF Config_save not support with this board" CR)); +#endif +} + +/** + * @brief Loads the RF configuration from persistent storage and applies it. + * + * This function retrieves the RF configuration stored in non-volatile + * storage (NVS) and applies it to the RF receiver. If the configuration + * is not found, a notice is logged, and the RF receiver is enabled with + * default settings. + * + * @note This function has specific behavior for ESP32 platforms. On ESP32, + * it uses the Preferences library to access stored configuration data. + * For other platforms, it directly enables the active receiver. + */ +void RFConfiguration::loadFromStorage() { +#ifdef ESP32 + StaticJsonDocument jsonBuffer; + preferences.begin(Gateway_Short_Name, true); + if (preferences.isKey("RFConfig")) { + auto error = deserializeJson(jsonBuffer, preferences.getString("RFConfig", "{}")); + preferences.end(); + if (error) { + Log.error(F("RF Config deserialization failed: %s, buffer capacity: %u" CR), error.c_str(), jsonBuffer.capacity()); + return; + } + if (jsonBuffer.isNull()) { + Log.warning(F("RF Config is null" CR)); + return; + } + JsonObject jo = jsonBuffer.as(); + fromJson(jo); + Log.notice(F("RF Config loaded" CR)); + } else { + preferences.end(); + Log.notice(F("RF Config not found using default" CR)); + iRFReceiver.enable(); + } +#else + iRFReceiver.enable(); +#endif +} + +/** + * @brief Loads the RF configuration from a JSON object and applies it. + * + * This function takes a JSON object containing RF configuration data and + * applies it to the RF receiver. It also handles the erasure and saving of + * the configuration based on the provided JSON data. + * + * Configuration modifications priorities: + * - First `init=true` and `load=true` commands are executed (if both are present, INIT prevails on LOAD) + * - Then parameters included in json are taken in account + * - Finally `erase=true` and `save=true` commands are executed (if both are present, ERASE prevails on SAVE)* + * + * @param RFdata A reference to a JsonObject containing the RF configuration data. + * + * The following keys are supported in the JSON object: + * - "init": If true, restores the default RF configuration. + * - "load": If true, loads the saved RF configuration from storage. + * - "erase": If true, erases the RF configuration from storage. + * - "save": If true, saves the current RF configuration to storage. + * + * Logs messages to indicate the success or failure of each operation. + */ +void RFConfiguration::loadFromMessage(JsonObject& RFdata) { + if (RFdata.containsKey("init") && RFdata["init"].as()) { + // Restore the default (initial) configuration + reInit(); + } else if (RFdata.containsKey("load") && RFdata["load"].as()) { + // Load the saved configuration, if not initialised + loadFromStorage(); + } + + fromJson(RFdata); + + iRFReceiver.disable(); + iRFReceiver.enable(); + + if (RFdata.containsKey("erase") && RFdata["erase"].as()) { + eraseStorage(); + Log.notice(F("RF Config erased" CR)); + } else if (RFdata.containsKey("save") && RFdata["save"].as()) { + saveOnStorage(); + Log.notice(F("RF Config saved" CR)); + } +} + +/** + * @brief Updates the RF configuration from a JSON object. + * + * This function parses the provided JSON object and updates the RF configuration + * based on the keys and values present in the object. It supports updating + * white-list, black-list, frequency, active receiver status, and other RF-related + * parameters depending on the defined preprocessor directives. + * + * @param RFdata A reference to a JsonObject containing the RF configuration data. + * + * The following keys are supported in the JSON object: + * - "white-list": Updates the RF white-list. + * - "black-list": Updates the RF black-list. + * - "frequency": Updates the RF frequency if the value is valid. + * - "active": Updates the active receiver status. + * + * Additional keys supported when ZgatewayRTL_433 is defined: + * - "rssithreshold": Updates the RSSI threshold for RTL_433. + * - "ookthreshold": Updates the OOK threshold for RTL_433 (requires RF_SX1276 or RF_SX1278). + * - "status": Retrieves the current status of the RF configuration. + * + * Logs messages to indicate the success or failure of each update operation. + * If no valid keys are found in the JSON object, an error message is logged. + */ +void RFConfiguration::fromJson(JsonObject& RFdata) { + bool success = false; + if (RFdata.containsKey("white-list")) { + success = commandSetWhiteorBlackList(RFdata, true); + Log.notice(F("RF white-list updated" CR)); + } + if (RFdata.containsKey("black-list")) { + success = commandSetWhiteorBlackList(RFdata, false); + Log.notice(F("RF black-list updated" CR)); + } + if (RFdata.containsKey("frequency") && validFrequency(RFdata["frequency"])) { + Config_update(RFdata, "frequency", frequency); + Log.notice(F("RF Receive mhz: %F" CR), frequency); + success = true; + } + if (RFdata.containsKey("active")) { + Config_update(RFdata, "active", activeReceiver); + Log.notice(F("RF receiver active: %d" CR), activeReceiver); + success = true; + } +#ifdef ZgatewayRTL_433 + if (RFdata.containsKey("rssithreshold")) { + Log.notice(F("RTL_433 RSSI Threshold : %d " CR), rssiThreshold); + Config_update(RFdata, "rssithreshold", rssiThreshold); + rtl_433.setRSSIThreshold(rssiThreshold); + success = true; + } +# if defined(RF_SX1276) || defined(RF_SX1278) + if (RFdata.containsKey("ookthreshold")) { + Config_update(RFdata, "ookthreshold", newOokThreshold); + Log.notice(F("RTL_433 ookThreshold %d" CR), newOokThreshold); + rtl_433.setOOKThreshold(newOokThreshold); + success = true; + } +# endif + if (RFdata.containsKey("status")) { + Log.notice(F("RF get status:" CR)); + rtl_433.getStatus(); + success = true; + } + if (!success) { + Log.error(F("MQTTtoRF Fail json" CR)); + } +#endif +} + +/** + * @brief Serializes the RFConfiguration object into a JSON object. + * + * This method populates the provided JSON object with the configuration + * details of the RF module, including frequency, RSSI threshold, OOK threshold, + * active receiver status, and ignore list settings. Additionally, it includes + * the white-list and black-list vectors as nested JSON arrays. + * + * @param RFdata A reference to a JsonObject where the RF configuration data + * will be serialized. + * + * JSON Structure: + * { + * "frequency": , // Frequency value + * "rssithreshold": , // RSSI threshold value + * "ookthreshold": , // OOK threshold value + * "active": , // Active receiver status + * "ignoreWhitelist": , // Ignore white-list flag + * "ignoreBlacklist": , // Ignore black-list flag + * "white-list": [, ...], // Array of white-list values + * "black-list": [, ...] // Array of black-list values + * } + */ +void RFConfiguration::toJson(JsonObject& RFdata) { + RFdata["frequency"] = frequency; + RFdata["rssithreshold"] = rssiThreshold; + RFdata["ookthreshold"] = newOokThreshold; + RFdata["active"] = activeReceiver; + RFdata["ignoreWhitelist"] = ignoreWhitelist; + RFdata["ignoreBlacklist"] = ignoreBlacklist; + + // Add white-list vector to the JSON object + JsonArray whiteListArray = RFdata.createNestedArray("white-list"); + for (size_t i = 0; i < whiteListSize; ++i) { + whiteListArray.add(whiteList[i]); + } + // Add black-list vector to the JSON object + JsonArray blackListArray = RFdata.createNestedArray("black-list"); + for (size_t i = 0; i < blackListSize; ++i) { + blackListArray.add(blackList[i]); + } +} + +/** + * @brief Checks if a given MQTT value is present in the blacklist. + * + * This function determines whether the specified MQTT value is included + * in the blacklist defined in the If the `ignoreBlacklist` + * flag in RFConfiguration is set to true, the function will always return false, + * effectively bypassing the blacklist check. + * + * @param MQTTvalue The MQTT value to check against the blacklist. + * @return true if the MQTT value is in the blacklist and the blacklist + * check is not ignored; false otherwise. + */ +bool RFConfiguration::inBlackList(uint64_t MQTTvalue) { + if (ignoreBlacklist) { + return false; + } + for (size_t i = 0; i < blackListSize; ++i) { + if (blackList[i] == MQTTvalue) { + return true; + } + } + return false; +} + +/** + * @brief Checks if a given MQTT value is in the whitelist. + * + * This function determines whether the specified MQTT value is present + * in the whitelist. If the whitelist is disabled (via the `ignoreWhitelist` + * flag) or is empty, the function will always return true. + * + * @param MQTTvalue The MQTT value to check against the whitelist. + * @return true if the whitelist is disabled, empty, or the value is found in the whitelist. + * @return false if the value is not in the whitelist. + */ +bool RFConfiguration::inWhiteList(uint64_t MQTTvalue) { + if (ignoreWhitelist || whiteListSize == 0) { + return true; + } + for (size_t i = 0; i < whiteListSize; ++i) { + if (whiteList[i] == MQTTvalue) { + return true; + } + } + return false; +} + +/** + * @brief Validates if the given frequency is within the acceptable ranges for the CC1101 module. + * + * The CC1101 module supports the following frequency ranges: + * - 300 MHz to 348 MHz + * - 387 MHz to 464 MHz + * - 779 MHz to 928 MHz + * + * @param mhz The frequency in MHz to validate. + * @return true if the frequency is within one of the valid ranges, false otherwise. + */ +bool RFConfiguration::validFrequency(float mhz) { + // CC1101 valid frequencies 300-348 MHZ, 387-464MHZ and 779-928MHZ. + if (mhz >= 300 && mhz <= 348) + return true; + if (mhz >= 387 && mhz <= 464) + return true; + if (mhz >= 779 && mhz <= 928) + return true; + return false; +} + +/** + * @brief Updates the white or black list of RF devices. + * + * This function updates the white or black list of RF devices based on the provided JSON object. + * It iterates through the list of devices and creates or updates them in the system. + * + * @param RFdata The JSON object containing the RF data. + * @param isWhite A boolean indicating whether to update the white list (true) or black list (false). + * @return true if the update was successful, false otherwise. + */ +bool RFConfiguration::commandSetWhiteorBlackList(JsonObject& RFdata, bool isWhite) { + Log.trace(F("RF update WorB" CR)); + const char* jsonKey = isWhite ? "white-list" : "black-list"; + + int size = RFdata[jsonKey].size(); + if (size == 0) + return false; + + if (isWhite) { + clearWhiteList(); + } else { + clearBlackList(); + } + + for (int i = 0; i < size; i++) { + const char* value = RFdata[jsonKey][i]; + if (value != NULL) { + uint64_t MQTTvalue = strtoull(value, NULL, 10); + if (isWhite) { + whiteList = (uint64_t*)realloc(whiteList, (whiteListSize + 1) * sizeof(uint64_t)); + whiteList[whiteListSize++] = MQTTvalue; + Log.trace(F("[RF] White list updated with value: %s" CR), value); + } else { + blackList = (uint64_t*)realloc(blackList, (blackListSize + 1) * sizeof(uint64_t)); + blackList[blackListSize++] = MQTTvalue; + Log.trace(F("[RF] Black list updated with value: %s" CR), value); + } + } else { + Log.error(F("[RF] Error updating WorB: NULL value" CR)); + return false; + } + } + return true; +} diff --git a/main/rf/RFConfiguration.h b/main/rf/RFConfiguration.h new file mode 100644 index 0000000000..4576f5d56d --- /dev/null +++ b/main/rf/RFConfiguration.h @@ -0,0 +1,154 @@ +#ifndef RFCONFIG_H +#define RFCONFIG_H +#pragma once + +#include +#include + +class RFConfiguration { +public: + // Constructor + RFConfiguration(RFReceiver& receiver); + ~RFConfiguration(); + + // Getters and Setters + float getFrequency() const; + void setFrequency(float freq); + + int getRssiThreshold() const; + void setRssiThreshold(int threshold); + + int getNewOokThreshold() const; + void setNewOokThreshold(int threshold); + + int getActiveReceiver() const; + void setActiveReceiver(int receiver); + + bool isWhitelistIgnored() const; + void setIgnoreWhitelist(bool ignore); + + bool isBlacklistIgnored() const; + void setIgnoreBlacklist(bool ignore); + + // Utility methods + void clearWhiteList(); + void clearBlackList(); + + /** + * Initializes the structure with default values. + * + * @note This function should be called during the initialization phase + * to ensure the structure is properly configured. + */ + void reInit(); + + /** + * Erases the RF configuration from non-volatile storage (NVS). + * + * @note This function is only available on ESP32 platforms. + */ + void eraseStorage(); + + /** + * Saves the RF configuration to non-volatile storage (NVS). + * + * @note This function is only available on ESP32 platforms. + */ + void saveOnStorage(); + + /** + * Loads the RF configuration from persistent storage and applies it. + * + * @note This function has specific behavior for ESP32 platforms. On ESP32, + * it uses the Preferences library to access stored configuration data. + * For other platforms, it directly enables the active receiver. + */ + void loadFromStorage(); + + /** + * Loads the RF configuration from a JSON object and applies it. + * + * @param RFdata A reference to a JsonObject containing the RF configuration data. + * + * The following keys are supported in the JSON object: + * - "erase": If true, erases the RF configuration from storage. + * - "save": If true, saves the current RF configuration to storage. + * + * Logs messages to indicate the success or failure of each operation. + */ + void loadFromMessage(JsonObject& RFdata); + + /** + * Updates the RF configuration from a JSON object. + * + * @param RFdata A reference to a JsonObject containing the RF configuration data. + * + * The following keys are supported in the JSON object: + * - "white-list": Updates the RF white-list. + * - "black-list": Updates the RF black-list. + * - "frequency": Updates the RF frequency if the value is valid. + * - "active": Updates the active receiver status. + * + * Additional keys supported when ZgatewayRTL_433 is defined: + * - "rssithreshold": Updates the RSSI threshold for RTL_433. + * - "ookthreshold": Updates the OOK threshold for RTL_433 (requires RF_SX1276 or RF_SX1278). + * - "status": Retrieves the current status of the RF configuration. + */ + void fromJson(JsonObject& RFdata); + + /** + * Serializes the RF configuration to a JSON object. + * + * @param RFdata A reference to a JsonObject where the RF configuration will be serialized. + */ + void toJson(JsonObject& RFdata); + + /** + * Checks if a given MQTT value is present in the blacklist. + * + * @param MQTTvalue The MQTT value to check against the blacklist. + * @return true if the MQTT value is in the blacklist and the blacklist + * check is not ignored; false otherwise. + */ + bool inBlackList(uint64_t MQTTvalue); + + /** + * Checks if a given MQTT value is in the whitelist. + * + * @param MQTTvalue The MQTT value to check against the whitelist. + * @return true if the whitelist is disabled, empty, or the value is found in the whitelist. + * @return false if the value is not in the whitelist. + */ + bool inWhiteList(uint64_t MQTTvalue); + + /** + * @brief Validates if the given frequency is within the acceptable ranges for the CC1101 module. + * + * The CC1101 module supports the following frequency ranges: + * - 300 MHz to 348 MHz + * - 387 MHz to 464 MHz + * - 779 MHz to 928 MHz + * + * @param mhz The frequency in MHz to validate. + * @return true if the frequency is within one of the valid ranges, false otherwise. + */ + bool validFrequency(float mhz); + +private: + // Reference to the RFReceiver object + RFReceiver& iRFReceiver; + float frequency; + int rssiThreshold; + int newOokThreshold; + int activeReceiver; + bool ignoreWhitelist; + bool ignoreBlacklist; + uint64_t* whiteList; + size_t whiteListSize; + uint64_t* blackList; + size_t blackListSize; + + bool commandSetWhiteorBlackList(JsonObject& RFdata, bool isWhite); +}; + +#endif // RFCONFIG_H \ No newline at end of file diff --git a/main/rf/RFReceiver.h b/main/rf/RFReceiver.h new file mode 100644 index 0000000000..312a29f12c --- /dev/null +++ b/main/rf/RFReceiver.h @@ -0,0 +1,15 @@ +#ifndef RFRECEIVER_H +#define RFRECEIVER_H +#pragma once + +class RFReceiver { +public: + virtual ~RFReceiver() = default; + + // Pure virtual methods + virtual void enable() = 0; + virtual void disable() = 0; + virtual int getReceiverID() const = 0; +}; + +#endif // RFRECEIVER_H \ No newline at end of file diff --git a/main/webUI.cpp b/main/webUI.cpp index c024490555..b3011169d1 100644 --- a/main/webUI.cpp +++ b/main/webUI.cpp @@ -976,14 +976,13 @@ void handleBL() { bool update = false; if (server.hasArg("save")) { - // Default BLE AES Key if (server.hasArg("bk")) { WEBtoSYS["ble_aes"] = server.arg("bk"); update = true; } - // Split Custom BLE AES key pair string add to config + // Split Custom BLE AES key pair string add to config if (server.hasArg("kp")) { String kp = server.arg("kp"); while (kp.length() > 0) { @@ -997,7 +996,7 @@ void handleBL() { if (kp.indexOf(':') == 12) { WEBtoSYS["ble_aes_keys"][kp.substring(0, 12)] = kp.substring(13, 45); } - kp = kp.substring(kpindex+1); + kp = kp.substring(kpindex + 1); } } update = true; @@ -1013,7 +1012,7 @@ void handleBL() { } } - // Build BLE Key Pair string + // Build BLE Key Pair string std::string aeskeysstring; JsonObject root = ble_aes_keys.as(); for (JsonPair kv : root) { @@ -1204,6 +1203,8 @@ void handleLA() { } # elif defined(ZgatewayRTL_433) || defined(ZgatewayPilight) || defined(ZgatewayRF) || defined(ZgatewayRF2) || defined(ZactuatorSomfy) # include + +# include "rf/RFConfiguration.h" std::map activeReceiverOptions = { {0, "Inactive"}, # if defined(ZgatewayPilight) && !defined(ZradioSX127x) @@ -1220,16 +1221,7 @@ std::map activeReceiverOptions = { # endif }; -struct RFConfig_s { - float frequency; - int rssiThreshold; - int newOokThreshold; - int activeReceiver; -}; -extern RFConfig_s RFConfig; - -bool validFrequency(float mhz); -void RFConfig_fromJson(JsonObject& RFdata); +extern RFConfiguration iRFConfig; bool isValidReceiver(int receiverId) { // Check if the receiverId exists in the activeReceiverOptions map @@ -1257,8 +1249,9 @@ String generateActiveReceiverOptions(int currentSelection) { * T: handleRF Arg: 3, dg=0 * T: handleRF Arg: 4, ar=0 * T: handleRF Arg: 4, save= - */ - + * TODO: need a review, it's a bit strance set the config in the iRFConfig attribute and then + * setup a message and finally call the loadFromMessage + */ void handleRF() { WEBUI_TRACE_LOG(F("handleRF: uri: %s, args: %d, method: %d" CR), server.uri(), server.args(), server.method()); WEBUI_SECURE @@ -1273,9 +1266,10 @@ void handleRF() { if (server.hasArg("save")) { if (server.hasArg("rf")) { String freqStr = server.arg("rf"); - RFConfig.frequency = freqStr.toFloat(); - if (validFrequency(RFConfig.frequency)) { - WEBtoRF["frequency"] = RFConfig.frequency; + float freq = freqStr.toFloat(); + if (iRFConfig.validFrequency(freq)) { + iRFConfig.setFrequency(freq); + WEBtoRF["frequency"] = iRFConfig.getFrequency(); update = true; } else { THEENGS_LOG_WARNING(F("[WebUI] Invalid Frequency" CR)); @@ -1284,34 +1278,34 @@ void handleRF() { if (server.hasArg("ar")) { int selectedReceiver = server.arg("ar").toInt(); if (isValidReceiver(selectedReceiver)) { // Assuming isValidReceiver is a validation function - RFConfig.activeReceiver = selectedReceiver; - WEBtoRF["activereceiver"] = RFConfig.activeReceiver; + iRFConfig.setActiveReceiver(selectedReceiver); + WEBtoRF["activereceiver"] = iRFConfig.getActiveReceiver(); update = true; } else { THEENGS_LOG_WARNING(F("[WebUI] Invalid Active Receiver" CR)); } } if (server.hasArg("oo")) { - RFConfig.newOokThreshold = server.arg("oo").toInt(); - WEBtoRF["ookthreshold"] = RFConfig.newOokThreshold; + iRFConfig.setNewOokThreshold(server.arg("oo").toInt()); + WEBtoRF["ookthreshold"] = iRFConfig.getNewOokThreshold(); update = true; } if (server.hasArg("rs")) { - RFConfig.rssiThreshold = server.arg("rs").toInt(); - WEBtoRF["rssithreshold"] = RFConfig.rssiThreshold; + iRFConfig.setRssiThreshold(server.arg("rs").toInt()); + WEBtoRF["rssithreshold"] = iRFConfig.getRssiThreshold(); update = true; } if (update) { THEENGS_LOG_NOTICE(F("[WebUI] Save data" CR)); WEBtoRF["save"] = true; - RFConfig_fromJson(WEBtoRF); + iRFConfig.loadFromMessage(WEBtoRF); stateRFMeasures(); THEENGS_LOG_TRACE(F("[WebUI] RFConfig end" CR)); } } } - String activeReceiverHtml = generateActiveReceiverOptions(RFConfig.activeReceiver); + String activeReceiverHtml = generateActiveReceiverOptions(iRFConfig.getActiveReceiver()); char jsonChar[100]; serializeJson(modules, jsonChar, measureJson(modules) + 1); @@ -1322,7 +1316,7 @@ void handleRF() { response += String(script); response += String(style); - snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, config_rf_body, jsonChar, gateway_name, RFConfig.frequency, activeReceiverHtml.c_str()); + snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, config_rf_body, jsonChar, gateway_name, iRFConfig.getFrequency(), activeReceiverHtml.c_str()); response += String(buffer); snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, footer, OMG_VERSION); response += String(buffer); From 8c5fc8e77d4a9ec4e26e1b770573942c06794ca8 Mon Sep 17 00:00:00 2001 From: Odyno Date: Sun, 24 Aug 2025 14:55:27 +0200 Subject: [PATCH 2/2] Refactor RFConfiguration by removing whitelist and blacklist functionality --- main/commonRF.cpp | 5 ++ main/gatewayRF.cpp | 2 +- main/rf/RFConfiguration.cpp | 146 +----------------------------------- main/rf/RFConfiguration.h | 36 --------- 4 files changed, 8 insertions(+), 181 deletions(-) diff --git a/main/commonRF.cpp b/main/commonRF.cpp index 3bc746ee9e..4eea813d00 100644 --- a/main/commonRF.cpp +++ b/main/commonRF.cpp @@ -43,6 +43,11 @@ int currentReceiver = ACTIVE_NONE; extern void enableActiveReceiver(); extern void disableCurrentReceiver(); +// Note: this is currently just a simple wrapper used to make everything work. +// It prevents introducing external dependencies on newly added C++ structures, +// and acts as a first approach to mask the concrete implementations (rf, rf2, +// pilight, etc.). Later this can be extended or replaced by more complete driver +// abstractions without changing the rest of the system. class ZCommonRFWrapper : public RFReceiver { public: ZCommonRFWrapper() : RFReceiver() {} diff --git a/main/gatewayRF.cpp b/main/gatewayRF.cpp index f0b03d832f..f9e884f971 100644 --- a/main/gatewayRF.cpp +++ b/main/gatewayRF.cpp @@ -207,7 +207,7 @@ void RFtoX() { mySwitch.resetAvailable(); - if (MQTTvalue != 0 && !isAduplicateSignal(MQTTvalue) && !iRFConfig.inBlackList(MQTTvalue) && iRFConfig.inWhiteList(MQTTvalue)) { // conditions to avoid duplications of RF -->MQTT + if (MQTTvalue != 0 && !isAduplicateSignal(MQTTvalue)) { // conditions to avoid duplications of RF -->MQTT # if defined(ZmqttDiscovery) && defined(RF_on_HAS_as_DeviceTrigger) if (SYSConfig.discovery) announceGatewayTriggerTypeToHASS(MQTTvalue); diff --git a/main/rf/RFConfiguration.cpp b/main/rf/RFConfiguration.cpp index 5edb3824b7..9d937d46d8 100644 --- a/main/rf/RFConfiguration.cpp +++ b/main/rf/RFConfiguration.cpp @@ -8,14 +8,12 @@ extern rtl_433_ESP rtl_433; #endif // Constructor -RFConfiguration::RFConfiguration(RFReceiver& receiver) : iRFReceiver(receiver), whiteList(nullptr), whiteListSize(0), blackList(nullptr), blackListSize(0) { +RFConfiguration::RFConfiguration(RFReceiver& receiver) : iRFReceiver(receiver) { reInit(); } // Destructor RFConfiguration::~RFConfiguration() { - delete[] whiteList; - delete[] blackList; } // Getters and Setters @@ -51,35 +49,6 @@ void RFConfiguration::setActiveReceiver(int receiver) { activeReceiver = receiver; } -bool RFConfiguration::isWhitelistIgnored() const { - return ignoreWhitelist; -} - -void RFConfiguration::setIgnoreWhitelist(bool ignore) { - ignoreWhitelist = ignore; -} - -bool RFConfiguration::isBlacklistIgnored() const { - return ignoreBlacklist; -} - -void RFConfiguration::setIgnoreBlacklist(bool ignore) { - ignoreBlacklist = ignore; -} - -// Utility methods -void RFConfiguration::clearWhiteList() { - delete[] whiteList; - whiteList = nullptr; - whiteListSize = 0; -} - -void RFConfiguration::clearBlackList() { - delete[] blackList; - blackList = nullptr; - blackListSize = 0; -} - /** * @brief Initializes the RFConfiguration with default values. * @@ -96,10 +65,6 @@ void RFConfiguration::reInit() { activeReceiver = ACTIVE_RECEIVER; rssiThreshold = 0; newOokThreshold = 0; - ignoreWhitelist = false; - ignoreBlacklist = false; - clearWhiteList(); - clearBlackList(); } /** @@ -272,14 +237,7 @@ void RFConfiguration::loadFromMessage(JsonObject& RFdata) { */ void RFConfiguration::fromJson(JsonObject& RFdata) { bool success = false; - if (RFdata.containsKey("white-list")) { - success = commandSetWhiteorBlackList(RFdata, true); - Log.notice(F("RF white-list updated" CR)); - } - if (RFdata.containsKey("black-list")) { - success = commandSetWhiteorBlackList(RFdata, false); - Log.notice(F("RF black-list updated" CR)); - } + if (RFdata.containsKey("frequency") && validFrequency(RFdata["frequency"])) { Config_update(RFdata, "frequency", frequency); Log.notice(F("RF Receive mhz: %F" CR), frequency); @@ -344,66 +302,11 @@ void RFConfiguration::toJson(JsonObject& RFdata) { RFdata["rssithreshold"] = rssiThreshold; RFdata["ookthreshold"] = newOokThreshold; RFdata["active"] = activeReceiver; - RFdata["ignoreWhitelist"] = ignoreWhitelist; - RFdata["ignoreBlacklist"] = ignoreBlacklist; // Add white-list vector to the JSON object JsonArray whiteListArray = RFdata.createNestedArray("white-list"); - for (size_t i = 0; i < whiteListSize; ++i) { - whiteListArray.add(whiteList[i]); - } // Add black-list vector to the JSON object JsonArray blackListArray = RFdata.createNestedArray("black-list"); - for (size_t i = 0; i < blackListSize; ++i) { - blackListArray.add(blackList[i]); - } -} - -/** - * @brief Checks if a given MQTT value is present in the blacklist. - * - * This function determines whether the specified MQTT value is included - * in the blacklist defined in the If the `ignoreBlacklist` - * flag in RFConfiguration is set to true, the function will always return false, - * effectively bypassing the blacklist check. - * - * @param MQTTvalue The MQTT value to check against the blacklist. - * @return true if the MQTT value is in the blacklist and the blacklist - * check is not ignored; false otherwise. - */ -bool RFConfiguration::inBlackList(uint64_t MQTTvalue) { - if (ignoreBlacklist) { - return false; - } - for (size_t i = 0; i < blackListSize; ++i) { - if (blackList[i] == MQTTvalue) { - return true; - } - } - return false; -} - -/** - * @brief Checks if a given MQTT value is in the whitelist. - * - * This function determines whether the specified MQTT value is present - * in the whitelist. If the whitelist is disabled (via the `ignoreWhitelist` - * flag) or is empty, the function will always return true. - * - * @param MQTTvalue The MQTT value to check against the whitelist. - * @return true if the whitelist is disabled, empty, or the value is found in the whitelist. - * @return false if the value is not in the whitelist. - */ -bool RFConfiguration::inWhiteList(uint64_t MQTTvalue) { - if (ignoreWhitelist || whiteListSize == 0) { - return true; - } - for (size_t i = 0; i < whiteListSize; ++i) { - if (whiteList[i] == MQTTvalue) { - return true; - } - } - return false; } /** @@ -427,48 +330,3 @@ bool RFConfiguration::validFrequency(float mhz) { return true; return false; } - -/** - * @brief Updates the white or black list of RF devices. - * - * This function updates the white or black list of RF devices based on the provided JSON object. - * It iterates through the list of devices and creates or updates them in the system. - * - * @param RFdata The JSON object containing the RF data. - * @param isWhite A boolean indicating whether to update the white list (true) or black list (false). - * @return true if the update was successful, false otherwise. - */ -bool RFConfiguration::commandSetWhiteorBlackList(JsonObject& RFdata, bool isWhite) { - Log.trace(F("RF update WorB" CR)); - const char* jsonKey = isWhite ? "white-list" : "black-list"; - - int size = RFdata[jsonKey].size(); - if (size == 0) - return false; - - if (isWhite) { - clearWhiteList(); - } else { - clearBlackList(); - } - - for (int i = 0; i < size; i++) { - const char* value = RFdata[jsonKey][i]; - if (value != NULL) { - uint64_t MQTTvalue = strtoull(value, NULL, 10); - if (isWhite) { - whiteList = (uint64_t*)realloc(whiteList, (whiteListSize + 1) * sizeof(uint64_t)); - whiteList[whiteListSize++] = MQTTvalue; - Log.trace(F("[RF] White list updated with value: %s" CR), value); - } else { - blackList = (uint64_t*)realloc(blackList, (blackListSize + 1) * sizeof(uint64_t)); - blackList[blackListSize++] = MQTTvalue; - Log.trace(F("[RF] Black list updated with value: %s" CR), value); - } - } else { - Log.error(F("[RF] Error updating WorB: NULL value" CR)); - return false; - } - } - return true; -} diff --git a/main/rf/RFConfiguration.h b/main/rf/RFConfiguration.h index 4576f5d56d..71b9de29c4 100644 --- a/main/rf/RFConfiguration.h +++ b/main/rf/RFConfiguration.h @@ -24,16 +24,6 @@ class RFConfiguration { int getActiveReceiver() const; void setActiveReceiver(int receiver); - bool isWhitelistIgnored() const; - void setIgnoreWhitelist(bool ignore); - - bool isBlacklistIgnored() const; - void setIgnoreBlacklist(bool ignore); - - // Utility methods - void clearWhiteList(); - void clearBlackList(); - /** * Initializes the structure with default values. * @@ -103,24 +93,6 @@ class RFConfiguration { */ void toJson(JsonObject& RFdata); - /** - * Checks if a given MQTT value is present in the blacklist. - * - * @param MQTTvalue The MQTT value to check against the blacklist. - * @return true if the MQTT value is in the blacklist and the blacklist - * check is not ignored; false otherwise. - */ - bool inBlackList(uint64_t MQTTvalue); - - /** - * Checks if a given MQTT value is in the whitelist. - * - * @param MQTTvalue The MQTT value to check against the whitelist. - * @return true if the whitelist is disabled, empty, or the value is found in the whitelist. - * @return false if the value is not in the whitelist. - */ - bool inWhiteList(uint64_t MQTTvalue); - /** * @brief Validates if the given frequency is within the acceptable ranges for the CC1101 module. * @@ -141,14 +113,6 @@ class RFConfiguration { int rssiThreshold; int newOokThreshold; int activeReceiver; - bool ignoreWhitelist; - bool ignoreBlacklist; - uint64_t* whiteList; - size_t whiteListSize; - uint64_t* blackList; - size_t blackListSize; - - bool commandSetWhiteorBlackList(JsonObject& RFdata, bool isWhite); }; #endif // RFCONFIG_H \ No newline at end of file