Skip to content

Commit

Permalink
adding option to disable power limiter via mqtt
Browse files Browse the repository at this point in the history
adding option to disable power limiter via mqtt - adding missing file
  • Loading branch information
MalteSchm committed Apr 13, 2023
1 parent 9efe076 commit ee82c8c
Show file tree
Hide file tree
Showing 5 changed files with 123 additions and 1 deletion.
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,12 @@ Topics for 3 phases of a power meter is configurable. Given is an example for th
| huawei/output_temp | R | Output air temperature | °C |
| huawei/efficiency | R | Efficiency | Percentage |

## Power Limiter topics
| Topic | R / W | Description | Value / Unit |
| --------------------------------------- | ----- | ---------------------------------------------------- | -------------------------- |
| powerlimiter/cmd/disable | W | Power Limiter disable override for external PL control | 0 / 1 |
| powerlimiter/status/disabled | R | Power Limiter disable override status | 0 / 1 |

## Currently supported Inverters
* Hoymiles HM-300
* Hoymiles HM-350
Expand Down
20 changes: 20 additions & 0 deletions include/MqttHandlePowerLimiter.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once

#include "Configuration.h"
#include <espMqttClient.h>

class MqttHandlePowerLimiterClass {
public:
void init();
void loop();

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

uint32_t _lastPublishStats;
uint32_t _lastPublish;

};

extern MqttHandlePowerLimiterClass MqttHandlePowerLimiter;
3 changes: 3 additions & 0 deletions include/PowerLimiter.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,16 @@ class PowerLimiterClass {
void loop();
plStates getPowerLimiterState();
int32_t getLastRequestedPowewrLimit();
void setDisable(bool disable);
bool getDisable();

private:
uint32_t _lastCommandSent = 0;
uint32_t _lastLoop = 0;
int32_t _lastRequestedPowerLimit = 0;
uint32_t _lastLimitSetTime = 0;
plStates _plState = STATE_DISCOVER;
bool _disabled = false;

float _powerMeter1Power;
float _powerMeter2Power;
Expand Down
83 changes: 83 additions & 0 deletions src/MqttHandlePowerLimiter.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (C) 2022 Thomas Basler, Malte Schmidt and others
*/
#include "MessageOutput.h"
#include "MqttSettings.h"
#include "MqttHandlePowerLimiter.h"
#include "PowerLimiter.h"
#include <ctime>

#define TOPIC_SUB_POWER_LIMITER "disable"

MqttHandlePowerLimiterClass MqttHandlePowerLimiter;

void MqttHandlePowerLimiterClass::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;

String topic = MqttSettings.getPrefix();
MqttSettings.subscribe(String(topic + "powerlimiter/cmd/" + TOPIC_SUB_POWER_LIMITER).c_str(), 0, std::bind(&MqttHandlePowerLimiterClass::onMqttMessage, this, _1, _2, _3, _4, _5, _6));

_lastPublish = millis();

}


void MqttHandlePowerLimiterClass::loop()
{
if (!MqttSettings.getConnected() ) {
return;
}

const CONFIG_T& config = Configuration.get();

if ((millis() - _lastPublish) > (config.Mqtt_PublishInterval * 1000) ) {
MqttSettings.publish("powerlimiter/status/disabled", String(PowerLimiter.getDisable()));

yield();
_lastPublish = millis();
}
}


void MqttHandlePowerLimiterClass::onMqttMessage(const espMqttClientTypes::MessageProperties& properties, const char* topic, const uint8_t* payload, size_t len, size_t index, size_t total)
{
const CONFIG_T& config = Configuration.get();

char token_topic[MQTT_MAX_TOPIC_STRLEN + 40]; // respect all subtopics
strncpy(token_topic, topic, MQTT_MAX_TOPIC_STRLEN + 40); // convert const char* to char*

char* setting;
char* rest = &token_topic[strlen(config.Mqtt_Topic)];

strtok_r(rest, "/", &rest); // Remove "powerlimiter"
strtok_r(rest, "/", &rest); // Remove "cmd"

setting = strtok_r(rest, "/", &rest);

if (setting == NULL) {
return;
}

char* strlimit = new char[len + 1];
memcpy(strlimit, payload, len);
strlimit[len] = '\0';
float payload_val = strtof(strlimit, NULL);
delete[] strlimit;

if (!strcmp(setting, TOPIC_SUB_POWER_LIMITER)) {
MessageOutput.printf("Disable power limter: %f A\r\n", payload_val);
if(payload_val == 1) {
PowerLimiter.setDisable(true);
}
if(payload_val == 0) {
PowerLimiter.setDisable(false);
}
}
}
12 changes: 11 additions & 1 deletion src/PowerLimiter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,13 @@ void PowerLimiterClass::loop()
CONFIG_T& config = Configuration.get();

if (!config.PowerLimiter_Enabled
|| _disabled
|| !config.PowerMeter_Enabled
|| !Hoymiles.getRadio()->isIdle()
|| (millis() - _lastCommandSent) < (config.PowerLimiter_Interval * 1000)
|| (millis() - _lastLoop) < (config.PowerLimiter_Interval * 1000)) {
if (!config.PowerLimiter_Enabled)
if (!config.PowerLimiter_Enabled
|| _disabled)
_plState = STATE_DISCOVER; // ensure STATE_DISCOVER is set, if PowerLimiter will be enabled.
return;
}
Expand Down Expand Up @@ -150,6 +152,14 @@ int32_t PowerLimiterClass::getLastRequestedPowewrLimit() {
return _lastRequestedPowerLimit;
}

bool PowerLimiterClass::getDisable() {
return _disabled;
}

void PowerLimiterClass::setDisable(bool disable) {
_disabled = disable;
}

bool PowerLimiterClass::canUseDirectSolarPower()
{
CONFIG_T& config = Configuration.get();
Expand Down

0 comments on commit ee82c8c

Please sign in to comment.