WIP: ✨ Real-time energy via trapezoidal ∫W·dt over the live power stream (streaming 4/5) #59
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "feat/stream-energy"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Slice 4 of 5 (stacked on #58). The energy total now rises in real time with the power stream, instead of jumping once per hour with a 1h offset.
What
_EnergyStateextended withlast_power_w/last_power_t/live_total_wh/live_by_hour(UTC-hour buckets, populated for Slice 5).ComwattCoordinator.integrate_live_energy(device_powers): trapezoidaldelta_Wh = (W_now + W_prev) / 2 × dt_hours, seeded from the poll'stotal_whon the first stream burst, bucketed by UTC calendar hour intolive_by_hour._fetch_device_metricsearly-returnsenergy = live_total_wh(no QUANTITY fetch) once the stream has taken over → prevents double-counting between the poll's bucket accumulation and the stream's ∫W·dt.stream.py: extracted_compute_device_powerspure helper;_apply_power_updatessignature refactored to(device_powers, devices_data);_process_batchintegrates live energy on every batch then notifies viaasync_update_listeners().Why trapezoidal + separate live_total_wh
The stream pushes power (~15s); energy = ∫W·dt. A separate
live_total_wh(seeded from the poll, then stream-owned) avoids double-counting the server's hourly QUANTITY buckets against the live accumulation. The 1h offset (#5/#42) dissolves because the energy is computed at the actual moment of consumption —last_updatedis correct by construction, no backdating needed.Scope / merge-safety
UPDATE_INTERVALunchanged (2 min). QUANTITY fetch NOT removed (Slice 5 re-uses it for reconciliation). No reconciliation in this slice —live_by_houris populated but not consumed.coordinator.py,stream.py,test_coordinator.py,test_stream.py.Tests
6 new tests (T7-T12) + 4 updated. T8/T9/T12 assert exact trapezoidal values with patched clocks (not sleeps). T10 verifies the double-count prevention (QUANTITY skipped when stream active). 63/63 passing, ruff + mypy clean.
Drift note
If the stream permanently dies, the energy freezes at the last live value until HA restart. Slice 5's reconciliation (vs server QUANTITY/HOUR for completed UTC hours) bounds this drift — that's the final slice.
Stacking
Base:
feat/stream-power(PR #58). Rebase once #58 merges.Landed in
mainvia the linear stack fast-forward (commit9d016f7). This slice is part of the streaming feature merged as #56…#62 — closing (its commits are already inmain).Pull request closed