From 52d7ac95810810739641d5790bb79535c63448ca Mon Sep 17 00:00:00 2001 From: Bernhard Kirchen Date: Wed, 10 Apr 2024 20:31:29 +0200 Subject: [PATCH] Feature: DPL: support setups without power meter without a power meter configured, the DPL now sets the base load as the inverter limit if the battery charge allows it. it also takes solar-passthrough into account, i.e., if the battery is in a charge cycle but the solar output (Victron MPPT) is significant, the solar power will be used up until the base load. if the battery reaches the full solar passthrough threshold, the DPL will match the inverter limit to the MPPT solar output. --- include/PowerLimiter.h | 2 -- src/PowerLimiter.cpp | 10 +--------- webapp/src/locales/de.json | 2 +- webapp/src/locales/en.json | 2 +- webapp/src/locales/fr.json | 2 +- webapp/src/views/PowerLimiterAdminView.vue | 11 +++++++---- 6 files changed, 11 insertions(+), 18 deletions(-) diff --git a/include/PowerLimiter.h b/include/PowerLimiter.h index 28463654e..8f1b04f10 100644 --- a/include/PowerLimiter.h +++ b/include/PowerLimiter.h @@ -23,7 +23,6 @@ class PowerLimiterClass { DisabledByConfig, DisabledByMqtt, WaitingForValidTimestamp, - PowerMeterDisabled, PowerMeterPending, InverterInvalid, InverterChanged, @@ -38,7 +37,6 @@ class PowerLimiterClass { NoVeDirect, NoEnergy, HuaweiPsu, - Settling, Stable, }; diff --git a/src/PowerLimiter.cpp b/src/PowerLimiter.cpp index 8dd214042..729fcc90d 100644 --- a/src/PowerLimiter.cpp +++ b/src/PowerLimiter.cpp @@ -31,12 +31,11 @@ frozen::string const& PowerLimiterClass::getStatusText(PowerLimiterClass::Status { static const frozen::string missing = "programmer error: missing status text"; - static const frozen::map texts = { + static const frozen::map texts = { { Status::Initializing, "initializing (should not see me)" }, { Status::DisabledByConfig, "disabled by configuration" }, { Status::DisabledByMqtt, "disabled by MQTT" }, { Status::WaitingForValidTimestamp, "waiting for valid date and time to be available" }, - { Status::PowerMeterDisabled, "no power meter is configured/enabled" }, { Status::PowerMeterPending, "waiting for sufficiently recent power meter reading" }, { Status::InverterInvalid, "invalid inverter selection/configuration" }, { Status::InverterChanged, "target inverter changed" }, @@ -174,13 +173,6 @@ void PowerLimiterClass::loop() return unconditionalSolarPassthrough(_inverter); } - // the normal mode of operation requires a valid - // power meter reading to calculate a power limit - if (!config.PowerMeter.Enabled) { - shutdown(Status::PowerMeterDisabled); - return; - } - // concerns both power limits and start/stop/restart commands and is // only updated if a respective response was received from the inverter auto lastUpdateCmd = std::max( diff --git a/webapp/src/locales/de.json b/webapp/src/locales/de.json index 3d7c68f71..a56d5050e 100644 --- a/webapp/src/locales/de.json +++ b/webapp/src/locales/de.json @@ -585,7 +585,7 @@ "ConfigHintRequirement": "Erforderlich", "ConfigHintOptional": "Optional", "ConfigHintsIntro": "Folgende Hinweise zur Konfiguration des Dynamic Power Limiter (DPL) sollen beachtet werden:", - "ConfigHintPowerMeterDisabled": "Zum Betrieb des DPL muss der Power Meter konfiguriert sein und Daten liefern.", + "ConfigHintPowerMeterDisabled": "Der DPL stellt ohne Stromzählerschnittstelle lediglich die konfigurierte Grundlast als Limit am Wechselrichter ein (Ausnahme: (Full) Solar-Passthrough).", "ConfigHintNoInverter": "Vor dem Festlegen von Einstellungen des DPL muss mindestens ein Inverter konfiguriert sein.", "ConfigHintInverterCommunication": "Das Abrufen von Daten und Senden von Kommandos muss für den zu regelnden Wechselrichter aktiviert sein.", "ConfigHintNoChargeController": "Die Solar-Passthrough Funktion kann nur mit aktivierter VE.Direct Schnittstelle genutzt werden.", diff --git a/webapp/src/locales/en.json b/webapp/src/locales/en.json index afc036b6e..6599ce797 100644 --- a/webapp/src/locales/en.json +++ b/webapp/src/locales/en.json @@ -591,7 +591,7 @@ "ConfigHintRequirement": "Required", "ConfigHintOptional": "Optional", "ConfigHintsIntro": "The following notes regarding the Dynamic Power Limiter (DPL) configuration shall be considered:", - "ConfigHintPowerMeterDisabled": "Operating the DPL requires the Power Meter being configured and delivering data.", + "ConfigHintPowerMeterDisabled": "Without a power meter interface, the inverter limit the DPL will configure equals the configured base load (exception: (full) solar-passthrough).", "ConfigHintNoInverter": "At least one inverter must be configured prior to setting up the DPL.", "ConfigHintInverterCommunication": "Polling data from and sending commands to the target inverter must be enabled.", "ConfigHintNoChargeController": "The solar-passthrough feature can only be used if the VE.Direct interface is configured.", diff --git a/webapp/src/locales/fr.json b/webapp/src/locales/fr.json index 67bb9d277..0f5946f87 100644 --- a/webapp/src/locales/fr.json +++ b/webapp/src/locales/fr.json @@ -673,7 +673,7 @@ "ConfigHintRequirement": "Required", "ConfigHintOptional": "Optional", "ConfigHintsIntro": "The following notes regarding the Dynamic Power Limiter (DPL) configuration shall be considered:", - "ConfigHintPowerMeterDisabled": "Operating the DPL requires the Power Meter being configured and delivering data.", + "ConfigHintPowerMeterDisabled": "Without a power meter interface, the inverter limit the DPL will configure equals the configured base load (exception: (full) solar-passthrough).", "ConfigHintNoInverter": "At least one inverter must be configured prior to setting up the DPL.", "ConfigHintInverterCommunication": "Polling data from and sending commands to the target inverter must be enabled.", "ConfigHintNoChargeController": "The solar-passthrough feature can only be used if the VE.Direct interface is configured.", diff --git a/webapp/src/views/PowerLimiterAdminView.vue b/webapp/src/views/PowerLimiterAdminView.vue index 46da5def7..fec3f4ff8 100644 --- a/webapp/src/views/PowerLimiterAdminView.vue +++ b/webapp/src/views/PowerLimiterAdminView.vue @@ -34,7 +34,7 @@ v-model="powerLimiterConfigList.verbose_logging" type="checkbox" wide/> - - @@ -275,8 +276,7 @@ export default defineComponent({ var hints = []; if (meta.power_meter_enabled !== true) { - hints.push({severity: "requirement", subject: "PowerMeterDisabled"}); - this.configAlert = true; + hints.push({severity: "optional", subject: "PowerMeterDisabled"}); } if (typeof meta.inverters === "undefined" || Object.keys(meta.inverters).length == 0) { @@ -305,6 +305,9 @@ export default defineComponent({ isEnabled() { return this.powerLimiterConfigList.enabled; }, + hasPowerMeter() { + return this.powerLimiterMetaData.power_meter_enabled; + }, canUseSolarPassthrough() { var cfg = this.powerLimiterConfigList; var meta = this.powerLimiterMetaData;