Skip to content

[codex] Add historical cost tracking - #33

Merged
LordMike merged 18 commits into
mainfrom
codex/historical-cost-tracking
Jun 19, 2026
Merged

[codex] Add historical cost tracking#33
LordMike merged 18 commits into
mainfrom
codex/historical-cost-tracking

Conversation

@LordMike

@LordMike LordMike commented May 24, 2026

Copy link
Copy Markdown
Owner

Fixes #28

Summary

Adds opt-in historical cost tracking backed by one private Home Assistant Store per WattPlan config entry (wattplan.history.<entry_id>). The store keeps explicit UTC slot starts, one shared set of raw slot facts, self-consumption simulation outputs, and persisted self-consumption battery SoC state with fixed 60-day local-day retention.

Scenario semantics

  • actual: measured grid import cost minus measured grid export value.
  • no_battery: recomputed from retained usage/PV facts without duplicate raw storage.
  • self_consumption: PV serves usage first, PV surplus charges configured batteries in order, batteries discharge before grid import, with no grid charging, no price awareness, and no preserve behavior.

Design notes

  • Uses HA Store rather than recorder, SQLite, or backfill because V1 only needs a compact WattPlan-owned retention window and must avoid rewriting historical simulated results from later config changes.
  • Saves are delayed/coalesced and flushed on unload or Home Assistant stop.
  • Skipped slots, meter resets, missing/non-numeric meters, and missing prices are flagged as gaps/missing slots instead of spreading meter deltas across varying prices.
  • Historical tracking is independent of planner execution and aligned to the configured slot size.
  • EV availability/presence is intentionally deferred to Support EV battery availability and controllability #32.

Entity changes

Adds daily historical cost/savings sensors enabled by default when historical tracking is enabled, with monthly variants disabled by default. Removes the user-facing projected savings HA entities from setup/specs/docs/tests; existing HA registry entries are left for user cleanup.

Tests run

  • WATTPLAN_TEST_VENV=/tmp/wattplan-venv-shared ./scripts/run_tests.sh tests/integration/test_config_flow.py tests/integration/test_integration_runtime.py tests/optimizer
  • WATTPLAN_TEST_VENV=/tmp/wattplan-venv-shared ./scripts/run_tests.sh

@LordMike
LordMike marked this pull request as ready for review May 24, 2026 22:01
Comment thread custom_components/wattplan/translations/en.json Outdated
Comment thread custom_components/wattplan/translations/en.json
Comment thread docs/architecture.md Outdated
Comment thread docs/architecture.md Outdated
Comment thread docs/entities-and-services.md Outdated

Copy link
Copy Markdown
Owner Author

Review findings from PR #33:

  • P1 custom_components/wattplan/historical_cost/tracker.py:213 / :227 / :150: first seed can create a bogus partial slot. If tracking is enabled at 12:30, _async_seed() reads meters at 12:30 but marks last_processed_slot as 11:00. At 13:05 it records slot 12:00 using the 12:30-13:05 meter delta. That contaminates the first day/month after enable, restart with missing cursors, or meter config changes.

  • P2 custom_components/wattplan/historical_cost/tracker.py:328: export price “not used” no longer behaves as zero when an export meter is configured. _async_export_price() returns None, then the slot gets FLAG_MISSING_EXPORT_PRICE, making all scenario costs unavailable. This contradicts README.md:37 and planner behavior where missing export price means exported power value is zero.

  • P2 custom_components/wattplan/historical_cost/simulations.py:98: self-consumption discharge capacity is reduced by efficiency twice. max_discharge_kwh is already delivered kWh per slot per docs/optimizer-api.md, and SoC drop already applies output / efficiency, so max_output = battery.max_discharge_kwh * efficiency underestimates discharge and biases the self-consumption baseline.

  • P2 custom_components/wattplan/historical_cost/tracker.py:152: skipped intervals are under-counted. If Home Assistant misses several slots, the tracker appends one gap at the latest completed slot and seeds past the rest, so missing_slots reports 1 instead of the number of missed slot starts.

I could not run local tests from this environment because command execution could not start a shell, but GitHub CI for head 112a4a4 reports success.

@LordMike
LordMike merged commit 2b1402e into main Jun 19, 2026
1 check passed
@LordMike
LordMike deleted the codex/historical-cost-tracking branch June 19, 2026 13:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Projected savings needs.. help

1 participant