Skip to content

Commit

Permalink
optimize DPL thresholds MQTT integration
Browse files Browse the repository at this point in the history
* fix logic in HomeAssistent handler
* also publish voltage thresholds (not just SoC thresholds)
* do not publish irrelevant thresholds to MQTT. if the inverter is
  solar-powered, no thresholds are effectively in use by the DPL and it
  therefore makes no sense to publish them to the broker. similarly, if
  no battery interface is enabled or the SoC values are set to be
  ignored, the SoC thresholds are effectively not in use and will not be
  published to the broker.
* make HA auto-discovery expire. this makes auto-dicovered items
  disappear from Home Assistent if their value is no longer updated.
  changes to settings which cause other thresholds to be relevant will
  then be reflected in Home Assistent even if some thresholds are no
  longer maintaned in MQTT.
* force HA update when related settings change enabling VE.Direct shall
  trigger an update since solar passthrough thresholds become relevant.
  similarly, enabling the battery interface makes SoC thresholds become
  relevant. there are more settings in the power limiter that also
  influence the auto-discoverable items.
* break very long lines
  • Loading branch information
schlimmchen committed Mar 10, 2024
1 parent fba5c02 commit 784e369
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 20 deletions.
33 changes: 24 additions & 9 deletions src/MqttHandlePowerLimiter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,18 +67,33 @@ void MqttHandlePowerLimiterClass::loop()

if (!MqttSettings.getConnected() ) { return; }

if ((millis() - _lastPublish) > (config.Mqtt.PublishInterval * 1000) ) {
auto val = static_cast<unsigned>(PowerLimiter.getMode());
MqttSettings.publish("powerlimiter/status/mode", String(val));
MqttSettings.publish("powerlimiter/status/threshold/soc/start", String(config.PowerLimiter.BatterySocStartThreshold));
MqttSettings.publish("powerlimiter/status/threshold/soc/stop", String(config.PowerLimiter.BatterySocStopThreshold));
MqttSettings.publish("powerlimiter/status/threshold/soc/full_solar_passthrough", String(config.PowerLimiter.FullSolarPassThroughSoc));
MqttSettings.publish("powerlimiter/status/threshold/voltage/start", String(config.PowerLimiter.VoltageStartThreshold));
MqttSettings.publish("powerlimiter/status/threshold/voltage/stop", String(config.PowerLimiter.VoltageStopThreshold));
if ((millis() - _lastPublish) < (config.Mqtt.PublishInterval * 1000)) {
return;
}

_lastPublish = millis();

auto val = static_cast<unsigned>(PowerLimiter.getMode());
MqttSettings.publish("powerlimiter/status/mode", String(val));

// no thresholds are relevant for setups without a battery
if (config.PowerLimiter.IsInverterSolarPowered) { return; }

MqttSettings.publish("powerlimiter/status/threshold/voltage/start", String(config.PowerLimiter.VoltageStartThreshold));
MqttSettings.publish("powerlimiter/status/threshold/voltage/stop", String(config.PowerLimiter.VoltageStopThreshold));

if (config.Vedirect.Enabled) {
MqttSettings.publish("powerlimiter/status/threshold/voltage/full_solar_passthrough_start", String(config.PowerLimiter.FullSolarPassThroughStartVoltage));
MqttSettings.publish("powerlimiter/status/threshold/voltage/full_solar_passthrough_stop", String(config.PowerLimiter.FullSolarPassThroughStopVoltage));
}

_lastPublish = millis();
if (!config.Battery.Enabled || config.PowerLimiter.IgnoreSoc) { return; }

MqttSettings.publish("powerlimiter/status/threshold/soc/start", String(config.PowerLimiter.BatterySocStartThreshold));
MqttSettings.publish("powerlimiter/status/threshold/soc/stop", String(config.PowerLimiter.BatterySocStopThreshold));

if (config.Vedirect.Enabled) {
MqttSettings.publish("powerlimiter/status/threshold/soc/full_solar_passthrough", String(config.PowerLimiter.FullSolarPassThroughSoc));
}
}

Expand Down
53 changes: 46 additions & 7 deletions src/MqttHandlePowerLimiterHass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,21 +46,55 @@ void MqttHandlePowerLimiterHassClass::forceUpdate()

void MqttHandlePowerLimiterHassClass::publishConfig()
{
if (!Configuration.get().Mqtt.Hass.Enabled) {
auto const& config = Configuration.get();

if (!config.Mqtt.Hass.Enabled) {
return;
}

if (!MqttSettings.getConnected()) {
return;
}

if (!Configuration.get().PowerLimiter.Enabled) {
publishSelect("DPL Mode", "mdi:gauge", "config", "mode", "mode");
publishNumber("DPL battery SoC start threshold", "mdi:battery-charging", "config", "threshold/soc/start", "threshold/soc/start", "%", 0, 100);
publishNumber("DPL battery SoC stop threshold", "mdi:battery-charging", "config", "threshold/soc/stop", "threshold/soc/stop", "%", 0, 100);
if (!config.PowerLimiter.Enabled) {
return;
}

publishSelect("DPL Mode", "mdi:gauge", "config", "mode", "mode");

if (config.PowerLimiter.IsInverterSolarPowered) {
return;
}

// as this project revolves around Hoymiles inverters, 16 - 60 V is a reasonable voltage range
publishNumber("DPL battery voltage start threshold", "mdi:battery-charging",
"config", "threshold/voltage/start", "threshold/voltage/start", "V", 16, 60);
publishNumber("DPL battery voltage stop threshold", "mdi:battery-charging",
"config", "threshold/voltage/stop", "threshold/voltage/stop", "V", 16, 60);

if (config.Vedirect.Enabled) {
publishNumber("DPL full solar passthrough start voltage",
"mdi:transmission-tower-import", "config",
"threshold/voltage/full_solar_passthrough_start",
"threshold/voltage/full_solar_passthrough_start", "V", 16, 60);
publishNumber("DPL full solar passthrough stop voltage",
"mdi:transmission-tower-import", "config",
"threshold/voltage/full_solar_passthrough_stop",
"threshold/voltage/full_solar_passthrough_stop", "V", 16, 60);
}
if (!Configuration.get().Vedirect.Enabled) {
publishNumber("DPL full solar passthrough SoC", "mdi:transmission-tower-import", "config", "threshold/soc/full_solar_passthrough", "threshold/soc/full_solar_passthrough", "%", 0, 100);

if (config.Battery.Enabled && !config.PowerLimiter.IgnoreSoc) {
publishNumber("DPL battery SoC start threshold", "mdi:battery-charging",
"config", "threshold/soc/start", "threshold/soc/start", "%", 0, 100);
publishNumber("DPL battery SoC stop threshold", "mdi:battery-charging",
"config", "threshold/soc/stop", "threshold/soc/stop", "%", 0, 100);

if (config.Vedirect.Enabled) {
publishNumber("DPL full solar passthrough SoC",
"mdi:transmission-tower-import", "config",
"threshold/soc/full_solar_passthrough",
"threshold/soc/full_solar_passthrough", "%", 0, 100);
}
}
}

Expand Down Expand Up @@ -137,6 +171,11 @@ void MqttHandlePowerLimiterHassClass::publishNumber(
root["max"] = max;
root["mode"] = "box";

auto const& config = Configuration.get();
if (config.Mqtt.Hass.Expire) {
root["exp_aft"] = config.Mqtt.PublishInterval * 3;
}

JsonObject deviceObj = root.createNestedObject("dev");
createDeviceInfo(deviceObj);

Expand Down
4 changes: 4 additions & 0 deletions src/WebApi_battery.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "Battery.h"
#include "Configuration.h"
#include "MqttHandleBatteryHass.h"
#include "MqttHandlePowerLimiterHass.h"
#include "WebApi.h"
#include "WebApi_battery.h"
#include "WebApi_errors.h"
Expand Down Expand Up @@ -114,4 +115,7 @@ void WebApiBatteryClass::onAdminPost(AsyncWebServerRequest* request)

Battery.updateSettings();
MqttHandleBatteryHass.forceUpdate();

// potentially make SoC thresholds auto-discoverable
MqttHandlePowerLimiterHass.forceUpdate();
}
8 changes: 4 additions & 4 deletions src/WebApi_powerlimiter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,7 @@
#include "ArduinoJson.h"
#include "AsyncJson.h"
#include "Configuration.h"
#include "MqttHandleHass.h"
#include "MqttHandleVedirectHass.h"
#include "MqttSettings.h"
#include "PowerMeter.h"
#include "MqttHandlePowerLimiterHass.h"
#include "PowerLimiter.h"
#include "WebApi.h"
#include "helper.h"
Expand Down Expand Up @@ -155,4 +152,7 @@ void WebApiPowerLimiterClass::onAdminPost(AsyncWebServerRequest* request)
request->send(response);

PowerLimiter.calcNextInverterRestart();

// potentially make thresholds auto-discoverable
MqttHandlePowerLimiterHass.forceUpdate();
}
4 changes: 4 additions & 0 deletions src/WebApi_vedirect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "WebApi.h"
#include "WebApi_errors.h"
#include "helper.h"
#include "MqttHandlePowerLimiterHass.h"

void WebApiVedirectClass::init(AsyncWebServer& server, Scheduler& scheduler)
{
Expand Down Expand Up @@ -118,4 +119,7 @@ void WebApiVedirectClass::onVedirectAdminPost(AsyncWebServerRequest* request)
request->send(response);

VictronMppt.updateSettings();

// potentially make solar passthrough thresholds auto-discoverable
MqttHandlePowerLimiterHass.forceUpdate();
}

0 comments on commit 784e369

Please sign in to comment.