From ac2e01740dd055bab386d3a836e9e0e741b6bd15 Mon Sep 17 00:00:00 2001 From: Xavier Berger Date: Thu, 13 Aug 2026 21:01:14 +0200 Subject: [PATCH 1/3] feat(engine): add regulator opening sensor with 1switch wiring MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds a shared "Regulator Opening Sensor" template sensor to `engine_common.yaml` so every engine variant surfaces the current regulator opening (%) in Home Assistant graphs. The sensor mirrors `id(regulator_opening)` on a 5 s update cadence. To make the sensor actually update on the 1-switch variant, this commit also declares the `regulator_opening` template number in `engine_1switch.yaml` and drives it from the `router_level` on_value handler — same pattern engine_1dimmer.yaml already uses at :48-50. On this variant the router is either fully open (100 %) or fully closed (0 %), so the number uses `mode: box` with `step: 100`; a slider would only be reachable at its endpoints. Without this wiring the sensor would read 0 forever on the 1-switch variant, which was the case in the original feature commit. Co-Authored-By: Claude Opus 4.7 --- solar_router/engine_1switch.yaml | 23 ++++++++++++++++++++++- solar_router/engine_common.yaml | 11 +++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/solar_router/engine_1switch.yaml b/solar_router/engine_1switch.yaml index c231fba..bbd1a13 100644 --- a/solar_router/engine_1switch.yaml +++ b/solar_router/engine_1switch.yaml @@ -61,6 +61,12 @@ number: optimistic: True on_value: then: + # Keep regulator_opening in sync with router_level so the shared + # regulator_opening_sensor in engine_common.yaml tracks this + # variant too (same pattern as engine_1dimmer.yaml). + - number.set: + id: regulator_opening + value: !lambda return id(router_level).state; - if: condition: number.in_range: @@ -85,7 +91,22 @@ number: - switch.is_on: activate then: - light.turn_on: green_led - + + # Regulator opening percentage. On this variant the router is either + # fully open (100 %) or fully closed (0 %), so `mode: box` reflects the + # discrete nature — a slider with step 100 would only be reachable at + # its endpoints. + - platform: template + name: "Regulator Opening" + id: regulator_opening + min_value: 0 + max_value: 100 + step: 100 + unit_of_measurement: "%" + optimistic: True + mode: box + internal: true + # Define the power level to start divertion - platform: template name: "Start power level" diff --git a/solar_router/engine_common.yaml b/solar_router/engine_common.yaml index ba43287..9297493 100644 --- a/solar_router/engine_common.yaml +++ b/solar_router/engine_common.yaml @@ -23,6 +23,17 @@ sensor: then: script.execute: energy_regulation + # Mirror the current regulator opening (%) as a template sensor so it + # is visible in Home Assistant graphs. Every engine variant defines a + # `regulator_opening` template number; this sensor tracks its state. + - platform: template + name: "Regulator Opening Sensor" + id: regulator_opening_sensor + unit_of_measurement: "%" + accuracy_decimals: 0 + update_interval: 5s + lambda: return id(regulator_opening).state; + substitutions: # By default LEDs are pin-controlled and not inverted green_led_inverted: "False" From 4dba278dda0c28b311faf256866c85a242fd6629 Mon Sep 17 00:00:00 2001 From: Xavier Berger Date: Thu, 13 Aug 2026 21:01:29 +0200 Subject: [PATCH 2/3] feat(power_meter): always poll meters and standardise package includes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Converts every power_meter_*.yaml from the YAML-merge include syntax (`<<: !include`) to the modern `packages:` include, and removes the `if id(power_meter_activated) != 0` guard around each meter's `power_meter_source` script so the meter reports live data to Home Assistant even while the Solar Router's `activate` switch is off. The engine still only acts on real_power when `activate` is on. The uniform refactor covers all six meter variants — fronius, shelly_em, shelly_em3, proxy_client, jsy-mk-194t, home_assistant. Meter-specific notes: - power_meter_home_assistant.yaml: because both this file and power_meter_common.yaml would now define `real_power`/`consumption` under `packages:`, the HA-imported sensors are renamed to `real_power_reader` / `consumption_reader` (marked `internal: True` to hide the duplicates from HA) and forward their values into the common template sensors via an `on_value` lambda. A `min_version: 2025.5.0` is pinned since the new include syntax requires it. - power_meter_shelly_em3.yaml: drops the previously required re- declarations of `real_power` / `consumption` (the `<<:` merge only kept the first `sensor:` key so the common template sensors were never instantiated). The obsolete comment about that limitation is removed. Substitutions are trimmed to the shelly-specific overrides, since `packages:` correctly propagates the defaults from common. - power_meter_proxy_client.yaml: `min_version` bumped from 2024.11.1 to 2025.5.0 to match the include syntax requirement. Co-Authored-By: Claude Opus 4.7 --- solar_router/power_meter_fronius.yaml | 12 +++--- solar_router/power_meter_home_assistant.yaml | 33 ++++++++++---- solar_router/power_meter_jsy-mk-194t.yaml | 12 +++--- solar_router/power_meter_proxy_client.yaml | 13 +++--- solar_router/power_meter_shelly_em.yaml | 11 +++-- solar_router/power_meter_shelly_em3.yaml | 45 ++++++-------------- 6 files changed, 59 insertions(+), 67 deletions(-) diff --git a/solar_router/power_meter_fronius.yaml b/solar_router/power_meter_fronius.yaml index 24439b8..7bf3686 100644 --- a/solar_router/power_meter_fronius.yaml +++ b/solar_router/power_meter_fronius.yaml @@ -1,4 +1,5 @@ -<<: !include power_meter_common.yaml +packages: + - !include power_meter_common.yaml esphome: min_version: 2025.5.0 @@ -100,10 +101,9 @@ script: time: - platform: sntp on_time: + # The engine only reacts to real_power / consumption when the + # `activate` switch is on; polling the meter unconditionally lets + # Home Assistant show live figures even while routing is off. - seconds: /1 then: - - if: - condition: - - lambda: return id(power_meter_activated) != 0; - then: - - script.execute: power_meter_source + - script.execute: power_meter_source diff --git a/solar_router/power_meter_home_assistant.yaml b/solar_router/power_meter_home_assistant.yaml index 1def5df..aa57594 100644 --- a/solar_router/power_meter_home_assistant.yaml +++ b/solar_router/power_meter_home_assistant.yaml @@ -1,26 +1,41 @@ -<<: !include power_meter_common.yaml +packages: + - !include power_meter_common.yaml + +esphome: + min_version: 2025.5.0 # ---------------------------------------------------------------------------------------------------- # Define sensor for power collection # ---------------------------------------------------------------------------------------------------- +# The Home Assistant power meter imports two sensors from HA and forwards +# them into the `real_power` / `consumption` template sensors declared in +# power_meter_common.yaml, so the rest of the packages see the same API +# as every other meter variant. The reader sensors are `internal: True` +# to avoid exposing duplicate entities in Home Assistant. sensor: - # Sensor showing the actual power exchange - platform: homeassistant - id: real_power + id: real_power_reader entity_id: ${main_power_sensor} - internal: False - name: "Real Power" + internal: True + name: "Real Power Reader" device_class: "power" unit_of_measurement: "W" filters: - multiply: ${power_sign} + on_value: + then: + - lambda: |- + id(real_power).publish_state(x); - # Sensor showing the actual consumption - platform: homeassistant - id: consumption + id: consumption_reader entity_id: ${consumption_sensor} - internal: False - name: "Consumption" + internal: True + name: "Consumption Reader" device_class: "power" unit_of_measurement: "W" + on_value: + then: + - lambda: |- + id(consumption).publish_state(x); diff --git a/solar_router/power_meter_jsy-mk-194t.yaml b/solar_router/power_meter_jsy-mk-194t.yaml index 19d4492..0adb08a 100644 --- a/solar_router/power_meter_jsy-mk-194t.yaml +++ b/solar_router/power_meter_jsy-mk-194t.yaml @@ -1,4 +1,6 @@ -<<: !include power_meter_common.yaml +packages: + - !include power_meter_common.yaml + # ---------------------------------------------------------------------------------------------------- # User interaction # ---------------------------------------------------------------------------------------------------- @@ -31,10 +33,8 @@ script: time: - platform: sntp on_time: + # Poll unconditionally so real_power stays fresh in HA even when + # the router's `activate` switch is off. - seconds: /1 then: - - if: - condition: - lambda: return id(power_meter_activated) != 0; - then: - - script.execute: power_meter_source + - script.execute: power_meter_source diff --git a/solar_router/power_meter_proxy_client.yaml b/solar_router/power_meter_proxy_client.yaml index 136b3f5..289d9a4 100644 --- a/solar_router/power_meter_proxy_client.yaml +++ b/solar_router/power_meter_proxy_client.yaml @@ -1,7 +1,8 @@ -<<: !include power_meter_common.yaml +packages: + - !include power_meter_common.yaml esphome: - min_version: 2024.11.1 + min_version: 2025.5.0 # ---------------------------------------------------------------------------------------------------- # Use http request component @@ -90,10 +91,8 @@ script: time: - platform: sntp on_time: + # Poll unconditionally so real_power/consumption stay fresh in HA + # even when the router's `activate` switch is off. - seconds: /1 then: - - if: - condition: - - lambda: return id(power_meter_activated) != 0; - then: - - script.execute: power_meter_source + - script.execute: power_meter_source diff --git a/solar_router/power_meter_shelly_em.yaml b/solar_router/power_meter_shelly_em.yaml index 290823f..bb7dfe8 100644 --- a/solar_router/power_meter_shelly_em.yaml +++ b/solar_router/power_meter_shelly_em.yaml @@ -1,4 +1,5 @@ -<<: !include power_meter_common.yaml +packages: + - !include power_meter_common.yaml esphome: min_version: 2025.5.0 @@ -72,10 +73,8 @@ script: time: - platform: sntp on_time: + # Poll unconditionally so real_power stays fresh in HA even when + # the router's `activate` switch is off. - seconds: /1 then: - - if: - condition: - - lambda: return id(power_meter_activated) != 0; - then: - - script.execute: power_meter_source + - script.execute: power_meter_source diff --git a/solar_router/power_meter_shelly_em3.yaml b/solar_router/power_meter_shelly_em3.yaml index b8c2bae..e214559 100644 --- a/solar_router/power_meter_shelly_em3.yaml +++ b/solar_router/power_meter_shelly_em3.yaml @@ -1,4 +1,5 @@ -<<: !include power_meter_common.yaml +packages: + - !include power_meter_common.yaml esphome: min_version: 2025.5.0 @@ -31,13 +32,9 @@ esphome: # show_phase_power (optional) expose per-phase W sensors, default "False". substitutions: - # Same defaults as power_meter_common.yaml - re-declared here because a - # substitution block overriding the merged one replaces it entirely. - power_meter_activated_at_start: "0" - power_sign: "1" - # The Shelly EM3 only exposes a NET power (total_act_power): the per-phase - # "consumption" template below is never written in this package, so it stayed - # stuck at "unknown" in HA. Hide it instead of shipping dead weight. + # The Shelly EM3 only exposes a net power (total_act_power), so the per-phase + # "consumption" template inherited from power_meter_common.yaml is never + # written from this package. Hide it instead of shipping a dead entity. consumption_sensor_internal: "true" # This package specifics power_meter_emeter_id: "0" @@ -51,7 +48,7 @@ http_request: verify_ssl: False script: - # Poll the Em3 meter and publish the grid-exchange power (total_act_power) + # Poll the EM3 meter and publish the grid-exchange power (total_act_power) - id: power_meter_source mode: single then: @@ -109,26 +106,10 @@ script: - lambda: |- id(real_power).publish_state(NAN); -# Sense the per-phase active powers for debugging / tuning (hidden by default) +# Per-phase active powers for debugging / tuning (hidden by default). +# real_power / consumption template sensors come from power_meter_common.yaml +# via the `packages:` include; no need (and no room) to redeclare them here. sensor: - # Re-declared from power_meter_common.yaml: the '<<' merge only keeps the - # FIRST definition of a key, and this file defines its own 'sensor:' section. - # The engine depends on these two template sensors. - - id: real_power - platform: template - name: "Real Power" - device_class: "power" - unit_of_measurement: "W" - update_interval: 1s - - - id: consumption - platform: template - name: "Consumption" - device_class: "power" - unit_of_measurement: "W" - update_interval: 1s - internal: ${consumption_sensor_internal} - - platform: template id: em3_phase_a_power name: "EM3 Phase A Active Power" @@ -161,10 +142,8 @@ time: # if a future ESPHome release fixes the http_request/IDF transport reuse race. - platform: sntp on_time: + # Poll unconditionally so real_power stays fresh in HA even when + # the router's `activate` switch is off. - seconds: /2 then: - - if: - condition: - - lambda: return id(power_meter_activated) != 0; - then: - - script.execute: power_meter_source \ No newline at end of file + - script.execute: power_meter_source From 293fef493a7e89d584264d02300ed25ed9edc21e Mon Sep 17 00:00:00 2001 From: Xavier Berger Date: Thu, 13 Aug 2026 21:01:42 +0200 Subject: [PATCH 3/3] refactor(temperature_limiter): switch to `packages:` include syntax MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Aligns temperature_limiter_DS18B20.yaml and temperature_limiter_home_assistant.yaml with the same include-syntax change already applied to every power_meter_*.yaml: replaces `<<: !include temperature_limiter_common.yaml` with a `packages:` block, and pins `esphome.min_version: 2025.5.0` since the merge-map form of `!include` was retired in newer ESPHome releases. Also fixes a typo in the header comment (temperaturewer → temperature). Co-Authored-By: Claude Opus 4.7 --- solar_router/temperature_limiter_DS18B20.yaml | 6 +++++- solar_router/temperature_limiter_home_assistant.yaml | 8 ++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/solar_router/temperature_limiter_DS18B20.yaml b/solar_router/temperature_limiter_DS18B20.yaml index 023cde1..739402f 100644 --- a/solar_router/temperature_limiter_DS18B20.yaml +++ b/solar_router/temperature_limiter_DS18B20.yaml @@ -1,9 +1,13 @@ +esphome: + min_version: 2025.5.0 + substitutions: DS18B20_address: "0" temperature_update_interval: 5s red_led_inverted: "False" -<<: !include temperature_limiter_common.yaml +packages: + - !include temperature_limiter_common.yaml one_wire: - platform: gpio diff --git a/solar_router/temperature_limiter_home_assistant.yaml b/solar_router/temperature_limiter_home_assistant.yaml index 3f9b2f7..8bfa109 100644 --- a/solar_router/temperature_limiter_home_assistant.yaml +++ b/solar_router/temperature_limiter_home_assistant.yaml @@ -1,10 +1,14 @@ # ---------------------------------------------------------------------------------------------------- -# Define sensor for temperaturewer collection +# Define sensor for temperature collection # ---------------------------------------------------------------------------------------------------- +esphome: + min_version: 2025.5.0 + substitutions: red_led_inverted: "False" -<<: !include temperature_limiter_common.yaml +packages: + - !include temperature_limiter_common.yaml sensor: # Sensor showing the temprature to monitor