From 66ce3ef4afd15961b633b8fa6aacb818203c8e1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kevin=20H=C3=BCbner?= Date: Tue, 14 Mar 2023 12:20:53 +0100 Subject: [PATCH 01/11] trigger update by sensor value if update_intervall is disabled --- .../soyosource_virtual_meter/soyosource_virtual_meter.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/components/soyosource_virtual_meter/soyosource_virtual_meter.cpp b/components/soyosource_virtual_meter/soyosource_virtual_meter.cpp index 621ead2..7e9d2c4 100644 --- a/components/soyosource_virtual_meter/soyosource_virtual_meter.cpp +++ b/components/soyosource_virtual_meter/soyosource_virtual_meter.cpp @@ -20,6 +20,11 @@ void SoyosourceVirtualMeter::setup() { this->last_power_demand_); this->last_power_demand_received_ = millis(); + + // If the update_interval is set to never, call the update() method on every power sensor update + if (this->get_update_interval() == SCHEDULER_DONT_RUN) { + this->update(); + } }); } From af12d0c8e5b224c615456a4764ad3561ae9a8708 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kevin=20H=C3=BCbner?= Date: Mon, 12 Jun 2023 13:58:47 +0200 Subject: [PATCH 02/11] overshoot compensation --- .../soyosource_virtual_meter.cpp | 34 +++++++++++++++++-- .../soyosource_virtual_meter.h | 7 +++- 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/components/soyosource_virtual_meter/soyosource_virtual_meter.cpp b/components/soyosource_virtual_meter/soyosource_virtual_meter.cpp index 7e9d2c4..ff685ca 100644 --- a/components/soyosource_virtual_meter/soyosource_virtual_meter.cpp +++ b/components/soyosource_virtual_meter/soyosource_virtual_meter.cpp @@ -111,16 +111,32 @@ int16_t SoyosourceVirtualMeter::calculate_power_demand_negative_measurements_(in // -500 -490 10 500 0 0 // -700 -690 10 500 -200 0 int16_t importing_now = consumption - this->buffer_; - int16_t power_demand = importing_now + last_power_demand; + + reset_power_demand_compensation(importing_now); + + int16_t power_demand = importing_now + last_power_demand - this->power_demand_compensation_; if (power_demand >= this->max_power_demand_) { - return this->max_power_demand_; + power_demand = max_power_demand_; } if (power_demand < this->min_power_demand_) { - return (this->zero_output_on_min_power_demand_) ? 0 : this->min_power_demand_; + power_demand = (this->zero_output_on_min_power_demand_) ? 0 : this->min_power_demand_; } + ESP_LOGD(TAG, "'%s': updated power_demand_compensation_ from %d", this->get_modbus_name(), this->power_demand_compensation_); + //only reduction of compensation but keep old demand: + if (this->power_demand_compensation_ != 0 && ((importing_now > 0 && power_demand < last_power_demand) || + (importing_now < 0 && power_demand > last_power_demand))) { + this->power_demand_compensation_ += power_demand - last_power_demand; + power_demand = last_power_demand; + ESP_LOGD(TAG, "'%s': Oscillation prevention, keeping previous demand: %d; reducing compensation", + this->get_modbus_name(), last_power_demand); + } else { + this->power_demand_compensation_ += power_demand - last_power_demand; + } + ESP_LOGD(TAG, "'%s': updated power_demand_compensation_ to %d", this->get_modbus_name(), this->power_demand_compensation_); + return power_demand; } @@ -206,5 +222,17 @@ void SoyosourceVirtualMeter::publish_state_(text_sensor::TextSensor *text_sensor text_sensor->publish_state(state); } +void SoyosourceVirtualMeter::reset_power_demand_compensation(int16_t importing_now) { + //reset on zero crossing or timeout + if (importing_now == 0 || (this->power_demand_compensation_ > 0 && importing_now < 0) + || (this->power_demand_compensation_ < 0 && importing_now > 0) + || this->power_demand_compensation_timestamp_ + this->power_demand_compensation_timeout_ms_ < millis()) { + ESP_LOGD(TAG, "'%s': reset power_demand_compensation_ to 0 %s", this->get_modbus_name(), + this->power_demand_compensation_timestamp_ + this->power_demand_compensation_timeout_ms_ < millis() ? "after timout" : "after zero crossing"); + this->power_demand_compensation_timestamp_ = millis(); + this->power_demand_compensation_ = 0; + } +} + } // namespace soyosource_virtual_meter } // namespace esphome diff --git a/components/soyosource_virtual_meter/soyosource_virtual_meter.h b/components/soyosource_virtual_meter/soyosource_virtual_meter.h index 89bfb51..a108f20 100644 --- a/components/soyosource_virtual_meter/soyosource_virtual_meter.h +++ b/components/soyosource_virtual_meter/soyosource_virtual_meter.h @@ -5,7 +5,7 @@ #include "esphome/components/sensor/sensor.h" #include "esphome/components/switch/switch.h" #include "esphome/components/text_sensor/text_sensor.h" -#include "esphome/components/soyosource_modbus/soyosource_modbus.h" +#include "../soyosource_modbus/soyosource_modbus.h" namespace esphome { namespace soyosource_virtual_meter { @@ -94,6 +94,10 @@ class SoyosourceVirtualMeter : public PollingComponent, public soyosource_modbus uint32_t last_power_demand_received_{0}; uint16_t last_power_demand_{0}; + int16_t power_demand_compensation_{0}; + uint32_t power_demand_compensation_timestamp_; + uint16_t power_demand_compensation_timeout_ms_{5000}; + void publish_state_(sensor::Sensor *sensor, float value); void publish_state_(text_sensor::TextSensor *text_sensor, const std::string &state); bool inactivity_timeout_(); @@ -102,6 +106,7 @@ class SoyosourceVirtualMeter : public PollingComponent, public soyosource_modbus int16_t calculate_power_demand_negative_measurements_(int16_t consumption, uint16_t last_power_demand); int16_t calculate_power_demand_restart_on_crossing_zero_(int16_t consumption, uint16_t last_power_demand); int16_t calculate_power_demand_oem_(int16_t consumption); + void reset_power_demand_compensation(int16_t importing_now); }; } // namespace soyosource_virtual_meter From ded6c2573b0f804f05805a00e8249e0797b91f0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kevin=20H=C3=BCbner?= Date: Thu, 16 Mar 2023 12:34:34 +0100 Subject: [PATCH 03/11] make power_demand_compensation_timeout_ configurable; 0 = disables this feature --- components/soyosource_virtual_meter/__init__.py | 9 +++++++++ .../soyosource_virtual_meter/soyosource_virtual_meter.h | 1 + 2 files changed, 10 insertions(+) diff --git a/components/soyosource_virtual_meter/__init__.py b/components/soyosource_virtual_meter/__init__.py index 03f43d1..3214dc3 100644 --- a/components/soyosource_virtual_meter/__init__.py +++ b/components/soyosource_virtual_meter/__init__.py @@ -19,6 +19,7 @@ CONF_POWER_DEMAND_DIVIDER = "power_demand_divider" CONF_OPERATION_STATUS_ID = "operation_status_id" CONF_ZERO_OUTPUT_ON_MIN_POWER_DEMAND = "zero_output_on_min_power_demand" +CONF_MAX_POWER_SENSOR_LATENCY_MS = "max_power_sensor_latency_ms" DEFAULT_MIN_BUFFER = -200 DEFAULT_MAX_BUFFER = 200 @@ -31,6 +32,10 @@ DEFAULT_MIN_POWER_DEMAND_DIVIDER = 1 DEFAULT_MAX_POWER_DEMAND_DIVIDER = 6 +DEFAULT_MAX_POWER_SENSOR_LATENCY_MS = 5000 +DEFAULT_MIN_MAX_POWER_SENSOR_LATENCY_MS = 0 +DEFAULT_MAX_MAX_POWER_SENSOR_LATENCY_MS = 30000 + soyosource_virtual_meter_ns = cg.esphome_ns.namespace("soyosource_virtual_meter") SoyosourceVirtualMeter = soyosource_virtual_meter_ns.class_( "SoyosourceVirtualMeter", @@ -85,6 +90,9 @@ def validate_min_max(config): CONF_MAX_POWER_DEMAND, default=DEFAULT_MAX_POWER_DEMAND ): cv.int_range(min=1, max=5400), cv.Optional(CONF_ZERO_OUTPUT_ON_MIN_POWER_DEMAND, default=True): cv.boolean, + cv.Optional( + CONF_MAX_POWER_SENSOR_LATENCY_MS, default=DEFAULT_MAX_POWER_SENSOR_LATENCY_MS + ): cv.int_range(min=DEFAULT_MIN_MAX_POWER_SENSOR_LATENCY_MS, max=DEFAULT_MAX_MAX_POWER_SENSOR_LATENCY_MS), } ) .extend(soyosource_modbus.soyosource_modbus_device_schema(0x24)) @@ -116,6 +124,7 @@ async def to_code(config): ) ) cg.add(var.set_power_demand_calculation(config[CONF_POWER_DEMAND_CALCULATION])) + cg.add(var.set_power_demand_compensation_timeout_ms(config[CONF_MAX_POWER_SENSOR_LATENCY_MS])) if CONF_OPERATION_STATUS_ID in config: operation_status_sensor = await cg.get_variable( diff --git a/components/soyosource_virtual_meter/soyosource_virtual_meter.h b/components/soyosource_virtual_meter/soyosource_virtual_meter.h index a108f20..c7b1581 100644 --- a/components/soyosource_virtual_meter/soyosource_virtual_meter.h +++ b/components/soyosource_virtual_meter/soyosource_virtual_meter.h @@ -47,6 +47,7 @@ class SoyosourceVirtualMeter : public PollingComponent, public soyosource_modbus void set_power_demand_divider_number(number::Number *power_demand_divider_number) { power_demand_divider_number_ = power_demand_divider_number; } + void set_power_demand_compensation_timeout_ms(uint16_t power_demand_compensation_timeout_ms) { this->power_demand_compensation_timeout_ms_ = power_demand_compensation_timeout_ms; } void set_manual_mode_switch(switch_::Switch *manual_mode_switch) { manual_mode_switch_ = manual_mode_switch; } void set_emergency_power_off_switch(switch_::Switch *emergency_power_off_switch) { From b24b9a6b184e06dc655ee0035951ee15e9265ea7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kevin=20H=C3=BCbner?= Date: Thu, 15 Jun 2023 16:38:47 +0200 Subject: [PATCH 04/11] forgot formatting again... :p --- .../soyosource_virtual_meter/__init__.py | 14 +++++++--- .../soyosource_virtual_meter.cpp | 26 +++++++++++-------- .../soyosource_virtual_meter.h | 6 +++-- 3 files changed, 30 insertions(+), 16 deletions(-) diff --git a/components/soyosource_virtual_meter/__init__.py b/components/soyosource_virtual_meter/__init__.py index 3214dc3..b0fd017 100644 --- a/components/soyosource_virtual_meter/__init__.py +++ b/components/soyosource_virtual_meter/__init__.py @@ -91,8 +91,12 @@ def validate_min_max(config): ): cv.int_range(min=1, max=5400), cv.Optional(CONF_ZERO_OUTPUT_ON_MIN_POWER_DEMAND, default=True): cv.boolean, cv.Optional( - CONF_MAX_POWER_SENSOR_LATENCY_MS, default=DEFAULT_MAX_POWER_SENSOR_LATENCY_MS - ): cv.int_range(min=DEFAULT_MIN_MAX_POWER_SENSOR_LATENCY_MS, max=DEFAULT_MAX_MAX_POWER_SENSOR_LATENCY_MS), + CONF_MAX_POWER_SENSOR_LATENCY_MS, + default=DEFAULT_MAX_POWER_SENSOR_LATENCY_MS, + ): cv.int_range( + min=DEFAULT_MIN_MAX_POWER_SENSOR_LATENCY_MS, + max=DEFAULT_MAX_MAX_POWER_SENSOR_LATENCY_MS, + ), } ) .extend(soyosource_modbus.soyosource_modbus_device_schema(0x24)) @@ -124,7 +128,11 @@ async def to_code(config): ) ) cg.add(var.set_power_demand_calculation(config[CONF_POWER_DEMAND_CALCULATION])) - cg.add(var.set_power_demand_compensation_timeout_ms(config[CONF_MAX_POWER_SENSOR_LATENCY_MS])) + cg.add( + var.set_power_demand_compensation_timeout_ms( + config[CONF_MAX_POWER_SENSOR_LATENCY_MS] + ) + ) if CONF_OPERATION_STATUS_ID in config: operation_status_sensor = await cg.get_variable( diff --git a/components/soyosource_virtual_meter/soyosource_virtual_meter.cpp b/components/soyosource_virtual_meter/soyosource_virtual_meter.cpp index ff685ca..937ce2c 100644 --- a/components/soyosource_virtual_meter/soyosource_virtual_meter.cpp +++ b/components/soyosource_virtual_meter/soyosource_virtual_meter.cpp @@ -112,7 +112,7 @@ int16_t SoyosourceVirtualMeter::calculate_power_demand_negative_measurements_(in // -700 -690 10 500 -200 0 int16_t importing_now = consumption - this->buffer_; - reset_power_demand_compensation(importing_now); + reset_power_demand_compensation_(importing_now); int16_t power_demand = importing_now + last_power_demand - this->power_demand_compensation_; @@ -124,10 +124,11 @@ int16_t SoyosourceVirtualMeter::calculate_power_demand_negative_measurements_(in power_demand = (this->zero_output_on_min_power_demand_) ? 0 : this->min_power_demand_; } - ESP_LOGD(TAG, "'%s': updated power_demand_compensation_ from %d", this->get_modbus_name(), this->power_demand_compensation_); - //only reduction of compensation but keep old demand: + ESP_LOGD(TAG, "'%s': updated power_demand_compensation_ from %d", this->get_modbus_name(), + this->power_demand_compensation_); + // only reduction of compensation but keep old demand: if (this->power_demand_compensation_ != 0 && ((importing_now > 0 && power_demand < last_power_demand) || - (importing_now < 0 && power_demand > last_power_demand))) { + (importing_now < 0 && power_demand > last_power_demand))) { this->power_demand_compensation_ += power_demand - last_power_demand; power_demand = last_power_demand; ESP_LOGD(TAG, "'%s': Oscillation prevention, keeping previous demand: %d; reducing compensation", @@ -135,7 +136,8 @@ int16_t SoyosourceVirtualMeter::calculate_power_demand_negative_measurements_(in } else { this->power_demand_compensation_ += power_demand - last_power_demand; } - ESP_LOGD(TAG, "'%s': updated power_demand_compensation_ to %d", this->get_modbus_name(), this->power_demand_compensation_); + ESP_LOGD(TAG, "'%s': updated power_demand_compensation_ to %d", this->get_modbus_name(), + this->power_demand_compensation_); return power_demand; } @@ -222,13 +224,15 @@ void SoyosourceVirtualMeter::publish_state_(text_sensor::TextSensor *text_sensor text_sensor->publish_state(state); } -void SoyosourceVirtualMeter::reset_power_demand_compensation(int16_t importing_now) { - //reset on zero crossing or timeout - if (importing_now == 0 || (this->power_demand_compensation_ > 0 && importing_now < 0) - || (this->power_demand_compensation_ < 0 && importing_now > 0) - || this->power_demand_compensation_timestamp_ + this->power_demand_compensation_timeout_ms_ < millis()) { +void SoyosourceVirtualMeter::reset_power_demand_compensation_(int16_t importing_now) { + // reset on zero crossing or timeout + if (importing_now == 0 || (this->power_demand_compensation_ > 0 && importing_now < 0) || + (this->power_demand_compensation_ < 0 && importing_now > 0) || + this->power_demand_compensation_timestamp_ + this->power_demand_compensation_timeout_ms_ < millis()) { ESP_LOGD(TAG, "'%s': reset power_demand_compensation_ to 0 %s", this->get_modbus_name(), - this->power_demand_compensation_timestamp_ + this->power_demand_compensation_timeout_ms_ < millis() ? "after timout" : "after zero crossing"); + this->power_demand_compensation_timestamp_ + this->power_demand_compensation_timeout_ms_ < millis() + ? "after timout" + : "after zero crossing"); this->power_demand_compensation_timestamp_ = millis(); this->power_demand_compensation_ = 0; } diff --git a/components/soyosource_virtual_meter/soyosource_virtual_meter.h b/components/soyosource_virtual_meter/soyosource_virtual_meter.h index c7b1581..89a868d 100644 --- a/components/soyosource_virtual_meter/soyosource_virtual_meter.h +++ b/components/soyosource_virtual_meter/soyosource_virtual_meter.h @@ -47,7 +47,9 @@ class SoyosourceVirtualMeter : public PollingComponent, public soyosource_modbus void set_power_demand_divider_number(number::Number *power_demand_divider_number) { power_demand_divider_number_ = power_demand_divider_number; } - void set_power_demand_compensation_timeout_ms(uint16_t power_demand_compensation_timeout_ms) { this->power_demand_compensation_timeout_ms_ = power_demand_compensation_timeout_ms; } + void set_power_demand_compensation_timeout_ms(uint16_t power_demand_compensation_timeout_ms) { + this->power_demand_compensation_timeout_ms_ = power_demand_compensation_timeout_ms; + } void set_manual_mode_switch(switch_::Switch *manual_mode_switch) { manual_mode_switch_ = manual_mode_switch; } void set_emergency_power_off_switch(switch_::Switch *emergency_power_off_switch) { @@ -107,7 +109,7 @@ class SoyosourceVirtualMeter : public PollingComponent, public soyosource_modbus int16_t calculate_power_demand_negative_measurements_(int16_t consumption, uint16_t last_power_demand); int16_t calculate_power_demand_restart_on_crossing_zero_(int16_t consumption, uint16_t last_power_demand); int16_t calculate_power_demand_oem_(int16_t consumption); - void reset_power_demand_compensation(int16_t importing_now); + void reset_power_demand_compensation_(int16_t importing_now); }; } // namespace soyosource_virtual_meter From dd9b6c2505b0fdb4d21a15ee9b1cd267a8eab010 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kevin=20H=C3=BCbner?= Date: Mon, 19 Jun 2023 11:58:28 +0200 Subject: [PATCH 05/11] additional time stamp update in some cases --- .../soyosource_virtual_meter.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/components/soyosource_virtual_meter/soyosource_virtual_meter.cpp b/components/soyosource_virtual_meter/soyosource_virtual_meter.cpp index 937ce2c..dbc839a 100644 --- a/components/soyosource_virtual_meter/soyosource_virtual_meter.cpp +++ b/components/soyosource_virtual_meter/soyosource_virtual_meter.cpp @@ -134,7 +134,15 @@ int16_t SoyosourceVirtualMeter::calculate_power_demand_negative_measurements_(in ESP_LOGD(TAG, "'%s': Oscillation prevention, keeping previous demand: %d; reducing compensation", this->get_modbus_name(), last_power_demand); } else { - this->power_demand_compensation_ += power_demand - last_power_demand; + int16_t new_demand = this->power_demand_compensation_ + power_demand - last_power_demand; + // if not really compensating at the moment and demand changes a bit more, increase current time stamp: helps to + // reduce false time-outs + if (abs(this->power_demand_compensation_) < 15 && abs(new_demand) > 50) { + ESP_LOGD(TAG, "'%s': resetting only timeout: power_demand_compensation_: %d; new_deman: %d", + this->get_modbus_name(), this->power_demand_compensation_, new_demand); + this->power_demand_compensation_timestamp_ = millis(); + } + this->power_demand_compensation_ = new_demand; } ESP_LOGD(TAG, "'%s': updated power_demand_compensation_ to %d", this->get_modbus_name(), this->power_demand_compensation_); From a4602539baab10787cbaaea6b1a5b19dda059895 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kevin=20H=C3=BCbner?= Date: Fri, 30 Jun 2023 13:26:18 +0200 Subject: [PATCH 06/11] minor improvement --- .../soyosource_virtual_meter/soyosource_virtual_meter.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/soyosource_virtual_meter/soyosource_virtual_meter.cpp b/components/soyosource_virtual_meter/soyosource_virtual_meter.cpp index dbc839a..bfc01e9 100644 --- a/components/soyosource_virtual_meter/soyosource_virtual_meter.cpp +++ b/components/soyosource_virtual_meter/soyosource_virtual_meter.cpp @@ -135,9 +135,9 @@ int16_t SoyosourceVirtualMeter::calculate_power_demand_negative_measurements_(in this->get_modbus_name(), last_power_demand); } else { int16_t new_demand = this->power_demand_compensation_ + power_demand - last_power_demand; - // if not really compensating at the moment and demand changes a bit more, increase current time stamp: helps to + // if not really compensating at the moment and demand changes a bit more, update current time stamp: helps to // reduce false time-outs - if (abs(this->power_demand_compensation_) < 15 && abs(new_demand) > 50) { + if (abs(this->power_demand_compensation_) <= 15 && abs(new_demand) > 30) { ESP_LOGD(TAG, "'%s': resetting only timeout: power_demand_compensation_: %d; new_deman: %d", this->get_modbus_name(), this->power_demand_compensation_, new_demand); this->power_demand_compensation_timestamp_ = millis(); From 99ae9c2778e806949119d094824a5a63ec3c734b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kevin=20H=C3=BCbner?= Date: Wed, 20 Dec 2023 15:14:25 +0100 Subject: [PATCH 07/11] make sensor latency adjustable for automations etc. --- .../number/__init__.py | 31 +++++++++++++++++++ .../number/soyosource_number.cpp | 3 ++ 2 files changed, 34 insertions(+) diff --git a/components/soyosource_virtual_meter/number/__init__.py b/components/soyosource_virtual_meter/number/__init__.py index b9a1e39..5b921fa 100644 --- a/components/soyosource_virtual_meter/number/__init__.py +++ b/components/soyosource_virtual_meter/number/__init__.py @@ -12,12 +12,14 @@ CONF_UNIT_OF_MEASUREMENT, UNIT_EMPTY, UNIT_WATT, + UNIT_MILLISECOND, ) from .. import ( CONF_BUFFER, CONF_POWER_DEMAND_DIVIDER, CONF_SOYOSOURCE_VIRTUAL_METER_ID, + CONF_MAX_POWER_SENSOR_LATENCY_MS, DEFAULT_BUFFER, DEFAULT_MAX_BUFFER, DEFAULT_MAX_POWER_DEMAND, @@ -26,6 +28,9 @@ DEFAULT_MIN_POWER_DEMAND, DEFAULT_MIN_POWER_DEMAND_DIVIDER, DEFAULT_POWER_DEMAND_DIVIDER, + DEFAULT_MAX_POWER_SENSOR_LATENCY_MS, + DEFAULT_MIN_MAX_POWER_SENSOR_LATENCY_MS, + DEFAULT_MAX_MAX_POWER_SENSOR_LATENCY_MS, SoyosourceVirtualMeter, soyosource_virtual_meter_ns, ) @@ -42,12 +47,14 @@ ICON_MANUAL_POWER_DEMAND = "mdi:home-lightning-bolt-outline" ICON_MAX_POWER_DEMAND = "mdi:transmission-tower-import" ICON_POWER_DEMAND_DIVIDER = "mdi:chart-arc" +ICON_POWER_SENSOR_LATENCY = "mdi:timer-sync-outline" NUMBERS = { CONF_MANUAL_POWER_DEMAND: 0x00, CONF_MAX_POWER_DEMAND: 0x01, CONF_BUFFER: 0x02, CONF_POWER_DEMAND_DIVIDER: 0x03, + CONF_MAX_POWER_SENSOR_LATENCY_MS: 0x04, } SoyosourceNumber = soyosource_virtual_meter_ns.class_( @@ -162,6 +169,30 @@ def validate(config): validate_min_max, validate, ), + cv.Optional(CONF_MAX_POWER_SENSOR_LATENCY_MS): cv.All( + number.NUMBER_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(SoyosourceNumber), + cv.Optional(CONF_ICON, default=ICON_POWER_SENSOR_LATENCY): cv.icon, + cv.Optional( + CONF_MIN_VALUE, default=DEFAULT_MIN_MAX_POWER_SENSOR_LATENCY_MS + ): cv.float_, + cv.Optional( + CONF_MAX_VALUE, default=DEFAULT_MAX_MAX_POWER_SENSOR_LATENCY_MS + ): cv.float_, + cv.Optional(CONF_STEP, default=DEFAULT_STEP): cv.float_, + cv.Optional( + CONF_UNIT_OF_MEASUREMENT, default=UNIT_MILLISECOND + ): cv.string_strict, + cv.Optional( + CONF_INITIAL_VALUE, default=DEFAULT_MAX_POWER_SENSOR_LATENCY_MS + ): cv.float_, + cv.Optional(CONF_RESTORE_VALUE, default=False): cv.boolean, + } + ).extend(cv.COMPONENT_SCHEMA), + validate_min_max, + validate, + ), } ) diff --git a/components/soyosource_virtual_meter/number/soyosource_number.cpp b/components/soyosource_virtual_meter/number/soyosource_number.cpp index 8128e78..8f17a86 100644 --- a/components/soyosource_virtual_meter/number/soyosource_number.cpp +++ b/components/soyosource_virtual_meter/number/soyosource_number.cpp @@ -42,6 +42,9 @@ void SoyosourceNumber::apply_and_publish_(float value) { case 0x03: this->parent_->set_power_demand_divider((uint8_t) value); break; + case 0x04: + this->parent_->set_power_demand_compensation_timeout_ms((uint16_t) value); + break; } this->publish_state(value); From 381a6b83437414b014a2ec4a091f3826493cc65c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kevin=20H=C3=BCbner?= Date: Wed, 20 Dec 2023 15:36:52 +0100 Subject: [PATCH 08/11] add dummy setter --- .../soyosource_virtual_meter/soyosource_virtual_meter.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/components/soyosource_virtual_meter/soyosource_virtual_meter.h b/components/soyosource_virtual_meter/soyosource_virtual_meter.h index 89a868d..8ea1c40 100644 --- a/components/soyosource_virtual_meter/soyosource_virtual_meter.h +++ b/components/soyosource_virtual_meter/soyosource_virtual_meter.h @@ -47,6 +47,9 @@ class SoyosourceVirtualMeter : public PollingComponent, public soyosource_modbus void set_power_demand_divider_number(number::Number *power_demand_divider_number) { power_demand_divider_number_ = power_demand_divider_number; } + void set_max_power_sensor_latency_ms_number(number::Number *max_power_sensor_latency_ms_number) { + this->power_demand_compensation_timeout_ms_number = max_power_sensor_latency_ms_number; + } void set_power_demand_compensation_timeout_ms(uint16_t power_demand_compensation_timeout_ms) { this->power_demand_compensation_timeout_ms_ = power_demand_compensation_timeout_ms; } @@ -76,6 +79,7 @@ class SoyosourceVirtualMeter : public PollingComponent, public soyosource_modbus number::Number *manual_power_demand_number_; number::Number *max_power_demand_number_; number::Number *power_demand_divider_number_; + number::Number *power_demand_compensation_timeout_ms_number; sensor::Sensor *power_sensor_; sensor::Sensor *operation_status_sensor_; From 9d04ec9c04a87a190e5cfae06c113204086a6fbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kevin=20H=C3=BCbner?= Date: Wed, 20 Dec 2023 16:03:54 +0100 Subject: [PATCH 09/11] fix typo in dummy setter --- .../soyosource_virtual_meter/soyosource_virtual_meter.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/soyosource_virtual_meter/soyosource_virtual_meter.h b/components/soyosource_virtual_meter/soyosource_virtual_meter.h index 8ea1c40..b6dfaa4 100644 --- a/components/soyosource_virtual_meter/soyosource_virtual_meter.h +++ b/components/soyosource_virtual_meter/soyosource_virtual_meter.h @@ -48,7 +48,7 @@ class SoyosourceVirtualMeter : public PollingComponent, public soyosource_modbus power_demand_divider_number_ = power_demand_divider_number; } void set_max_power_sensor_latency_ms_number(number::Number *max_power_sensor_latency_ms_number) { - this->power_demand_compensation_timeout_ms_number = max_power_sensor_latency_ms_number; + this->power_demand_compensation_timeout_ms_number_ = max_power_sensor_latency_ms_number; } void set_power_demand_compensation_timeout_ms(uint16_t power_demand_compensation_timeout_ms) { this->power_demand_compensation_timeout_ms_ = power_demand_compensation_timeout_ms; @@ -79,7 +79,7 @@ class SoyosourceVirtualMeter : public PollingComponent, public soyosource_modbus number::Number *manual_power_demand_number_; number::Number *max_power_demand_number_; number::Number *power_demand_divider_number_; - number::Number *power_demand_compensation_timeout_ms_number; + number::Number *power_demand_compensation_timeout_ms_number_; sensor::Sensor *power_sensor_; sensor::Sensor *operation_status_sensor_; From 5f1802f0929d54cd567b649a591def905e171053 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kevin=20H=C3=BCbner?= Date: Tue, 20 Feb 2024 10:15:21 +0100 Subject: [PATCH 10/11] renamed variable --- .../soyosource_virtual_meter.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/components/soyosource_virtual_meter/soyosource_virtual_meter.cpp b/components/soyosource_virtual_meter/soyosource_virtual_meter.cpp index bfc01e9..b635c69 100644 --- a/components/soyosource_virtual_meter/soyosource_virtual_meter.cpp +++ b/components/soyosource_virtual_meter/soyosource_virtual_meter.cpp @@ -134,15 +134,15 @@ int16_t SoyosourceVirtualMeter::calculate_power_demand_negative_measurements_(in ESP_LOGD(TAG, "'%s': Oscillation prevention, keeping previous demand: %d; reducing compensation", this->get_modbus_name(), last_power_demand); } else { - int16_t new_demand = this->power_demand_compensation_ + power_demand - last_power_demand; + int16_t next_demand_compensation = this->power_demand_compensation_ + power_demand - last_power_demand; // if not really compensating at the moment and demand changes a bit more, update current time stamp: helps to // reduce false time-outs - if (abs(this->power_demand_compensation_) <= 15 && abs(new_demand) > 30) { - ESP_LOGD(TAG, "'%s': resetting only timeout: power_demand_compensation_: %d; new_deman: %d", - this->get_modbus_name(), this->power_demand_compensation_, new_demand); + if (abs(this->power_demand_compensation_) <= 15 && abs(next_demand_compensation) > 30) { + ESP_LOGD(TAG, "'%s': resetting only timeout: power_demand_compensation_: %d; next_demand_compensation: %d", + this->get_modbus_name(), this->power_demand_compensation_, next_demand_compensation); this->power_demand_compensation_timestamp_ = millis(); } - this->power_demand_compensation_ = new_demand; + this->power_demand_compensation_ = next_demand_compensation; } ESP_LOGD(TAG, "'%s': updated power_demand_compensation_ to %d", this->get_modbus_name(), this->power_demand_compensation_); From 18749864d910561c0c3acd0e9b22c09dc438ede0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kevin=20H=C3=BCbner?= Date: Mon, 2 Jun 2025 16:40:19 +0200 Subject: [PATCH 11/11] Fix *.*_SCHEMA deprecations for sensor latency --- .../soyosource_virtual_meter/number/__init__.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/components/soyosource_virtual_meter/number/__init__.py b/components/soyosource_virtual_meter/number/__init__.py index f53c46d..ca13c53 100644 --- a/components/soyosource_virtual_meter/number/__init__.py +++ b/components/soyosource_virtual_meter/number/__init__.py @@ -172,10 +172,13 @@ def validate(config): validate, ), cv.Optional(CONF_MAX_POWER_SENSOR_LATENCY_MS): cv.All( - number.NUMBER_SCHEMA.extend( + number.number_schema( + SoyosourceNumber, + icon=ICON_POWER_SENSOR_LATENCY, + unit_of_measurement=UNIT_MILLISECOND, + ) + .extend( { - cv.GenerateID(): cv.declare_id(SoyosourceNumber), - cv.Optional(CONF_ICON, default=ICON_POWER_SENSOR_LATENCY): cv.icon, cv.Optional( CONF_MIN_VALUE, default=DEFAULT_MIN_MAX_POWER_SENSOR_LATENCY_MS ): cv.float_, @@ -183,15 +186,13 @@ def validate(config): CONF_MAX_VALUE, default=DEFAULT_MAX_MAX_POWER_SENSOR_LATENCY_MS ): cv.float_, cv.Optional(CONF_STEP, default=DEFAULT_STEP): cv.float_, - cv.Optional( - CONF_UNIT_OF_MEASUREMENT, default=UNIT_MILLISECOND - ): cv.string_strict, cv.Optional( CONF_INITIAL_VALUE, default=DEFAULT_MAX_POWER_SENSOR_LATENCY_MS ): cv.float_, cv.Optional(CONF_RESTORE_VALUE, default=False): cv.boolean, } - ).extend(cv.COMPONENT_SCHEMA), + ) + .extend(cv.COMPONENT_SCHEMA), validate_min_max, validate, ),