Skip to content

feat: EV priority Home Assistant blueprint - #161

Closed
XavierBerger wants to merge 2 commits into
mainfrom
feat/priority_to_ev
Closed

feat: EV priority Home Assistant blueprint#161
XavierBerger wants to merge 2 commits into
mainfrom
feat/priority_to_ev

Conversation

@XavierBerger

Copy link
Copy Markdown
Member

Summary

  • Adds blueprints/priority_to_ev.yaml, a Home Assistant blueprint that gives the EV charger priority over the Solar Router's diversion load whenever there is enough solar surplus to run the EV, and reactivates the router once the EV is full or unplugged.
  • Ships the reference doc as docs/en/blueprint_priority_to_ev.md (with French stub) and a corrected truth-table page docs/en/blueprint_use_cases.md; both wired into mkdocs.yml.
  • Adds a top-level AGENTS.md describing the project's layout, package system, and conventions for AI assistants working on the repo.

Design decisions

  • numeric_state triggers list both grid_power and diverted_power in entity_id. Home Assistant only re-evaluates the template when a listed entity changes — the classic blueprint pitfall is to list only the grid sensor, in which case a rising diverted value with a flat grid never re-fires the trigger. Both entities are listed so every surplus change is observed.
  • Anti-flicker ev_soc guard. Once ev_soc >= ev_full_soc (default 100 %), Condition 1 is blocked and the router is not deactivated. This is what makes the "never stop at full" behaviour actually happen in code. Users without an SOC sensor can raise ev_full_soc to 101 % to disable the guard.
  • mode: queued, max: 2 avoids the sunrise-recovery race in which both numeric-state triggers cross their thresholds simultaneously and one is dropped under mode: single.
  • Plug/unplug debounce. ev_connected state triggers use for: !input delay_before_deactivation / delay_before_activation, so a connector wiggle can't slam the router.
  • has_value(...) guards on the surplus template and Condition 1 treat sensor drop-outs as 0 W surplus rather than 0-substituted phantom surplus that could spuriously deactivate the router.
  • homeassistant.min_version: 2024.8.0 pinned for action: keys, trigger_variables + !input, and has_value().

Docs

  • docs/en/blueprint_priority_to_ev.md — full algorithm, worked "day in the life" example, and a Known-behavior section covering overnight lockout, sensor drop-outs, plug debounce, SOC unavailability, and reload semantics.
  • docs/en/blueprint_use_cases.md — corrected truth table (a prior draft had row 5 vs row 7 diverging on identical inputs, row 10 acting on a surplus below ev_full_threshold, and row 11 arithmetic inconsistent with the shown numbers).
  • French stubs added under docs/fr/; mkdocs.yml nav updated for both locales.

Test plan

  • Import the blueprint into Home Assistant and confirm all inputs render.
  • Walk a scripted state sequence covering every row of the truth table (particularly rows 5/7/10/11/12 and boundary rows 13/14).
  • Force diverted_power to unavailable mid-run and confirm the router does not flip.
  • mkdocs serve locally and confirm the new pages appear under both /en/ and /fr/ navs.

🤖 Generated with Claude Code

Xavier Berger and others added 2 commits August 13, 2026 20:56
Adds `blueprints/priority_to_ev.yaml`, a Home Assistant blueprint that
gives an EV charger priority over the Solar Router's diversion load
whenever enough solar surplus is available to run the EV. When the EV
is full, when it is unplugged, or when surplus reappears in the grid
export, the router is turned back on to resume diversion.

Design notes worth flagging for review:

- The two `numeric_state` triggers list both `grid_power` and
  `diverted_power` in `entity_id`, so a rising diverted value with a
  flat grid still re-evaluates the template. Listing only `grid_power`
  is the classic HA blueprint bug where the template never re-fires.
- Anti-flicker `ev_soc` guard: once the EV reports SOC >= `ev_full_soc`
  (default 100 %), Condition 1 is blocked and the router will not be
  deactivated to give the EV priority. This is the mechanism behind the
  "never stop at full" rows in the use-case table. Users without a SOC
  sensor can raise `ev_full_soc` to 101 % to disable the guard.
- `mode: queued, max: 2` avoids the sunrise-recovery race where both
  numeric_state triggers cross their thresholds simultaneously and one
  is dropped under `mode: single`.
- Plug/unplug transitions are debounced with
  `delay_before_deactivation` / `delay_before_activation` so a brief
  connector wiggle can't slam the router.
- `has_value(...)` guards on the surplus template and Condition 1's
  template treat sensor drop-outs as 0 W surplus, so an `unavailable`
  reading can no longer force a spurious deactivation.
- `homeassistant.min_version: 2024.8.0` pinned for `action:` keys,
  `trigger_variables` + `!input`, and `has_value()`.

Docs land under `docs/en/` alongside the rest of the site (with French
stubs and mkdocs.yml nav entries):

- `blueprint_priority_to_ev.md` — algorithm, worked "day in the life"
  example, and a Known-behavior section covering overnight lockout,
  sensor drop-outs, and the SOC guard.
- `blueprint_use_cases.md` — corrected truth table. The earlier draft
  had row 5 vs row 7 diverging on identical inputs (blueprint is
  stateless w.r.t. "why surplus dropped"), row 10 acting on a surplus
  below `ev_full_threshold`, and row 11 arithmetic inconsistent with
  the numbers shown.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Adds a top-level AGENTS.md summarising the project's repository layout,
package architecture, YAML conventions, docs workflow, and common tasks
so an AI assistant onboarded onto this repo has a single reference to
work from.

Verified claims against the working tree:

- Repository structure lists directories that actually exist.
- Tool references (`tools/check_documentation_coverage.sh`,
  `check_build_coverage.sh`, `compile_all_local_yaml.sh`,
  `update_documentation.sh`, `http_server_simulator.py`) exist.
- `cliff.toml` reference verified.
- `power_meter_source` script contract is described from the actual
  package pattern (SNTP `on_time` → script publishes `real_power` /
  `consumption`).

Choices explicitly avoided:

- No hardcoded per-board `min_version` — pins vary between boards
  (2026.1.0 on `esp32-standalone.yaml`, 2025.9.0 on
  `esp32-JSY-MK-194T.yaml`), so the template points at the target YAML
  header instead of a single "2026.x.x" placeholder.
- No `release/vX.Y.Z` branch convention — releases are tagged on
  `main`, not cut on a long-lived release branch.
- No hardcoded LED / triac / zero-crossing GPIO numbers — pins are
  parameterised via substitutions and vary per board. The doc points
  the reader at the substitutions block in each device YAML.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
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.

1 participant