diff --git a/src/MqttHandlePowerLimiter.cpp b/src/MqttHandlePowerLimiter.cpp index 065f65105..411fa3f1a 100644 --- a/src/MqttHandlePowerLimiter.cpp +++ b/src/MqttHandlePowerLimiter.cpp @@ -67,18 +67,33 @@ void MqttHandlePowerLimiterClass::loop() if (!MqttSettings.getConnected() ) { return; } - if ((millis() - _lastPublish) > (config.Mqtt.PublishInterval * 1000) ) { - auto val = static_cast(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(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)); } } diff --git a/src/MqttHandlePowerLimiterHass.cpp b/src/MqttHandlePowerLimiterHass.cpp index 17b9ad7cb..47edfbae6 100644 --- a/src/MqttHandlePowerLimiterHass.cpp +++ b/src/MqttHandlePowerLimiterHass.cpp @@ -46,7 +46,9 @@ void MqttHandlePowerLimiterHassClass::forceUpdate() void MqttHandlePowerLimiterHassClass::publishConfig() { - if (!Configuration.get().Mqtt.Hass.Enabled) { + auto const& config = Configuration.get(); + + if (!config.Mqtt.Hass.Enabled) { return; } @@ -54,13 +56,45 @@ void MqttHandlePowerLimiterHassClass::publishConfig() 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); + } } } @@ -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); diff --git a/src/WebApi_battery.cpp b/src/WebApi_battery.cpp index 9e2230c4e..3f26d83cc 100644 --- a/src/WebApi_battery.cpp +++ b/src/WebApi_battery.cpp @@ -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" @@ -114,4 +115,7 @@ void WebApiBatteryClass::onAdminPost(AsyncWebServerRequest* request) Battery.updateSettings(); MqttHandleBatteryHass.forceUpdate(); + + // potentially make SoC thresholds auto-discoverable + MqttHandlePowerLimiterHass.forceUpdate(); } diff --git a/src/WebApi_powerlimiter.cpp b/src/WebApi_powerlimiter.cpp index 3a7d827a2..444c134f2 100644 --- a/src/WebApi_powerlimiter.cpp +++ b/src/WebApi_powerlimiter.cpp @@ -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" @@ -155,4 +152,7 @@ void WebApiPowerLimiterClass::onAdminPost(AsyncWebServerRequest* request) request->send(response); PowerLimiter.calcNextInverterRestart(); + + // potentially make thresholds auto-discoverable + MqttHandlePowerLimiterHass.forceUpdate(); } diff --git a/src/WebApi_vedirect.cpp b/src/WebApi_vedirect.cpp index 088be259f..4e1e352b2 100644 --- a/src/WebApi_vedirect.cpp +++ b/src/WebApi_vedirect.cpp @@ -10,6 +10,7 @@ #include "WebApi.h" #include "WebApi_errors.h" #include "helper.h" +#include "MqttHandlePowerLimiterHass.h" void WebApiVedirectClass::init(AsyncWebServer& server, Scheduler& scheduler) { @@ -118,4 +119,7 @@ void WebApiVedirectClass::onVedirectAdminPost(AsyncWebServerRequest* request) request->send(response); VictronMppt.updateSettings(); + + // potentially make solar passthrough thresholds auto-discoverable + MqttHandlePowerLimiterHass.forceUpdate(); }