diff --git a/include/PowerMeter.h b/include/powermeter/Controller.h similarity index 65% rename from include/PowerMeter.h rename to include/powermeter/Controller.h index 44c99d062..b25b7df95 100644 --- a/include/PowerMeter.h +++ b/include/powermeter/Controller.h @@ -1,12 +1,14 @@ // SPDX-License-Identifier: GPL-2.0-or-later #pragma once -#include "PowerMeterProvider.h" +#include #include #include #include -class PowerMeterClass { +namespace PowerMeters { + +class Controller { public: void init(Scheduler& scheduler); @@ -21,7 +23,9 @@ class PowerMeterClass { Task _loopTask; mutable std::mutex _mutex; - std::unique_ptr _upProvider = nullptr; + std::unique_ptr _upProvider = nullptr; }; -extern PowerMeterClass PowerMeter; +} // namespace PowerMeters + +extern PowerMeters::Controller PowerMeter; diff --git a/include/PowerMeterProvider.h b/include/powermeter/Provider.h similarity index 91% rename from include/PowerMeterProvider.h rename to include/powermeter/Provider.h index 0ca7bcdf5..ca8c4995b 100644 --- a/include/PowerMeterProvider.h +++ b/include/powermeter/Provider.h @@ -4,9 +4,11 @@ #include #include "Configuration.h" -class PowerMeterProvider { +namespace PowerMeters { + +class Provider { public: - virtual ~PowerMeterProvider() { } + virtual ~Provider() { } enum class Type : unsigned { MQTT = 0, @@ -29,7 +31,7 @@ class PowerMeterProvider { void mqttLoop() const; protected: - PowerMeterProvider() { + Provider() { auto const& config = Configuration.get(); _verboseLogging = config.PowerMeter.VerboseLogging; } @@ -49,3 +51,5 @@ class PowerMeterProvider { mutable uint32_t _lastMqttPublish = 0; }; + +} // namespace PowerMeters diff --git a/include/PowerMeterHttpJson.h b/include/powermeter/json/http/Provider.h similarity index 79% rename from include/PowerMeterHttpJson.h rename to include/powermeter/json/http/Provider.h index 2a9e1dd2d..c29fbb518 100644 --- a/include/PowerMeterHttpJson.h +++ b/include/powermeter/json/http/Provider.h @@ -8,19 +8,21 @@ #include #include #include -#include "HttpGetter.h" -#include "Configuration.h" -#include "PowerMeterProvider.h" +#include +#include +#include using Auth_t = HttpRequestConfig::Auth; using Unit_t = PowerMeterHttpJsonValue::Unit; -class PowerMeterHttpJson : public PowerMeterProvider { +namespace PowerMeters::Json::Http { + +class Provider : public ::PowerMeters::Provider { public: - explicit PowerMeterHttpJson(PowerMeterHttpJsonConfig const& cfg) + explicit Provider(PowerMeterHttpJsonConfig const& cfg) : _cfg(cfg) { } - ~PowerMeterHttpJson(); + ~Provider(); bool init() final; void loop() final; @@ -51,3 +53,5 @@ class PowerMeterHttpJson : public PowerMeterProvider { mutable std::mutex _pollingMutex; std::condition_variable _cv; }; + +} // namespace PowerMeters::Json::Http diff --git a/include/PowerMeterMqtt.h b/include/powermeter/mqtt/Provider.h similarity index 78% rename from include/PowerMeterMqtt.h rename to include/powermeter/mqtt/Provider.h index b12e919bc..8a99e91ea 100644 --- a/include/PowerMeterMqtt.h +++ b/include/powermeter/mqtt/Provider.h @@ -1,19 +1,21 @@ // SPDX-License-Identifier: GPL-2.0-or-later #pragma once -#include "Configuration.h" -#include "PowerMeterProvider.h" +#include +#include #include #include #include #include -class PowerMeterMqtt : public PowerMeterProvider { +namespace PowerMeters::Mqtt { + +class Provider : public ::PowerMeters::Provider { public: - explicit PowerMeterMqtt(PowerMeterMqttConfig const& cfg) + explicit Provider(PowerMeterMqttConfig const& cfg) : _cfg(cfg) { } - ~PowerMeterMqtt(); + ~Provider(); bool init() final; void loop() final { } @@ -37,3 +39,5 @@ class PowerMeterMqtt : public PowerMeterProvider { mutable std::mutex _mutex; }; + +} // namespace PowerMeters::Mqtt diff --git a/include/PowerMeterSerialSdm.h b/include/powermeter/sdm/serial/Provider.h similarity index 81% rename from include/PowerMeterSerialSdm.h rename to include/powermeter/sdm/serial/Provider.h index d676fcbbd..0019141ff 100644 --- a/include/PowerMeterSerialSdm.h +++ b/include/powermeter/sdm/serial/Provider.h @@ -5,22 +5,24 @@ #include #include #include -#include "Configuration.h" -#include "PowerMeterProvider.h" -#include "SDM.h" +#include +#include +#include -class PowerMeterSerialSdm : public PowerMeterProvider { +namespace PowerMeters::Sdm::Serial { + +class Provider : public ::PowerMeters::Provider { public: enum class Phases { One, Three }; - PowerMeterSerialSdm(Phases phases, PowerMeterSerialSdmConfig const& cfg) + Provider(Phases phases, PowerMeterSerialSdmConfig const& cfg) : _phases(phases) , _cfg(cfg) { } - ~PowerMeterSerialSdm(); + ~Provider(); bool init() final; void loop() final; @@ -58,3 +60,5 @@ class PowerMeterSerialSdm : public PowerMeterProvider { mutable std::mutex _pollingMutex; std::condition_variable _cv; }; + +} // namespace PowerMeters::Sdm::Serial diff --git a/include/PowerMeterSml.h b/include/powermeter/sml/Provider.h similarity index 91% rename from include/PowerMeterSml.h rename to include/powermeter/sml/Provider.h index 79e37ab9a..59a192ee3 100644 --- a/include/PowerMeterSml.h +++ b/include/powermeter/sml/Provider.h @@ -7,17 +7,19 @@ #include #include #include -#include "Configuration.h" -#include "PowerMeterProvider.h" -#include "sml.h" +#include +#include +#include -class PowerMeterSml : public PowerMeterProvider { +namespace PowerMeters::Sml { + +class Provider : public ::PowerMeters::Provider { public: float getPowerTotal() const final; void doMqttPublish() const final; protected: - explicit PowerMeterSml(char const* user) + explicit Provider(char const* user) : _user(user) { } void reset(); @@ -67,3 +69,5 @@ class PowerMeterSml : public PowerMeterProvider { {{0x01, 0x00, 0x02, 0x08, 0x00, 0xff}, &smlOBISWh, &_cache.energyExport, "energy export"} }; }; + +} // namespace PowerMeters::Sml diff --git a/include/PowerMeterHttpSml.h b/include/powermeter/sml/http/Provider.h similarity index 68% rename from include/PowerMeterHttpSml.h rename to include/powermeter/sml/http/Provider.h index 9c49b639c..08cd2f069 100644 --- a/include/PowerMeterHttpSml.h +++ b/include/powermeter/sml/http/Provider.h @@ -7,17 +7,19 @@ #include #include #include -#include "HttpGetter.h" -#include "Configuration.h" -#include "PowerMeterSml.h" +#include +#include +#include -class PowerMeterHttpSml : public PowerMeterSml { +namespace PowerMeters::Sml::Http { + +class Provider : public ::PowerMeters::Sml::Provider { public: - explicit PowerMeterHttpSml(PowerMeterHttpSmlConfig const& cfg) - : PowerMeterSml("PowerMeterHttpSml") + explicit Provider(PowerMeterHttpSmlConfig const& cfg) + : ::PowerMeters::Sml::Provider("PowerMeterHttpSml") , _cfg(cfg) { } - ~PowerMeterHttpSml(); + ~Provider(); bool init() final; void loop() final; @@ -43,3 +45,5 @@ class PowerMeterHttpSml : public PowerMeterSml { mutable std::mutex _pollingMutex; std::condition_variable _cv; }; + +} // namespace PowerMeters::Sml::Http diff --git a/include/PowerMeterSerialSml.h b/include/powermeter/sml/serial/Provider.h similarity index 83% rename from include/PowerMeterSerialSml.h rename to include/powermeter/sml/serial/Provider.h index abe595332..c620871ca 100644 --- a/include/PowerMeterSerialSml.h +++ b/include/powermeter/sml/serial/Provider.h @@ -1,15 +1,17 @@ // SPDX-License-Identifier: GPL-2.0-or-later #pragma once -#include "PowerMeterSml.h" #include +#include -class PowerMeterSerialSml : public PowerMeterSml { +namespace PowerMeters::Sml::Serial { + +class Provider : public ::PowerMeters::Sml::Provider { public: - PowerMeterSerialSml() - : PowerMeterSml("PowerMeterSerialSml") { } + Provider() + : ::PowerMeters::Sml::Provider("PowerMeterSerialSml") { } - ~PowerMeterSerialSml(); + ~Provider(); bool init() final; void loop() final; @@ -42,3 +44,5 @@ class PowerMeterSerialSml : public PowerMeterSml { std::unique_ptr _upSmlSerial = nullptr; }; + +} // namespace PowerMeters::Sml::Serial diff --git a/include/PowerMeterUdpSmaHomeManager.h b/include/powermeter/udp/smahm/Provider.h similarity index 79% rename from include/PowerMeterUdpSmaHomeManager.h rename to include/powermeter/udp/smahm/Provider.h index 5d4b3a8d3..3abdd1c41 100644 --- a/include/PowerMeterUdpSmaHomeManager.h +++ b/include/powermeter/udp/smahm/Provider.h @@ -5,11 +5,13 @@ #pragma once #include -#include "PowerMeterProvider.h" +#include -class PowerMeterUdpSmaHomeManager : public PowerMeterProvider { +namespace PowerMeters::Udp::SmaHM { + +class Provider : public ::PowerMeters::Provider { public: - ~PowerMeterUdpSmaHomeManager(); + ~Provider(); bool init() final; void loop() final; @@ -29,3 +31,5 @@ class PowerMeterUdpSmaHomeManager : public PowerMeterProvider { uint32_t _previousMillis = 0; uint32_t _serial = 0; }; + +} // namespace PowerMeters::Udp::SmaHM diff --git a/src/Display_Graphic.cpp b/src/Display_Graphic.cpp index ce845cec7..54273a73d 100644 --- a/src/Display_Graphic.cpp +++ b/src/Display_Graphic.cpp @@ -5,7 +5,7 @@ #include "Display_Graphic.h" #include "Datastore.h" #include "I18n.h" -#include "PowerMeter.h" +#include #include "Configuration.h" #include #include diff --git a/src/PowerLimiter.cpp b/src/PowerLimiter.cpp index fe47258c2..a1f85877d 100644 --- a/src/PowerLimiter.cpp +++ b/src/PowerLimiter.cpp @@ -4,7 +4,7 @@ */ #include "Battery.h" -#include "PowerMeter.h" +#include #include "PowerLimiter.h" #include "Configuration.h" #include "MqttSettings.h" diff --git a/src/PowerMeter.cpp b/src/PowerMeter.cpp deleted file mode 100644 index b6041e34e..000000000 --- a/src/PowerMeter.cpp +++ /dev/null @@ -1,94 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -#include "PowerMeter.h" -#include "Configuration.h" -#include "PowerMeterHttpJson.h" -#include "PowerMeterHttpSml.h" -#include "PowerMeterMqtt.h" -#include "PowerMeterSerialSdm.h" -#include "PowerMeterSerialSml.h" -#include "PowerMeterUdpSmaHomeManager.h" - -PowerMeterClass PowerMeter; - -void PowerMeterClass::init(Scheduler& scheduler) -{ - scheduler.addTask(_loopTask); - _loopTask.setCallback(std::bind(&PowerMeterClass::loop, this)); - _loopTask.setIterations(TASK_FOREVER); - _loopTask.enable(); - - updateSettings(); -} - -void PowerMeterClass::updateSettings() -{ - std::lock_guard l(_mutex); - - if (_upProvider) { _upProvider.reset(); } - - auto const& pmcfg = Configuration.get().PowerMeter; - - if (!pmcfg.Enabled) { return; } - - switch(static_cast(pmcfg.Source)) { - case PowerMeterProvider::Type::MQTT: - _upProvider = std::make_unique(pmcfg.Mqtt); - break; - case PowerMeterProvider::Type::SDM1PH: - _upProvider = std::make_unique( - PowerMeterSerialSdm::Phases::One, pmcfg.SerialSdm); - break; - case PowerMeterProvider::Type::SDM3PH: - _upProvider = std::make_unique( - PowerMeterSerialSdm::Phases::Three, pmcfg.SerialSdm); - break; - case PowerMeterProvider::Type::HTTP_JSON: - _upProvider = std::make_unique(pmcfg.HttpJson); - break; - case PowerMeterProvider::Type::SERIAL_SML: - _upProvider = std::make_unique(); - break; - case PowerMeterProvider::Type::SMAHM2: - _upProvider = std::make_unique(); - break; - case PowerMeterProvider::Type::HTTP_SML: - _upProvider = std::make_unique(pmcfg.HttpSml); - break; - } - - if (!_upProvider->init()) { - _upProvider = nullptr; - } -} - -float PowerMeterClass::getPowerTotal() const -{ - std::lock_guard l(_mutex); - if (!_upProvider) { return 0.0; } - return _upProvider->getPowerTotal(); -} - -uint32_t PowerMeterClass::getLastUpdate() const -{ - std::lock_guard l(_mutex); - if (!_upProvider) { return 0; } - return _upProvider->getLastUpdate(); -} - -bool PowerMeterClass::isDataValid() const -{ - std::lock_guard l(_mutex); - if (!_upProvider) { return false; } - return _upProvider->isDataValid(); -} - -void PowerMeterClass::loop() -{ - std::lock_guard lock(_mutex); - if (!_upProvider) { return; } - _upProvider->loop(); - - auto const& pmcfg = Configuration.get().PowerMeter; - if (pmcfg.Source == static_cast(PowerMeterProvider::Type::MQTT)) { return; } - _upProvider->mqttLoop(); -} diff --git a/src/WebApi_mqtt.cpp b/src/WebApi_mqtt.cpp index 8727dd220..cdcfb67eb 100644 --- a/src/WebApi_mqtt.cpp +++ b/src/WebApi_mqtt.cpp @@ -15,7 +15,7 @@ #include "WebApi_errors.h" #include "helper.h" #include "PowerLimiter.h" -#include "PowerMeter.h" +#include #include #include diff --git a/src/WebApi_powermeter.cpp b/src/WebApi_powermeter.cpp index 35fc04dcd..8ffbbc22b 100644 --- a/src/WebApi_powermeter.cpp +++ b/src/WebApi_powermeter.cpp @@ -9,9 +9,9 @@ #include "MqttHandleHass.h" #include "MqttSettings.h" #include "PowerLimiter.h" -#include "PowerMeter.h" -#include "PowerMeterHttpJson.h" -#include "PowerMeterHttpSml.h" +#include +#include +#include #include "WebApi.h" #include "helper.h" @@ -116,7 +116,7 @@ void WebApiPowerMeterClass::onAdminPost(AsyncWebServerRequest* request) return true; }; - if (static_cast(root["source"].as()) == PowerMeterProvider::Type::HTTP_JSON) { + if (static_cast<::PowerMeters::Provider::Type>(root["source"].as()) == ::PowerMeters::Provider::Type::HTTP_JSON) { JsonObject httpJson = root["http_json"]; JsonArray valueConfigs = httpJson["values"]; for (uint8_t i = 0; i < valueConfigs.size(); i++) { @@ -142,7 +142,7 @@ void WebApiPowerMeterClass::onAdminPost(AsyncWebServerRequest* request) } } - if (static_cast(root["source"].as()) == PowerMeterProvider::Type::HTTP_SML) { + if (static_cast<::PowerMeters::Provider::Type>(root["source"].as()) == ::PowerMeters::Provider::Type::HTTP_SML) { JsonObject httpSml = root["http_sml"]; if (!checkHttpConfig(httpSml["http_request"].as())) { return; @@ -195,10 +195,10 @@ void WebApiPowerMeterClass::onTestHttpJsonRequest(AsyncWebServerRequest* request auto powerMeterConfig = std::make_unique(); Configuration.deserializePowerMeterHttpJsonConfig(root["http_json"].as(), *powerMeterConfig); - auto upMeter = std::make_unique(*powerMeterConfig); + auto upMeter = std::make_unique<::PowerMeters::Json::Http::Provider>(*powerMeterConfig); upMeter->init(); auto res = upMeter->poll(); - using values_t = PowerMeterHttpJson::power_values_t; + using values_t = ::PowerMeters::Json::Http::Provider::power_values_t; if (std::holds_alternative(res)) { retMsg["type"] = "success"; auto vals = std::get(res); @@ -236,7 +236,7 @@ void WebApiPowerMeterClass::onTestHttpSmlRequest(AsyncWebServerRequest* request) auto powerMeterConfig = std::make_unique(); Configuration.deserializePowerMeterHttpSmlConfig(root["http_sml"].as(), *powerMeterConfig); - auto upMeter = std::make_unique(*powerMeterConfig); + auto upMeter = std::make_unique<::PowerMeters::Sml::Http::Provider>(*powerMeterConfig); upMeter->init(); auto res = upMeter->poll(); if (res.isEmpty()) { diff --git a/src/WebApi_ws_live.cpp b/src/WebApi_ws_live.cpp index 1eddcb277..95f447bae 100644 --- a/src/WebApi_ws_live.cpp +++ b/src/WebApi_ws_live.cpp @@ -9,7 +9,7 @@ #include "WebApi.h" #include "Battery.h" #include -#include "PowerMeter.h" +#include #include "defaults.h" #include #include diff --git a/src/gridcharger/huawei/Controller.cpp b/src/gridcharger/huawei/Controller.cpp index 6359b2e66..e5b9c3ea0 100644 --- a/src/gridcharger/huawei/Controller.cpp +++ b/src/gridcharger/huawei/Controller.cpp @@ -7,7 +7,7 @@ #include #include #include "MessageOutput.h" -#include "PowerMeter.h" +#include #include "PowerLimiter.h" #include "Configuration.h" diff --git a/src/main.cpp b/src/main.cpp index ba12c129d..06216a0c1 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -29,7 +29,7 @@ #include "SunPosition.h" #include "Utils.h" #include "WebApi.h" -#include "PowerMeter.h" +#include #include "PowerLimiter.h" #include "defaults.h" #include diff --git a/src/powermeter/Controller.cpp b/src/powermeter/Controller.cpp new file mode 100644 index 000000000..a5b51e60c --- /dev/null +++ b/src/powermeter/Controller.cpp @@ -0,0 +1,98 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +#include +#include +#include +#include +#include +#include +#include +#include + +PowerMeters::Controller PowerMeter; + +namespace PowerMeters { + +void Controller::init(Scheduler& scheduler) +{ + scheduler.addTask(_loopTask); + _loopTask.setCallback(std::bind(&Controller::loop, this)); + _loopTask.setIterations(TASK_FOREVER); + _loopTask.enable(); + + updateSettings(); +} + +void Controller::updateSettings() +{ + std::lock_guard l(_mutex); + + if (_upProvider) { _upProvider.reset(); } + + auto const& pmcfg = Configuration.get().PowerMeter; + + if (!pmcfg.Enabled) { return; } + + switch(static_cast(pmcfg.Source)) { + case Provider::Type::MQTT: + _upProvider = std::make_unique<::PowerMeters::Mqtt::Provider>(pmcfg.Mqtt); + break; + case Provider::Type::SDM1PH: + _upProvider = std::make_unique<::PowerMeters::Sdm::Serial::Provider>( + ::PowerMeters::Sdm::Serial::Provider::Phases::One, pmcfg.SerialSdm); + break; + case Provider::Type::SDM3PH: + _upProvider = std::make_unique<::PowerMeters::Sdm::Serial::Provider>( + ::PowerMeters::Sdm::Serial::Provider::Phases::Three, pmcfg.SerialSdm); + break; + case Provider::Type::HTTP_JSON: + _upProvider = std::make_unique<::PowerMeters::Json::Http::Provider>(pmcfg.HttpJson); + break; + case Provider::Type::SERIAL_SML: + _upProvider = std::make_unique<::PowerMeters::Sml::Serial::Provider>(); + break; + case Provider::Type::SMAHM2: + _upProvider = std::make_unique<::PowerMeters::Udp::SmaHM::Provider>(); + break; + case Provider::Type::HTTP_SML: + _upProvider = std::make_unique<::PowerMeters::Sml::Http::Provider>(pmcfg.HttpSml); + break; + } + + if (!_upProvider->init()) { + _upProvider = nullptr; + } +} + +float Controller::getPowerTotal() const +{ + std::lock_guard l(_mutex); + if (!_upProvider) { return 0.0; } + return _upProvider->getPowerTotal(); +} + +uint32_t Controller::getLastUpdate() const +{ + std::lock_guard l(_mutex); + if (!_upProvider) { return 0; } + return _upProvider->getLastUpdate(); +} + +bool Controller::isDataValid() const +{ + std::lock_guard l(_mutex); + if (!_upProvider) { return false; } + return _upProvider->isDataValid(); +} + +void Controller::loop() +{ + std::lock_guard lock(_mutex); + if (!_upProvider) { return; } + _upProvider->loop(); + + auto const& pmcfg = Configuration.get().PowerMeter; + if (pmcfg.Source == static_cast(Provider::Type::MQTT)) { return; } + _upProvider->mqttLoop(); +} + +} // namespace PowerMeters diff --git a/src/PowerMeterProvider.cpp b/src/powermeter/Provider.cpp similarity index 68% rename from src/PowerMeterProvider.cpp rename to src/powermeter/Provider.cpp index d1c7d6282..6c0bfeef7 100644 --- a/src/PowerMeterProvider.cpp +++ b/src/powermeter/Provider.cpp @@ -1,18 +1,20 @@ // SPDX-License-Identifier: GPL-2.0-or-later -#include "PowerMeterProvider.h" -#include "MqttSettings.h" +#include +#include -bool PowerMeterProvider::isDataValid() const +namespace PowerMeters { + +bool Provider::isDataValid() const { return _lastUpdate > 0 && ((millis() - _lastUpdate) < (30 * 1000)); } -void PowerMeterProvider::mqttPublish(String const& topic, float const& value) const +void Provider::mqttPublish(String const& topic, float const& value) const { MqttSettings.publish("powermeter/" + topic, String(value)); } -void PowerMeterProvider::mqttLoop() const +void Provider::mqttLoop() const { if (!MqttSettings.getConnected()) { return; } @@ -27,3 +29,5 @@ void PowerMeterProvider::mqttLoop() const _lastMqttPublish = millis(); } + +} // namespace PowerMeters diff --git a/src/PowerMeterHttpJson.cpp b/src/powermeter/json/http/Provider.cpp similarity index 81% rename from src/PowerMeterHttpJson.cpp rename to src/powermeter/json/http/Provider.cpp index 3d4431f3d..9ce349414 100644 --- a/src/PowerMeterHttpJson.cpp +++ b/src/powermeter/json/http/Provider.cpp @@ -1,14 +1,16 @@ // SPDX-License-Identifier: GPL-2.0-or-later -#include "Utils.h" -#include "PowerMeterHttpJson.h" -#include "MessageOutput.h" +#include +#include +#include #include #include -#include "mbedtls/sha256.h" +#include #include #include -PowerMeterHttpJson::~PowerMeterHttpJson() +namespace PowerMeters::Json::Http { + +Provider::~Provider() { _taskDone = false; @@ -24,7 +26,7 @@ PowerMeterHttpJson::~PowerMeterHttpJson() } } -bool PowerMeterHttpJson::init() +bool Provider::init() { for (uint8_t i = 0; i < POWERMETER_HTTP_JSON_MAX_VALUES; i++) { auto const& valueConfig = _cfg.Values[i]; @@ -43,15 +45,15 @@ bool PowerMeterHttpJson::init() continue; } - MessageOutput.printf("[PowerMeterHttpJson] Initializing HTTP getter for value %d failed:\r\n", i + 1); - MessageOutput.printf("[PowerMeterHttpJson] %s\r\n", _httpGetters[i]->getErrorText()); + MessageOutput.printf("[PowerMeters::Json::Http] Initializing HTTP getter for value %d failed:\r\n", i + 1); + MessageOutput.printf("[PowerMeters::Json::Http] %s\r\n", _httpGetters[i]->getErrorText()); return false; } return true; } -void PowerMeterHttpJson::loop() +void Provider::loop() { if (_taskHandle != nullptr) { return; } @@ -60,19 +62,19 @@ void PowerMeterHttpJson::loop() lock.unlock(); uint32_t constexpr stackSize = 3072; - xTaskCreate(PowerMeterHttpJson::pollingLoopHelper, "PM:HTTP+JSON", + xTaskCreate(Provider::pollingLoopHelper, "PM:HTTP+JSON", stackSize, this, 1/*prio*/, &_taskHandle); } -void PowerMeterHttpJson::pollingLoopHelper(void* context) +void Provider::pollingLoopHelper(void* context) { - auto pInstance = static_cast(context); + auto pInstance = static_cast(context); pInstance->pollingLoop(); pInstance->_taskDone = true; vTaskDelete(nullptr); } -void PowerMeterHttpJson::pollingLoop() +void Provider::pollingLoop() { std::unique_lock lock(_pollingMutex); @@ -93,17 +95,17 @@ void PowerMeterHttpJson::pollingLoop() lock.lock(); if (std::holds_alternative(res)) { - MessageOutput.printf("[PowerMeterHttpJson] %s\r\n", std::get(res).c_str()); + MessageOutput.printf("[PowerMeters::Json::Http] %s\r\n", std::get(res).c_str()); continue; } - MessageOutput.printf("[PowerMeterHttpJson] New total: %.2f\r\n", getPowerTotal()); + MessageOutput.printf("[PowerMeters::Json::Http] New total: %.2f\r\n", getPowerTotal()); gotUpdate(); } } -PowerMeterHttpJson::poll_result_t PowerMeterHttpJson::poll() +Provider::poll_result_t Provider::poll() { power_values_t cache; JsonDocument jsonResponse; @@ -169,7 +171,7 @@ PowerMeterHttpJson::poll_result_t PowerMeterHttpJson::poll() return cache; } -float PowerMeterHttpJson::getPowerTotal() const +float Provider::getPowerTotal() const { float sum = 0.0; std::unique_lock lock(_valueMutex); @@ -177,16 +179,18 @@ float PowerMeterHttpJson::getPowerTotal() const return sum; } -bool PowerMeterHttpJson::isDataValid() const +bool Provider::isDataValid() const { uint32_t age = millis() - getLastUpdate(); return getLastUpdate() > 0 && (age < (3 * _cfg.PollingInterval * 1000)); } -void PowerMeterHttpJson::doMqttPublish() const +void Provider::doMqttPublish() const { std::unique_lock lock(_valueMutex); mqttPublish("power1", _powerValues[0]); mqttPublish("power2", _powerValues[1]); mqttPublish("power3", _powerValues[2]); } + +} // namespace PowerMeters::Json::Http diff --git a/src/PowerMeterMqtt.cpp b/src/powermeter/mqtt/Provider.cpp similarity index 79% rename from src/PowerMeterMqtt.cpp rename to src/powermeter/mqtt/Provider.cpp index 99a51a69e..a35178cb3 100644 --- a/src/PowerMeterMqtt.cpp +++ b/src/powermeter/mqtt/Provider.cpp @@ -1,18 +1,20 @@ // SPDX-License-Identifier: GPL-2.0-or-later -#include "PowerMeterMqtt.h" -#include "MqttSettings.h" -#include "MessageOutput.h" -#include "ArduinoJson.h" -#include "Utils.h" +#include +#include +#include +#include +#include -bool PowerMeterMqtt::init() +namespace PowerMeters::Mqtt { + +bool Provider::init() { auto subscribe = [this](PowerMeterMqttValue const& val, float* targetVariable) { *targetVariable = 0; char const* topic = val.Topic; if (strlen(topic) == 0) { return; } MqttSettings.subscribe(topic, 0, - std::bind(&PowerMeterMqtt::onMessage, + std::bind(&Provider::onMessage, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5, std::placeholders::_6, @@ -28,17 +30,17 @@ bool PowerMeterMqtt::init() return _mqttSubscriptions.size() > 0; } -PowerMeterMqtt::~PowerMeterMqtt() +Provider::~Provider() { for (auto const& t: _mqttSubscriptions) { MqttSettings.unsubscribe(t); } _mqttSubscriptions.clear(); } -void PowerMeterMqtt::onMessage(PowerMeterMqtt::MsgProperties const& properties, +void Provider::onMessage(Provider::MsgProperties const& properties, char const* topic, uint8_t const* payload, size_t len, size_t index, size_t total, float* targetVariable, PowerMeterMqttValue const* cfg) { - auto extracted = Utils::getNumericValueFromMqttPayload("PowerMeterMqtt", + auto extracted = Utils::getNumericValueFromMqttPayload("PowerMeters::Mqtt", std::string(reinterpret_cast(payload), len), topic, cfg->JsonPath); @@ -66,17 +68,19 @@ void PowerMeterMqtt::onMessage(PowerMeterMqtt::MsgProperties const& properties, } if (_verboseLogging) { - MessageOutput.printf("[PowerMeterMqtt] Topic '%s': new value: %5.2f, " + MessageOutput.printf("[PowerMeters::Mqtt] Topic '%s': new value: %5.2f, " "total: %5.2f\r\n", topic, newValue, getPowerTotal()); } gotUpdate(); } -float PowerMeterMqtt::getPowerTotal() const +float Provider::getPowerTotal() const { float sum = 0.0; std::unique_lock lock(_mutex); for (auto v: _powerValues) { sum += v; } return sum; } + +} // namespace PowerMeters::Mqtt diff --git a/src/PowerMeterSerialSdm.cpp b/src/powermeter/sdm/serial/Provider.cpp similarity index 80% rename from src/PowerMeterSerialSdm.cpp rename to src/powermeter/sdm/serial/Provider.cpp index 4d271b750..0cc438468 100644 --- a/src/PowerMeterSerialSdm.cpp +++ b/src/powermeter/sdm/serial/Provider.cpp @@ -1,9 +1,11 @@ // SPDX-License-Identifier: GPL-2.0-or-later -#include "PowerMeterSerialSdm.h" -#include "PinMapping.h" -#include "MessageOutput.h" +#include +#include +#include -PowerMeterSerialSdm::~PowerMeterSerialSdm() +namespace PowerMeters::Sdm::Serial { + +Provider::~Provider() { _taskDone = false; @@ -24,15 +26,15 @@ PowerMeterSerialSdm::~PowerMeterSerialSdm() } } -bool PowerMeterSerialSdm::init() +bool Provider::init() { const PinMapping_t& pin = PinMapping.get(); - MessageOutput.printf("[PowerMeterSerialSdm] rx = %d, tx = %d, dere = %d, rxen = %d, txen = %d \r\n", + MessageOutput.printf("[PowerMeters::Sdm::Serial] rx = %d, tx = %d, dere = %d, rxen = %d, txen = %d \r\n", pin.powermeter_rx, pin.powermeter_tx, pin.powermeter_dere, pin.powermeter_rxen, pin.powermeter_txen); if (pin.powermeter_rx < 0 || pin.powermeter_tx < 0) { - MessageOutput.println("[PowerMeterSerialSdm] invalid pin config for SDM " + MessageOutput.println("[PowerMeters::Sdm::Serial] invalid pin config for SDM " "power meter (RX and TX pins must be defined)"); return false; } @@ -53,7 +55,7 @@ bool PowerMeterSerialSdm::init() return true; } -void PowerMeterSerialSdm::loop() +void Provider::loop() { if (_taskHandle != nullptr) { return; } @@ -62,23 +64,23 @@ void PowerMeterSerialSdm::loop() lock.unlock(); uint32_t constexpr stackSize = 3072; - xTaskCreate(PowerMeterSerialSdm::pollingLoopHelper, "PM:SDM", + xTaskCreate(Provider::pollingLoopHelper, "PM:SDM", stackSize, this, 1/*prio*/, &_taskHandle); } -float PowerMeterSerialSdm::getPowerTotal() const +float Provider::getPowerTotal() const { std::lock_guard l(_valueMutex); return _phase1Power + _phase2Power + _phase3Power; } -bool PowerMeterSerialSdm::isDataValid() const +bool Provider::isDataValid() const { uint32_t age = millis() - getLastUpdate(); return getLastUpdate() > 0 && (age < (3 * _cfg.PollingInterval * 1000)); } -void PowerMeterSerialSdm::doMqttPublish() const +void Provider::doMqttPublish() const { std::lock_guard l(_valueMutex); mqttPublish("power1", _phase1Power); @@ -94,15 +96,15 @@ void PowerMeterSerialSdm::doMqttPublish() const } } -void PowerMeterSerialSdm::pollingLoopHelper(void* context) +void Provider::pollingLoopHelper(void* context) { - auto pInstance = static_cast(context); + auto pInstance = static_cast(context); pInstance->pollingLoop(); pInstance->_taskDone = true; vTaskDelete(nullptr); } -bool PowerMeterSerialSdm::readValue(std::unique_lock& lock, uint16_t reg, float& targetVar) +bool Provider::readValue(std::unique_lock& lock, uint16_t reg, float& targetVar) { lock.unlock(); // reading values takes too long to keep holding the lock float val = _upSdm->readVal(reg, _cfg.Address); @@ -118,7 +120,7 @@ bool PowerMeterSerialSdm::readValue(std::unique_lock& lock, uint16_t switch (err) { case SDM_ERR_NO_ERROR: if (_verboseLogging) { - MessageOutput.printf("[PowerMeterSerialSdm]: read register %d " + MessageOutput.printf("[PowerMeters::Sdm::Serial]: read register %d " "(0x%04x) successfully\r\n", reg, reg); } @@ -126,23 +128,23 @@ bool PowerMeterSerialSdm::readValue(std::unique_lock& lock, uint16_t return true; break; case SDM_ERR_CRC_ERROR: - MessageOutput.printf("[PowerMeterSerialSdm]: CRC error " + MessageOutput.printf("[PowerMeters::Sdm::Serial]: CRC error " "while reading register %d (0x%04x)\r\n", reg, reg); break; case SDM_ERR_WRONG_BYTES: - MessageOutput.printf("[PowerMeterSerialSdm]: unexpected data in " + MessageOutput.printf("[PowerMeters::Sdm::Serial]: unexpected data in " "message while reading register %d (0x%04x)\r\n", reg, reg); break; case SDM_ERR_NOT_ENOUGHT_BYTES: - MessageOutput.printf("[PowerMeterSerialSdm]: unexpected end of " + MessageOutput.printf("[PowerMeters::Sdm::Serial]: unexpected end of " "message while reading register %d (0x%04x)\r\n", reg, reg); break; case SDM_ERR_TIMEOUT: - MessageOutput.printf("[PowerMeterSerialSdm]: timeout occured " + MessageOutput.printf("[PowerMeters::Sdm::Serial]: timeout occured " "while reading register %d (0x%04x)\r\n", reg, reg); break; default: - MessageOutput.printf("[PowerMeterSerialSdm]: unknown SDM error " + MessageOutput.printf("[PowerMeters::Sdm::Serial]: unknown SDM error " "code after reading register %d (0x%04x)\r\n", reg, reg); break; } @@ -150,7 +152,7 @@ bool PowerMeterSerialSdm::readValue(std::unique_lock& lock, uint16_t return false; } -void PowerMeterSerialSdm::pollingLoop() +void Provider::pollingLoop() { std::unique_lock lock(_pollingMutex); @@ -204,8 +206,10 @@ void PowerMeterSerialSdm::pollingLoop() _energyExport = static_cast(energyExport); } - MessageOutput.printf("[PowerMeterSerialSdm] TotalPower: %5.2f\r\n", getPowerTotal()); + MessageOutput.printf("[PowerMeters::Sdm::Serial] TotalPower: %5.2f\r\n", getPowerTotal()); gotUpdate(); } } + +} // namespace PowerMeters::Sdm::Serial diff --git a/src/PowerMeterSml.cpp b/src/powermeter/sml/Provider.cpp similarity index 86% rename from src/PowerMeterSml.cpp rename to src/powermeter/sml/Provider.cpp index c44662104..86cce573a 100644 --- a/src/PowerMeterSml.cpp +++ b/src/powermeter/sml/Provider.cpp @@ -1,15 +1,17 @@ // SPDX-License-Identifier: GPL-2.0-or-later -#include "PowerMeterSml.h" -#include "MessageOutput.h" +#include +#include -float PowerMeterSml::getPowerTotal() const +namespace PowerMeters::Sml { + +float Provider::getPowerTotal() const { std::lock_guard l(_mutex); if (_values.activePowerTotal.has_value()) { return *_values.activePowerTotal; } return 0; } -void PowerMeterSml::doMqttPublish() const +void Provider::doMqttPublish() const { #define PUB(t, m) \ if (_values.m.has_value()) { mqttPublish(t, *_values.m); } @@ -30,13 +32,13 @@ void PowerMeterSml::doMqttPublish() const #undef PUB } -void PowerMeterSml::reset() +void Provider::reset() { smlReset(); _cache = { std::nullopt }; } -void PowerMeterSml::processSmlByte(uint8_t byte) +void Provider::processSmlByte(uint8_t byte) { switch (smlState(byte)) { case SML_LISTEND: @@ -71,3 +73,5 @@ void PowerMeterSml::processSmlByte(uint8_t byte) break; } } + +} // namespace PowerMeters::Sml diff --git a/src/PowerMeterHttpSml.cpp b/src/powermeter/sml/http/Provider.cpp similarity index 74% rename from src/PowerMeterHttpSml.cpp rename to src/powermeter/sml/http/Provider.cpp index 8cfd14806..cf41572b5 100644 --- a/src/PowerMeterHttpSml.cpp +++ b/src/powermeter/sml/http/Provider.cpp @@ -1,11 +1,13 @@ // SPDX-License-Identifier: GPL-2.0-or-later -#include "PowerMeterHttpSml.h" -#include "MessageOutput.h" +#include +#include #include #include #include -PowerMeterHttpSml::~PowerMeterHttpSml() +namespace PowerMeters::Sml::Http { + +Provider::~Provider() { _taskDone = false; @@ -21,21 +23,21 @@ PowerMeterHttpSml::~PowerMeterHttpSml() } } -bool PowerMeterHttpSml::init() +bool Provider::init() { _upHttpGetter = std::make_unique(_cfg.HttpRequest); if (_upHttpGetter->init()) { return true; } - MessageOutput.printf("[PowerMeterHttpSml] Initializing HTTP getter failed:\r\n"); - MessageOutput.printf("[PowerMeterHttpSml] %s\r\n", _upHttpGetter->getErrorText()); + MessageOutput.printf("[PowerMeters::Sml::Http] Initializing HTTP getter failed:\r\n"); + MessageOutput.printf("[PowerMeters::Sml::Http] %s\r\n", _upHttpGetter->getErrorText()); _upHttpGetter = nullptr; return false; } -void PowerMeterHttpSml::loop() +void Provider::loop() { if (_taskHandle != nullptr) { return; } @@ -44,19 +46,19 @@ void PowerMeterHttpSml::loop() lock.unlock(); uint32_t constexpr stackSize = 3072; - xTaskCreate(PowerMeterHttpSml::pollingLoopHelper, "PM:HTTP+SML", + xTaskCreate(Provider::pollingLoopHelper, "PM:HTTP+SML", stackSize, this, 1/*prio*/, &_taskHandle); } -void PowerMeterHttpSml::pollingLoopHelper(void* context) +void Provider::pollingLoopHelper(void* context) { - auto pInstance = static_cast(context); + auto pInstance = static_cast(context); pInstance->pollingLoop(); pInstance->_taskDone = true; vTaskDelete(nullptr); } -void PowerMeterHttpSml::pollingLoop() +void Provider::pollingLoop() { std::unique_lock lock(_pollingMutex); @@ -77,7 +79,7 @@ void PowerMeterHttpSml::pollingLoop() lock.lock(); if (!res.isEmpty()) { - MessageOutput.printf("[PowerMeterHttpSml] %s\r\n", res.c_str()); + MessageOutput.printf("[PowerMeters::Sml::Http] %s\r\n", res.c_str()); continue; } @@ -85,13 +87,13 @@ void PowerMeterHttpSml::pollingLoop() } } -bool PowerMeterHttpSml::isDataValid() const +bool Provider::isDataValid() const { uint32_t age = millis() - getLastUpdate(); return getLastUpdate() > 0 && (age < (3 * _cfg.PollingInterval * 1000)); } -String PowerMeterHttpSml::poll() +String Provider::poll() { if (!_upHttpGetter) { return "Initialization of HTTP request failed"; @@ -111,7 +113,9 @@ String PowerMeterHttpSml::poll() processSmlByte(pStream->read()); } - PowerMeterSml::reset(); + ::PowerMeters::Sml::Provider::reset(); return ""; } + +} // namespace PowerMeters::Sml::Http diff --git a/src/PowerMeterSerialSml.cpp b/src/powermeter/sml/serial/Provider.cpp similarity index 81% rename from src/PowerMeterSerialSml.cpp rename to src/powermeter/sml/serial/Provider.cpp index a6af3ccba..a25df0d2a 100644 --- a/src/PowerMeterSerialSml.cpp +++ b/src/powermeter/sml/serial/Provider.cpp @@ -1,16 +1,18 @@ // SPDX-License-Identifier: GPL-2.0-or-later -#include "PowerMeterSerialSml.h" -#include "PinMapping.h" -#include "MessageOutput.h" +#include +#include +#include -bool PowerMeterSerialSml::init() +namespace PowerMeters::Sml::Serial { + +bool Provider::init() { const PinMapping_t& pin = PinMapping.get(); - MessageOutput.printf("[PowerMeterSerialSml] rx = %d\r\n", pin.powermeter_rx); + MessageOutput.printf("[PowerMeters::Sml::Serial] rx = %d\r\n", pin.powermeter_rx); if (pin.powermeter_rx < 0) { - MessageOutput.println("[PowerMeterSerialSml] invalid pin config " + MessageOutput.println("[PowerMeters::Sml::Serial] invalid pin config " "for serial SML power meter (RX pin must be defined)"); return false; } @@ -26,7 +28,7 @@ bool PowerMeterSerialSml::init() return true; } -void PowerMeterSerialSml::loop() +void Provider::loop() { if (_taskHandle != nullptr) { return; } @@ -35,11 +37,11 @@ void PowerMeterSerialSml::loop() lock.unlock(); uint32_t constexpr stackSize = 3072; - xTaskCreate(PowerMeterSerialSml::pollingLoopHelper, "PM:SML", + xTaskCreate(Provider::pollingLoopHelper, "PM:SML", stackSize, this, 1/*prio*/, &_taskHandle); } -PowerMeterSerialSml::~PowerMeterSerialSml() +Provider::~Provider() { _taskDone = false; @@ -58,15 +60,15 @@ PowerMeterSerialSml::~PowerMeterSerialSml() } } -void PowerMeterSerialSml::pollingLoopHelper(void* context) +void Provider::pollingLoopHelper(void* context) { - auto pInstance = static_cast(context); + auto pInstance = static_cast(context); pInstance->pollingLoop(); pInstance->_taskDone = true; vTaskDelete(nullptr); } -void PowerMeterSerialSml::pollingLoop() +void Provider::pollingLoop() { int lastAvailable = 0; uint32_t gapStartMillis = 0; @@ -115,8 +117,10 @@ void PowerMeterSerialSml::pollingLoop() lastAvailable = 0; - PowerMeterSml::reset(); + ::PowerMeters::Sml::Provider::reset(); lock.lock(); } } + +} // namespace PowerMeters::Sml::Serial diff --git a/src/PowerMeterUdpSmaHomeManager.cpp b/src/powermeter/udp/smahm/Provider.cpp similarity index 86% rename from src/PowerMeterUdpSmaHomeManager.cpp rename to src/powermeter/udp/smahm/Provider.cpp index d68275c2c..5df24801b 100644 --- a/src/PowerMeterUdpSmaHomeManager.cpp +++ b/src/powermeter/udp/smahm/Provider.cpp @@ -2,46 +2,48 @@ /* * Copyright (C) 2024 Holger-Steffen Stapf */ -#include "PowerMeterUdpSmaHomeManager.h" +#include #include #include #include "MessageOutput.h" +namespace PowerMeters::Udp::SmaHM { + static constexpr unsigned int multicastPort = 9522; // local port to listen on static const IPAddress multicastIP(239, 12, 255, 254); static WiFiUDP SMAUdp; constexpr uint32_t interval = 1000; -void PowerMeterUdpSmaHomeManager::Soutput(int kanal, int index, int art, int tarif, +void Provider::Soutput(int kanal, int index, int art, int tarif, char const* name, float value, uint32_t timestamp) { if (!_verboseLogging) { return; } - MessageOutput.printf("[PowerMeterUdpSmaHomeManager] %s = %.1f (timestamp %u)\r\n", + MessageOutput.printf("[PowerMeters::Udp::SmaHM] %s = %.1f (timestamp %u)\r\n", name, value, timestamp); } -bool PowerMeterUdpSmaHomeManager::init() +bool Provider::init() { SMAUdp.begin(multicastPort); SMAUdp.beginMulticast(multicastIP, multicastPort); return true; } -PowerMeterUdpSmaHomeManager::~PowerMeterUdpSmaHomeManager() +Provider::~Provider() { SMAUdp.stop(); } -void PowerMeterUdpSmaHomeManager::doMqttPublish() const +void Provider::doMqttPublish() const { mqttPublish("power1", _powerMeterL1); mqttPublish("power2", _powerMeterL2); mqttPublish("power3", _powerMeterL3); } -uint8_t* PowerMeterUdpSmaHomeManager::decodeGroup(uint8_t* offset, uint16_t grouplen) +uint8_t* Provider::decodeGroup(uint8_t* offset, uint16_t grouplen) { float Pbezug = 0; float BezugL1 = 0; @@ -145,7 +147,7 @@ uint8_t* PowerMeterUdpSmaHomeManager::decodeGroup(uint8_t* offset, uint16_t grou continue; } - MessageOutput.printf("[PowerMeterUdpSmaHomeManager] Skipped unknown measurement: %d %d %d %d\r\n", + MessageOutput.printf("[PowerMeters::Udp::SmaHM] Skipped unknown measurement: %d %d %d %d\r\n", kanal, index, art, tarif); offset += art; } @@ -153,7 +155,7 @@ uint8_t* PowerMeterUdpSmaHomeManager::decodeGroup(uint8_t* offset, uint16_t grou return offset; } -void PowerMeterUdpSmaHomeManager::loop() +void Provider::loop() { uint32_t currentMillis = millis(); if (currentMillis - _previousMillis < interval) { return; } @@ -166,7 +168,7 @@ void PowerMeterUdpSmaHomeManager::loop() uint8_t buffer[1024]; int rSize = SMAUdp.read(buffer, 1024); if (buffer[0] != 'S' || buffer[1] != 'M' || buffer[2] != 'A') { - MessageOutput.println("[PowerMeterUdpSmaHomeManager] Not an SMA packet?"); + MessageOutput.println("[PowerMeters::Udp::SmaHM] Not an SMA packet?"); return; } @@ -197,8 +199,10 @@ void PowerMeterUdpSmaHomeManager::loop() continue; } - MessageOutput.printf("[PowerMeterUdpSmaHomeManager] Unhandled group 0x%04x with length %d\r\n", + MessageOutput.printf("[PowerMeters::Udp::SmaHM] Unhandled group 0x%04x with length %d\r\n", grouptag, grouplen); offset += grouplen; } while (grouplen > 0 && offset + 4 < buffer + rSize); } + +} // namespace PowerMeters::Udp::SmaHM