Home Assistant blueprint β Priority to EVΒΆ
What it doesΒΆ
When an EV is plugged into a smart charger (MyEnergi Zappi, OpenEVSE, Wallbox Quasar, β¦) that already does its own surplus-following logic, you generally want the car to win the surplus, not the Solar Router's water heater. This blueprint arbitrates between the two:
- When the surplus is large enough for long enough, it turns the Solar Router off so the surplus is released to the grid, where the EV charger picks it up.
- When the EV is unplugged, a cloud cuts PV production and the house starts importing from the grid, or the EV stops taking the surplus (car full, paused, or tapering finished), it turns the Solar Router back on so the water heater catches whatever remains.
The router firmware itself does not talk to the EV charger β the blueprint only toggles the router's Activate Solar Routing switch. Everything else stays in the charger's own hands.
Install itΒΆ
SignalsΒΆ
Handoff (router ON β OFF)ΒΆ
grid_poweris signed: positive when importing, negative when exporting. That's the sign convention shipped by default in the Solar Router firmware (power_sign: "1").diverted_poweris the router's ownPower divertionsensor β always positive, zero when the router is off.
The router is turned OFF when surplus > EV_Charging_Minimum_Surplus holds continuously for surplus_duration_trigger seconds, provided the EV is plugged in and (if a SoC sensor is set) still below target.
Restore (router OFF β ON)ΒΆ
Once the router is OFF and the EV is drawing on solar, the surplus formula collapses to ~0: diverted_power = 0 because the router is off, and grid_power β 0 because the EV consumes what PV produces. The blueprint would then be unable to tell a cloud from ordinary charging. Instead, it watches grid_power directly:
grid_power > cloud_import_thresholdfor N s β we are importing β PV can no longer cover the EV β cloud arrived.-grid_power > release_export_thresholdfor N s β we are exporting β the EV isn't taking the surplus β EV done, paused or capped.
Plus one immediate signal that doesn't need debouncing:
- EV unplugged (
ev_connectedtransitions tooff)
The SoC target is deliberately not an immediate restore signal. Most cars keep charging past a user-set target at reduced power, and turning the router back ON at that instant would fight the EV for the tail-end energy. The blueprint waits for -grid_power > release_export_threshold β i.e. the car has actually stopped drawing β to restore the router. The SoC target still gates new handoffs (see Behavior).
BehaviorΒΆ
HANDOFF (router ON β OFF), when this stays true for surplus_duration_trigger s:
ev_connected == on
AND solar_router == on
AND ( ev_soc_entity is empty OR ev_soc < ev_soc_target )
AND surplus > EV_Charging_Minimum_Surplus
RESTORE (router OFF β ON), on any of:
ev_connected transitions to off [immediate]
grid_power > cloud_import_threshold for surplus_duration_trigger s [cloud]
-grid_power > release_export_threshold for surplus_duration_trigger s [EV done]
The two level-based triggers use HA template triggers with for:, so a brief spike either way is absorbed and never toggles the router. Crossing ev_soc_target freezes the handoff (no fresh router-OFF) but does not by itself restore the router β the export threshold handles that once the car actually stops drawing.
InputsΒΆ
| Input | Purpose | Default |
|---|---|---|
ev_connected | Binary sensor, ON when the EV is plugged in | required |
ev_soc | (optional) SoC sensor, % | empty |
ev_soc_target | Above this SoC no new handoff β restore still waits for real export | 80 |
grid_power | Signed grid power in W (+ import, β export) | required |
diverted_power | Solar Router's Power divertion sensor | required |
solar_router | The Activate Solar Routing switch to toggle | required |
ev_charging_minimum_surplus | Surplus threshold for handoff in W | 1400 |
cloud_import_threshold | Import threshold for cloud detection in W | 200 |
release_export_threshold | Export threshold for "EV done" detection in W | 200 |
surplus_duration_trigger | Debounce for all three level triggers in s | 60 |
Requirement: keep Real Power alive while the router is OFFΒΆ
Before this version, turning the Activate Solar Routing switch OFF also stopped the meter polling and forced Real Power to NaN. The blueprint would then be blind exactly when it most needs eyes β with Option-3 signals, that would mean not being able to detect either the cloud OR the EV-done cases. The firmware shipped with this blueprint keeps the native power meters polling continuously and no longer publishes NaN on shutdown. No user action is required if you flash the matching firmware version.
A day in the lifeΒΆ
Handoff threshold 1400 W, cloud & release thresholds 200 W each, debounce 60 s.
Top strip: numbered events (see caption below the figure). Middle panel: PV production (yellow), household baseline + water heater + EV stacked; the blue outline is the total consumption. Bottom panel: signed grid exchange (import above zero, export below) and the dashed blueprint surplus curve plotted on the export side.
| Time | Situation | grid_power | diverted | Router | Action |
|---|---|---|---|---|---|
| 06:00 | Night ending, no PV | +300 (import) | 0 | ON idle | β |
| 09:00 | PV ramps, EV plugged, SoC 40 % | β1600 | 200 | ON diverting | β (debounce running) |
| 09:01 | Handoff template stable > 60 s | β1650 | 200 | OFF | give priority to EV |
| 09:02 | EV drawing, PV matched | β 0 | 0 | OFF | β (grid stable, no restore) |
| 10:30 | Big cloud, EV keeps drawing from grid | +800 | 0 | ON | cloud detected β router restored |
| 11:00 | Sun back, surplus > 1400 for 60 s | β2500 | (rising) | OFF | EV again |
| 15:00 | SoC hits target (80 %), car keeps tapering | β 0 | 0 | OFF | β (handoff frozen, but EV still draws) |
| 15:30 | EV self-stops on full, export stable > 60 s | β1500 | 0 | ON | export release β router restored |
| 20:00 | EV unplugged | β200 | 100 | ON | β |
Wiring an EV plug sensor (MyEnergi Zappi example)ΒΆ
If your charger only exposes a text status, wrap it in a template binary sensor:
template:
- binary_sensor:
- name: EV plugged in
device_class: plug
state: >-
{{ states('sensor.myenergi_zappi_plug_status')
in ['EV Connected', 'Waiting for EV', 'Charging', 'Boosting', 'Complete'] }}
InstallationΒΆ
Import the blueprint into Home Assistant:
- Settings β Automations & Scenes β Blueprints β Import Blueprint
- Paste the raw URL of
blueprints/priority_to_ev.yamlin this repository.
Create an automation from the imported blueprint and fill in the inputs.
Edge casesΒΆ
- Brief cloud (<
surplus_duration_triggers) β the router stays off; the debounce absorbs it. - HA restart mid-charge β the automation re-evaluates on
homeassistant.start, but the restore branch only fires if a real restore reason holds (unplug / cloud / EV done). A restart during a stable handoff is a no-op. - Sensor
unavailableβ every level trigger useshas_value()guards; ifgrid_powerordiverted_powerdrops out, no restore is triggered. - User manually turns the router ON while EV is plugged and surplus is high β the next handoff cycle (60 s) will turn it back off. If you want to disable the automation temporarily, disable the automation itself in HA.
- Charger with a small export margin (some chargers leave 100 W going to the grid even at max) β set
release_export_thresholdabove that margin (e.g. 200β300 W) to avoid a false "EV done" detection. - Household load spikes (dishwasher starts) β a large kitchen appliance can push
grid_powerbriefly positive; the 60 s debounce absorbs a normal cycle, but a sustained heavy load will trigger the cloud branch. Raisecloud_import_thresholdif this is a frequent nuisance.
