Skip to content

fix: Trim the options dialog and the controls an unused input adds - #20

Merged
sdebasek merged 1 commit into
mainfrom
fix/options-and-entity-clutter
Aug 21, 2026
Merged

sdebasek merged 1 commit into
mainfrom
fix/options-and-entity-clutter

Conversation

@sdebasek

Copy link
Copy Markdown
Owner

From a user report against 0.6.1, with screenshots. Three separate problems on the same two screens.

1. Controls appeared for an input that does not exist

select.py created a BleBoxButtonActionSelect for every input in data.inputs with no gating, so a five-input device showed ten of them in the Configuration block whether or not the fifth input is physically wired. On a switchBox the fifth is the optional external terminal, which most installations never use.

event.py already handles this correctly for the same situation, passing enabled=bool(data.enabled_events.get(input_id)) with a comment explaining why. The selects now follow the same rule: registered, but disabled by default when the input has no events selected.

The stale-default trap came with it. entity_registry_enabled_default is only read at first registration, so an input given events later would have stayed disabled for good. That is the bug fixed for event entities in #17. Rather than copy that fix-up, it moves to entity.py and serves both platforms, because both ask the identical question and differ only in which unique ids to correct. Two copies would have had to stay in step for ever, and a copy that fell behind would leave its platform's entities stuck disabled, which is precisely what the helper exists to prevent. A disable the user made is still never undone.

Entities are addressed by the same formula BleBoxDeviceEntity uses to create them, rather than a second spelling of it that could drift.

Known limitation, worth stating plainly: this does not retroactively disable controls already registered. An existing install keeps its ten until the two unused ones are disabled by hand, once. The fix governs new registrations.

2. Options sections could not be backed out of

Every sub-step ended in async_create_entry, which closes the whole dialog, so after visiting one section the user had to reopen Configure to visit another.

Established from the installed core rather than guessed: OptionsFlowManager.async_finish_flow applies result["data"] as the entry's options only on CREATE_ENTRY. So a section returning to the menu has to persist itself, via async_update_entry. That is also what fires the update listener, so:

  • a change needing re-provisioning still reloads the entry (now asserted by checking for a new coordinator object, which the old test did not);
  • an update that changes nothing returns False and notifies nobody, so browsing costs no spurious reload.

Also confirmed a reload does not abort an open options flow (async_reload aborts reauth flows only).

Submit labels now match what the buttons do, in both languages: Save / Zapisz, Back / Wstecz, and a Done / Gotowe entry to close.

3. Callback URLs are manual-mode only

In automatic mode the integration writes the URLs to the device itself, so the menu entry was noise on the one screen a user opens to change something. It is now offered only in manual mode, where pasting them into wBox by hand is the entire point.

data_entry_flow validates a menu choice against vol.In(menu_options), so the step cannot be reached otherwise, but it re-checks the mode anyway and bounces back to the menu. That covers the mode changing while the dialog is open, which this dialog's own events section can do.

docs/setup.md and docs/troubleshooting.md no longer claim the URLs are viewable at any time.

Testing

232 passing, up from 226. Coverage holds at 99%, with config_flow.py, entity.py, event.py and select.py all at 100%. ruff clean, three language files key-for-key in sync.

8 of 9 new tests fail against pre-fix source, each on its own assertion. The ninth is flagged in its own docstring as a behaviour-preservation guard, since nothing else writes disabled_by and it can only fail once the fix-up exists.

Isolation was checked too, so no test rides on another's fix: reverting only the manual-mode change fails exactly the two URL tests, and applying the select gating without the fix-up call fails exactly the re-enable test.

Reported against 0.6.1 with screenshots.

An input nobody selected events for still got a control for each of its
press types. The event entity for such an input is already registered
disabled by default, on the reasoning that an input with no events is
very likely one the hardware does not physically have, such as the
optional external terminal on a switchBox. The button behaviour selects
had no equivalent check, so a five input device showed ten of them
whether or not the fifth exists. They now follow the same rule.

Because entity_registry_enabled_default is only read when an entity is
first registered, an input given events later would have stayed
disabled for good. The event platform already had a fix-up for exactly
that, which now lives in entity and serves both platforms rather than
being copied. A copy that fell behind would have left one platform's
entities stuck disabled, which is the bug the fix-up exists to prevent.
A disable the user made is still never undone.

Opening a section of the options dialog closed it on save, so visiting a
second section meant reopening Configure. Home Assistant applies options
only on CREATE_ENTRY, so sections that return to the menu now persist
themselves, which is also what fires the update listener, so a change
that needs re-provisioning still reloads the entry and one that changes
nothing still costs no reload. The submit labels say what the buttons do
in both languages, and the menu has a way to finish.

Showing the callback URLs is only offered in manual mode. In automatic
mode the integration writes them to the device itself, so the entry was
noise on the one screen a user opens to change something. The step
re-checks the mode rather than trusting the menu, so a mode changed
while the dialog is open cannot leave it reachable.
@sdebasek
sdebasek merged commit a22694a into main Aug 21, 2026
6 checks passed
@sdebasek
sdebasek deleted the fix/options-and-entity-clutter branch August 21, 2026 14:59
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