With v2.0.0 landing the "Immediate" phase of docs/roadmap/configflow_approach.md (#60, #136), I'd like to open a place to discuss the next step — deliveries and scenarios in the UI — before anyone (me included) writes more code in the wrong direction. Splitting it out of the closed threads so it's easy to find.
I have three pieces of work sitting on my fork that are relevant. None of them need to land as-is; I'm listing them so you can pick what's useful and reject the rest.
- Deliveries as config subentries (prototype, working end-to-end)
A DeliverySubentryFlowHandler (ConfigSubentryFlow, HA 2025.3+ API) that creates/edits/removes a delivery from the integration page. Typed fields for transport (SelectSelector), enabled, priority, occupancy, selection, action, target, plus an ObjectSelector for the transport-specific data/options/conditions. The raw form dict is stored in the subentry and validated through DELIVERY_SCHEMA at runtime; subentry deliveries are merged with the YAML ones (subentry wins on a name clash), so YAML users can add UI deliveries incrementally without migrating anything. Tested on my instance: create → persists across restart → notify.supernotify delivers to it.
Two non-obvious things I hit that apply to any implementation storing deliveries in the entry, whichever model you choose:
Anything that has gone through SUPERNOTIFY_SCHEMA contains Template objects (e.g. volume_template), which are not JSON-serializable. Storing validated dicts in entry.data/options breaks the whole entry save (TypeError: Type is not JSON serializable: Template) the first time anything else touches the entry. Store raw strings and re-validate at load time.
Update listeners registered with entry.add_update_listener() must be coroutine functions; a @callback sync listener makes async_create_task(listener(hass, entry)) blow up with "a coroutine was expected, got None" at the first options save.
The question I'd like your steer on: the roadmap says deliveries/transports/scenarios/recipients should be "maintained as YAML, in a similar fashion to how HA treats automations" (UI edits round-trip to the file). That's a different model from subentries (data lives in the entry, no separate file). Before I go further:
Does the YAML file stay hand-editable in parallel once someone has used the UI (like automations.yaml), or is it UI-owned after migration?
Is the entry meant to hold only global settings, with the delivery/scenario file entirely outside it?
Is there a reason to prefer round-trip YAML over subentries that I'm missing? I'm not attached to the prototype — if round-trip is the direction, I'll adapt it; the field-typing work (transport-specific data) is the same problem either way.
2. Scenario state as a real binary_sensor (small patch, self-contained)
expose_entities() already creates binary_sensor.supernotify_scenario_, but with state=STATE_UNKNOWN hard-coded and never refreshed. The patch (≈70 lines in notify.py) evaluates each scenario's conditions with neutral variables (real occupancy + PRIORITY_MEDIUM, same as enquire_active_scenarios), sets ON/OFF, and refreshes on a 1-minute timer plus async_track_state_change_event on the entities extracted from the conditions via condition.async_extract_entities. Scenarios whose conditions reference no entities (priority-only, or pure applied_scenarios triggers like a manual emergency) stay unknown, which is the honest answer for them.
This maps onto your "Fourth" phase (scenarios: view / enable-disable) and is independent of the config flow. I can open it as a PR straight away if you want it; happy to do an issue-first round if you'd rather shape it.
Design note behind it (from mapping my own 25 scenarios): only 1 is a manual switch, 17 self-activate on priority/time/occupancy, 7 are driven by existing helpers. So "scenario = helper" would break most of them; "scenario state exposed read-only, helpers referenced as inputs" keeps the automation intact. Details in the write-up if useful.
- delivery_selection semantics (UX, no code yet)
Not a bug, but the thing that trips up every new user I've walked through the config, and it will surface hard once deliveries are editable in a form:
Passing delivery: as a map defaults to IMPLICIT (default + scenarios + listed), as a list to EXPLICIT (no defaults, but scenarios still apply). Same key, different behaviour depending on YAML shape.
Only fixed gives "just these" — and 1.17.0's change to fixed (overrides priority/conditions, only enabled blocks) is a good step, thanks.
Separately, when two active scenarios disagree on a delivery's enabled (e.g. dnd_globale says alexa: false, high_priority says alexa: true), false wins silently. That's a defensible safety default, but it's undocumented and the scenario author has no way to express "this one should win".
Proposal for Phase 2: expose delivery_selection explicitly in the delivery form with the three modes spelled out, decouple the default from the map/list shape, and document (or make configurable) the merge rule when scenarios conflict on enabled.
Suggested order from my side, if it helps: (2) as a small PR now, (3) as a doc/decision, (1) once you've said which storage model you want. I'll also be sending the Matrix/Discord/HTML5/Kodi transports as separate PRs over the next days — those are independent of all of the above.
With v2.0.0 landing the "Immediate" phase of docs/roadmap/configflow_approach.md (#60, #136), I'd like to open a place to discuss the next step — deliveries and scenarios in the UI — before anyone (me included) writes more code in the wrong direction. Splitting it out of the closed threads so it's easy to find.
I have three pieces of work sitting on my fork that are relevant. None of them need to land as-is; I'm listing them so you can pick what's useful and reject the rest.
A DeliverySubentryFlowHandler (ConfigSubentryFlow, HA 2025.3+ API) that creates/edits/removes a delivery from the integration page. Typed fields for transport (SelectSelector), enabled, priority, occupancy, selection, action, target, plus an ObjectSelector for the transport-specific data/options/conditions. The raw form dict is stored in the subentry and validated through DELIVERY_SCHEMA at runtime; subentry deliveries are merged with the YAML ones (subentry wins on a name clash), so YAML users can add UI deliveries incrementally without migrating anything. Tested on my instance: create → persists across restart → notify.supernotify delivers to it.
Two non-obvious things I hit that apply to any implementation storing deliveries in the entry, whichever model you choose:
Anything that has gone through SUPERNOTIFY_SCHEMA contains Template objects (e.g. volume_template), which are not JSON-serializable. Storing validated dicts in entry.data/options breaks the whole entry save (TypeError: Type is not JSON serializable: Template) the first time anything else touches the entry. Store raw strings and re-validate at load time.
Update listeners registered with entry.add_update_listener() must be coroutine functions; a @callback sync listener makes async_create_task(listener(hass, entry)) blow up with "a coroutine was expected, got None" at the first options save.
The question I'd like your steer on: the roadmap says deliveries/transports/scenarios/recipients should be "maintained as YAML, in a similar fashion to how HA treats automations" (UI edits round-trip to the file). That's a different model from subentries (data lives in the entry, no separate file). Before I go further:
Does the YAML file stay hand-editable in parallel once someone has used the UI (like automations.yaml), or is it UI-owned after migration?
Is the entry meant to hold only global settings, with the delivery/scenario file entirely outside it?
Is there a reason to prefer round-trip YAML over subentries that I'm missing? I'm not attached to the prototype — if round-trip is the direction, I'll adapt it; the field-typing work (transport-specific data) is the same problem either way.
2. Scenario state as a real binary_sensor (small patch, self-contained)
expose_entities() already creates binary_sensor.supernotify_scenario_, but with state=STATE_UNKNOWN hard-coded and never refreshed. The patch (≈70 lines in notify.py) evaluates each scenario's conditions with neutral variables (real occupancy + PRIORITY_MEDIUM, same as enquire_active_scenarios), sets ON/OFF, and refreshes on a 1-minute timer plus async_track_state_change_event on the entities extracted from the conditions via condition.async_extract_entities. Scenarios whose conditions reference no entities (priority-only, or pure applied_scenarios triggers like a manual emergency) stay unknown, which is the honest answer for them.
This maps onto your "Fourth" phase (scenarios: view / enable-disable) and is independent of the config flow. I can open it as a PR straight away if you want it; happy to do an issue-first round if you'd rather shape it.
Design note behind it (from mapping my own 25 scenarios): only 1 is a manual switch, 17 self-activate on priority/time/occupancy, 7 are driven by existing helpers. So "scenario = helper" would break most of them; "scenario state exposed read-only, helpers referenced as inputs" keeps the automation intact. Details in the write-up if useful.
Not a bug, but the thing that trips up every new user I've walked through the config, and it will surface hard once deliveries are editable in a form:
Passing delivery: as a map defaults to IMPLICIT (default + scenarios + listed), as a list to EXPLICIT (no defaults, but scenarios still apply). Same key, different behaviour depending on YAML shape.
Only fixed gives "just these" — and 1.17.0's change to fixed (overrides priority/conditions, only enabled blocks) is a good step, thanks.
Separately, when two active scenarios disagree on a delivery's enabled (e.g. dnd_globale says alexa: false, high_priority says alexa: true), false wins silently. That's a defensible safety default, but it's undocumented and the scenario author has no way to express "this one should win".
Proposal for Phase 2: expose delivery_selection explicitly in the delivery form with the three modes spelled out, decouple the default from the map/list shape, and document (or make configurable) the merge rule when scenarios conflict on enabled.
Suggested order from my side, if it helps: (2) as a small PR now, (3) as a doc/decision, (1) once you've said which storage model you want. I'll also be sending the Matrix/Discord/HTML5/Kodi transports as separate PRs over the next days — those are independent of all of the above.