Skip to content

Commit

Permalink
PowerMeter fixes (#342)
Browse files Browse the repository at this point in the history
* PowerMeter: gracefully handle non-float MQTT values

* PowerMeter: update _lastPowerMeterUpdate conservatively

update the timestampt only if the topic actually matched any
subscription and if the value could be parsed as a float.

* PowerMeter: unsubscribe before subscribing

* PowerMeter: organize subscriptions in a map

this allows for a slightly more elegant code and reduced amount of code
overall.

* PowerMeter: clean up header

* move private methods to private section of class declaration.
* remove unused member variable.
  • Loading branch information
schlimmchen authored Jul 31, 2023
1 parent 9bc334e commit 6b425d9
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 51 deletions.
14 changes: 8 additions & 6 deletions include/PowerMeter.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
#include "Configuration.h"
#include <espMqttClient.h>
#include <Arduino.h>
#include <Hoymiles.h>
#include <memory>
#include <map>
#include <list>
#include "SDM.h"
#include "sml.h"

Expand Down Expand Up @@ -37,15 +37,17 @@ class PowerMeterClass {
SOURCE_SML = 4
};
void init();
void mqtt();
void loop();
void onMqttMessage(const espMqttClientTypes::MessageProperties& properties, const char* topic, const uint8_t* payload, size_t len, size_t index, size_t total);
float getPowerTotal(bool forceUpdate = true);
uint32_t getLastPowerMeterUpdate();

private:
void mqtt();

void onMqttMessage(const espMqttClientTypes::MessageProperties& properties,
const char* topic, const uint8_t* payload, size_t len, size_t index, size_t total);

bool _verboseLogging = true;
uint32_t _interval;
uint32_t _lastPowerMeterCheck;
// Used in Power limiter for safety check
uint32_t _lastPowerMeterUpdate;
Expand All @@ -59,7 +61,7 @@ class PowerMeterClass {
float _powerMeterImport = 0.0;
float _powerMeterExport = 0.0;

bool mqttInitDone = false;
std::map<String, float*> _mqttSubscriptions;

void readPowerMeter();

Expand Down
88 changes: 43 additions & 45 deletions src/PowerMeter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,80 +20,78 @@ SoftwareSerial inputSerial;

void PowerMeterClass::init()
{
using std::placeholders::_1;
using std::placeholders::_2;
using std::placeholders::_3;
using std::placeholders::_4;
using std::placeholders::_5;
using std::placeholders::_6;

_lastPowerMeterCheck = 0;
_lastPowerMeterUpdate = 0;

for (auto const& s: _mqttSubscriptions) { MqttSettings.unsubscribe(s.first); }
_mqttSubscriptions.clear();

CONFIG_T& config = Configuration.get();

if (!config.PowerMeter_Enabled) {
return;
}

if (config.PowerMeter_Source == SOURCE_MQTT) {
if (strlen(config.PowerMeter_MqttTopicPowerMeter1) > 0) {
MqttSettings.subscribe(config.PowerMeter_MqttTopicPowerMeter1, 0, std::bind(&PowerMeterClass::onMqttMessage, this, _1, _2, _3, _4, _5, _6));
}

if (strlen(config.PowerMeter_MqttTopicPowerMeter2) > 0) {
MqttSettings.subscribe(config.PowerMeter_MqttTopicPowerMeter2, 0, std::bind(&PowerMeterClass::onMqttMessage, this, _1, _2, _3, _4, _5, _6));
}
switch(config.PowerMeter_Source) {
case SOURCE_MQTT: {
auto subscribe = [this](char const* topic, float* target) {
if (strlen(topic) == 0) { return; }
MqttSettings.subscribe(topic, 0,
std::bind(&PowerMeterClass::onMqttMessage,
this, std::placeholders::_1, std::placeholders::_2,
std::placeholders::_3, std::placeholders::_4,
std::placeholders::_5, std::placeholders::_6)
);
_mqttSubscriptions.try_emplace(topic, target);
};

if (strlen(config.PowerMeter_MqttTopicPowerMeter3) > 0) {
MqttSettings.subscribe(config.PowerMeter_MqttTopicPowerMeter3, 0, std::bind(&PowerMeterClass::onMqttMessage, this, _1, _2, _3, _4, _5, _6));
}
subscribe(config.PowerMeter_MqttTopicPowerMeter1, &_powerMeter1Power);
subscribe(config.PowerMeter_MqttTopicPowerMeter2, &_powerMeter2Power);
subscribe(config.PowerMeter_MqttTopicPowerMeter3, &_powerMeter3Power);
break;
}

if(config.PowerMeter_Source == SOURCE_SDM1PH || config.PowerMeter_Source == SOURCE_SDM3PH) {
case SOURCE_SDM1PH:
case SOURCE_SDM3PH:
sdm.begin();
}
break;

if (config.PowerMeter_Source == SOURCE_HTTP) {
case SOURCE_HTTP:
HttpPowerMeter.init();
}
break;

if (config.PowerMeter_Source == SOURCE_SML) {
case SOURCE_SML:
pinMode(SML_RX_PIN, INPUT);
inputSerial.begin(9600, SWSERIAL_8N1, SML_RX_PIN, -1, false, 128, 95);
inputSerial.enableRx(true);
inputSerial.enableTx(false);
inputSerial.flush();
break;
}

mqttInitDone = true;
}

void PowerMeterClass::onMqttMessage(const espMqttClientTypes::MessageProperties& properties, const char* topic, const uint8_t* payload, size_t len, size_t index, size_t total)
{
CONFIG_T& config = Configuration.get();
for (auto const& subscription: _mqttSubscriptions) {
if (subscription.first != topic) { continue; }

if (!config.PowerMeter_Enabled || config.PowerMeter_Source != SOURCE_MQTT) {
return;
}

if (strcmp(topic, config.PowerMeter_MqttTopicPowerMeter1) == 0) {
_powerMeter1Power = std::stof(std::string(reinterpret_cast<const char*>(payload), (unsigned int)len));
}

if (strcmp(topic, config.PowerMeter_MqttTopicPowerMeter2) == 0) {
_powerMeter2Power = std::stof(std::string(reinterpret_cast<const char*>(payload), (unsigned int)len));
}
std::string value(reinterpret_cast<const char*>(payload), len);
try {
*subscription.second = std::stof(value);
}
catch(std::invalid_argument const& e) {
MessageOutput.printf("PowerMeterClass: cannot parse payload of topic '%s' as float: %s\r\n",
topic, value.c_str());
return;
}

if (strcmp(topic, config.PowerMeter_MqttTopicPowerMeter3) == 0) {
_powerMeter3Power = std::stof(std::string(reinterpret_cast<const char*>(payload), (unsigned int)len));
}
if (_verboseLogging) {
MessageOutput.printf("PowerMeterClass: Updated from '%s', TotalPower: %5.2f\r\n",
topic, getPowerTotal());
}

if (_verboseLogging) {
MessageOutput.printf("PowerMeterClass: TotalPower: %5.2f\r\n", getPowerTotal());
_lastPowerMeterUpdate = millis();
}

_lastPowerMeterUpdate = millis();
}

float PowerMeterClass::getPowerTotal(bool forceUpdate)
Expand Down

0 comments on commit 6b425d9

Please sign in to comment.