Skip to content

Commit 67a1c10

Browse files
committed
docs: phase A energy package and clean-up decisions
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DPAUqfZW6rUEbebKuuXncP
1 parent 3111bae commit 67a1c10

2 files changed

Lines changed: 289 additions & 7 deletions

File tree

‎docs/energy_sensors_plan.md‎

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -109,10 +109,12 @@ Energy (kWh; integral `method: left`, `max_sub_interval: 1 min`; utility meters
109109
7. **Integration v0.6.0**: map `HOUSE_W`, switch battery gains to measured Solis losses, finish
110110
Option B (household factor from clean data).
111111

112-
## 6. Open points
113-
114-
* Keep or retire PredAI?
115-
* The `ashp_heating/dhw_power_consumption_*` templates are YAML (not readable via the API): paste
116-
them, or confirm they can be replaced by the new split.
117-
* DHW signal for the split: `binary_sensor.bridge0_dhw_dhw_demand` vs the 3-way valve sensor — to be
118-
checked against the meter in phase A.
112+
## 6. Decisions (10 Oct 2026)
113+
114+
* PredAI is **retired** (its forecast was not used by Predbat); remove the add-on and
115+
`sensor.total_house_consumption_prediction`.
116+
* The YAML templates `ashp_{heating,dhw}_power_consumption_*` are **replaced** by utility meters on
117+
the metered split (`heat_pump_{heating,dhw}_energy_*`; renamed to the ashp_* IDs in phase B).
118+
* DHW split signal: `binary_sensor.bridge0_dhw_dhw_demand` (the 3-way valve rests on "tank" when
119+
idle, so it cannot separate DHW from standby). 4–10 Oct: 6.8 kWh DHW, 2.3 kWh standby.
120+
* Phase A package: `docs/ha/packages/energy.yaml` (all templates rendered live without errors).

‎docs/ha/packages/energy.yaml‎

Lines changed: 280 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,280 @@
1+
# Canonical energy sensors — PHASE A (new sensors only; nothing existing is changed)
2+
# Plan and rationale: docs/energy_sensors_plan.md
3+
#
4+
# Install:
5+
# 1. configuration.yaml: homeassistant:
6+
# packages: !include_dir_named packages
7+
# 2. copy this file to /config/packages/energy.yaml
8+
# 3. Developer tools → YAML → Check configuration, then restart Home Assistant.
9+
#
10+
# Sign conventions: grid + = import; Solis AC + = inverter delivering to the house (− = charging from
11+
# the grid); battery + = discharging; generation and loads ≥ 0.
12+
#
13+
# The four sensors ending in "_new" are the replacements for the faulty helpers solis_power,
14+
# pv_power, house_power and total_house_consumption. Phase B (after 3–7 days of comparison) gives
15+
# them the old entity IDs; until then the old helpers stay untouched.
16+
17+
template:
18+
- sensor:
19+
# --- power (W) ---------------------------------------------------------------------------
20+
- name: "Grid power"
21+
unique_id: energy_grid_power_new
22+
default_entity_id: sensor.solis_power_new
23+
unit_of_measurement: W
24+
device_class: power
25+
state_class: measurement
26+
# Glow/Hildebrand smart meter; Solis CT (≈ −0.94 × smart meter + 53 W) only as fallback.
27+
state: >
28+
{% set sm = states('sensor.smart_meter_electricity_power') %}
29+
{% if is_number(sm) %}{{ sm | float | round(0) }}
30+
{% else %}{{ ((53 - states('sensor.solis_meter_active_power') | float) / 0.94) | round(0) }}
31+
{% endif %}
32+
availability: >
33+
{{ is_number(states('sensor.smart_meter_electricity_power'))
34+
or is_number(states('sensor.solis_meter_active_power')) }}
35+
36+
- name: "PV power"
37+
unique_id: energy_pv_power_new
38+
default_entity_id: sensor.pv_power_new
39+
unit_of_measurement: W
40+
device_class: power
41+
state_class: measurement
42+
# Solis PV (DC, garage) + roof GW2000 (HomeWizard meter, export negative) + shed micro-inverter
43+
state: >
44+
{{ (states('sensor.solis_pv_total_power') | float(0)
45+
+ [0, -(states('sensor.kwh_meter_power_2') | float(0))] | max
46+
+ states('sensor.shed_power_ac') | float(0)) | round(0) }}
47+
availability: >
48+
{{ is_number(states('sensor.solis_pv_total_power'))
49+
and is_number(states('sensor.kwh_meter_power_2')) }}
50+
51+
- name: "House power"
52+
unique_id: energy_house_power_new
53+
default_entity_id: sensor.house_power_new
54+
unit_of_measurement: W
55+
device_class: power
56+
state_class: measurement
57+
# AC side: grid + Solis AC output + roof (net, incl. its standby) + shed.
58+
# Excludes the Solis conversion/standby losses (see solis_loss_power).
59+
state: >
60+
{% set grid = states('sensor.solis_power_new') | float(0) %}
61+
{% set solis = states('sensor.solis_active_power') | float(0) %}
62+
{% set roof = -(states('sensor.kwh_meter_power_2') | float(0)) %}
63+
{% set shed = states('sensor.shed_power_ac') | float(0) %}
64+
{{ [grid + solis + roof + shed, 0] | max | round(0) }}
65+
availability: >
66+
{{ has_value('sensor.solis_power_new')
67+
and is_number(states('sensor.solis_active_power'))
68+
and is_number(states('sensor.kwh_meter_power_2')) }}
69+
70+
- name: "Solis loss power"
71+
unique_id: energy_solis_loss_power
72+
default_entity_id: sensor.solis_loss_power
73+
unit_of_measurement: W
74+
device_class: power
75+
state_class: measurement
76+
# Conversion + standby losses of the Solis (inside the house): PV + battery − AC output.
77+
state: >
78+
{{ [states('sensor.solis_pv_total_power') | float(0)
79+
+ states('sensor.battery_power') | float(0)
80+
- states('sensor.solis_active_power') | float(0), 0] | max | round(0) }}
81+
availability: >
82+
{{ is_number(states('sensor.solis_pv_total_power'))
83+
and is_number(states('sensor.battery_power'))
84+
and is_number(states('sensor.solis_active_power')) }}
85+
86+
- name: "Heat pump power"
87+
unique_id: energy_heat_pump_power
88+
default_entity_id: sensor.heat_pump_power
89+
unit_of_measurement: W
90+
device_class: power
91+
state_class: measurement
92+
state: "{{ [states('sensor.kwh_meter_power') | float(0), 0] | max | round(0) }}"
93+
availability: "{{ is_number(states('sensor.kwh_meter_power')) }}"
94+
95+
# Split of the metered heat-pump power. The 3-way valve rests on "tank" when idle, so the
96+
# DHW demand signal is used (4–10 Oct 2026: 6.8 kWh DHW, 2.3 kWh standby, heating ≈ 0).
97+
- name: "Heat pump DHW power"
98+
unique_id: energy_heat_pump_dhw_power
99+
default_entity_id: sensor.heat_pump_dhw_power
100+
unit_of_measurement: W
101+
device_class: power
102+
state_class: measurement
103+
state: >
104+
{{ states('sensor.heat_pump_power') | float(0)
105+
if is_state('binary_sensor.bridge0_dhw_dhw_demand', 'on') else 0 }}
106+
availability: >
107+
{{ has_value('sensor.heat_pump_power')
108+
and has_value('binary_sensor.bridge0_dhw_dhw_demand') }}
109+
110+
- name: "Heat pump heating power"
111+
unique_id: energy_heat_pump_heating_power
112+
default_entity_id: sensor.heat_pump_heating_power
113+
unit_of_measurement: W
114+
device_class: power
115+
state_class: measurement
116+
# space heating: compressor or circulation pump running without DHW demand (incl. defrost)
117+
state: >
118+
{% set running = is_state('binary_sensor.bridge0_mode_compressor', 'on')
119+
or is_state('binary_sensor.bridge0_mode_circulation_pump', 'on') %}
120+
{{ states('sensor.heat_pump_power') | float(0)
121+
if running and not is_state('binary_sensor.bridge0_dhw_dhw_demand', 'on') else 0 }}
122+
availability: >
123+
{{ has_value('sensor.heat_pump_power')
124+
and has_value('binary_sensor.bridge0_dhw_dhw_demand')
125+
and has_value('binary_sensor.bridge0_mode_compressor')
126+
and has_value('binary_sensor.bridge0_mode_circulation_pump') }}
127+
128+
- name: "Heat pump standby power"
129+
unique_id: energy_heat_pump_standby_power
130+
default_entity_id: sensor.heat_pump_standby_power
131+
unit_of_measurement: W
132+
device_class: power
133+
state_class: measurement
134+
state: >
135+
{{ [states('sensor.heat_pump_power') | float(0)
136+
- states('sensor.heat_pump_dhw_power') | float(0)
137+
- states('sensor.heat_pump_heating_power') | float(0), 0] | max }}
138+
availability: >
139+
{{ has_value('sensor.heat_pump_dhw_power') and has_value('sensor.heat_pump_heating_power') }}
140+
141+
- name: "House power excl. heating"
142+
unique_id: energy_house_power_excl_heating
143+
default_entity_id: sensor.house_power_excl_heating
144+
unit_of_measurement: W
145+
device_class: power
146+
state_class: measurement
147+
# household load for Predbat/Predheat: space heating removed, DHW and standby kept
148+
state: >
149+
{{ [states('sensor.house_power_new') | float(0)
150+
- states('sensor.heat_pump_heating_power') | float(0), 0] | max }}
151+
availability: >
152+
{{ has_value('sensor.house_power_new') and has_value('sensor.heat_pump_heating_power') }}
153+
154+
- name: "House power excl. heat pump"
155+
unique_id: energy_house_power_excl_heat_pump
156+
default_entity_id: sensor.house_power_excl_heat_pump
157+
unit_of_measurement: W
158+
device_class: power
159+
state_class: measurement
160+
state: >
161+
{{ [states('sensor.house_power_new') | float(0)
162+
- states('sensor.heat_pump_power') | float(0), 0] | max }}
163+
availability: >
164+
{{ has_value('sensor.house_power_new') and has_value('sensor.heat_pump_power') }}
165+
166+
# --- energy (kWh): integrals of the power sensors ---------------------------------------------
167+
sensor:
168+
- platform: integration
169+
source: sensor.house_power_new
170+
name: House energy total
171+
unique_id: energy_house_energy_total
172+
method: left
173+
round: 3
174+
unit_prefix: k
175+
unit_time: h
176+
max_sub_interval:
177+
minutes: 1
178+
- platform: integration
179+
source: sensor.house_power_excl_heating
180+
name: House energy excl heating total
181+
unique_id: energy_house_energy_excl_heating_total
182+
method: left
183+
round: 3
184+
unit_prefix: k
185+
unit_time: h
186+
max_sub_interval:
187+
minutes: 1
188+
- platform: integration
189+
source: sensor.solis_loss_power
190+
name: Solis loss energy total
191+
unique_id: energy_solis_loss_energy_total
192+
method: left
193+
round: 3
194+
unit_prefix: k
195+
unit_time: h
196+
max_sub_interval:
197+
minutes: 1
198+
- platform: integration
199+
source: sensor.heat_pump_dhw_power
200+
name: Heat pump DHW energy total
201+
unique_id: energy_heat_pump_dhw_energy_total
202+
method: left
203+
round: 3
204+
unit_prefix: k
205+
unit_time: h
206+
max_sub_interval:
207+
minutes: 1
208+
- platform: integration
209+
source: sensor.heat_pump_heating_power
210+
name: Heat pump heating energy total
211+
unique_id: energy_heat_pump_heating_energy_total
212+
method: left
213+
round: 3
214+
unit_prefix: k
215+
unit_time: h
216+
max_sub_interval:
217+
minutes: 1
218+
- platform: integration
219+
source: sensor.heat_pump_standby_power
220+
name: Heat pump standby energy total
221+
unique_id: energy_heat_pump_standby_energy_total
222+
method: left
223+
round: 3
224+
unit_prefix: k
225+
unit_time: h
226+
max_sub_interval:
227+
minutes: 1
228+
229+
# --- daily / periodic counters ------------------------------------------------------------------
230+
utility_meter:
231+
total_house_consumption_new:
232+
unique_id: energy_total_house_consumption_new
233+
source: sensor.house_energy_total
234+
cycle: daily
235+
house_load_excl_heating_daily:
236+
unique_id: energy_house_load_excl_heating_daily
237+
source: sensor.house_energy_excl_heating_total
238+
cycle: daily
239+
solis_loss_energy_daily:
240+
unique_id: energy_solis_loss_energy_daily
241+
source: sensor.solis_loss_energy_total
242+
cycle: daily
243+
# Replacements for the broken YAML templates ashp_{heating,dhw}_power_consumption_* (phase B
244+
# renames these keys to the ashp_* names after the old templates are removed).
245+
heat_pump_dhw_energy_daily:
246+
unique_id: energy_heat_pump_dhw_energy_daily
247+
source: sensor.heat_pump_dhw_energy_total
248+
cycle: daily
249+
heat_pump_dhw_energy_weekly:
250+
unique_id: energy_heat_pump_dhw_energy_weekly
251+
source: sensor.heat_pump_dhw_energy_total
252+
cycle: weekly
253+
heat_pump_dhw_energy_monthly:
254+
unique_id: energy_heat_pump_dhw_energy_monthly
255+
source: sensor.heat_pump_dhw_energy_total
256+
cycle: monthly
257+
heat_pump_dhw_energy_annually:
258+
unique_id: energy_heat_pump_dhw_energy_annually
259+
source: sensor.heat_pump_dhw_energy_total
260+
cycle: yearly
261+
heat_pump_heating_energy_daily:
262+
unique_id: energy_heat_pump_heating_energy_daily
263+
source: sensor.heat_pump_heating_energy_total
264+
cycle: daily
265+
heat_pump_heating_energy_weekly:
266+
unique_id: energy_heat_pump_heating_energy_weekly
267+
source: sensor.heat_pump_heating_energy_total
268+
cycle: weekly
269+
heat_pump_heating_energy_monthly:
270+
unique_id: energy_heat_pump_heating_energy_monthly
271+
source: sensor.heat_pump_heating_energy_total
272+
cycle: monthly
273+
heat_pump_heating_energy_annually:
274+
unique_id: energy_heat_pump_heating_energy_annually
275+
source: sensor.heat_pump_heating_energy_total
276+
cycle: yearly
277+
heat_pump_standby_energy_daily:
278+
unique_id: energy_heat_pump_standby_energy_daily
279+
source: sensor.heat_pump_standby_energy_total
280+
cycle: daily

0 commit comments

Comments
 (0)