rainbird: Add config option to display zones as switches or valves - #177435
rainbird: Add config option to display zones as switches or valves#177435donavanbecker wants to merge 13 commits into
Conversation
|
Hey there @konikvranik, @allenporter, mind taking a look at this pull request as it has been labeled with an integration ( Code owner commandsCode owners of
|
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 10 out of 10 changed files in this pull request and generated 1 comment.
Comments suppressed due to low confidence (4)
homeassistant/components/rainbird/services.py:59
- Update the service target metadata to allow valve entities. This handler now resolves valves, but
homeassistant/components/rainbird/services.yaml:5still declaresdomain: switch, so the action UI/entity picker hides every valve zone even though manual service calls work.
partial(_get_rainbird_irrigation_entities, hass),
HassJob(_async_start_irrigation),
homeassistant/components/rainbird/config_flow.py:224
- Migrate or remove the inactive domain’s entity-registry entries when the zone type changes. Reloading calls
Entity.async_remove, which retains registered entities as unavailable (homeassistant/helpers/entity.py:1483-1503), so switch-to-valve and valve-to-switch transitions leave the old entities behind instead of cleanly replacing them as the PR and linked documentation state; add an end-to-end reload/registry test as well.
vol.Optional(
CONF_ZONE_TYPE,
default=self.config_entry.options.get(
CONF_ZONE_TYPE, ZONE_TYPE_SWITCH
),
tests/components/rainbird/test_config_flow.py:116
- Restore the unique-ID assertion after the options assertion. Removing it leaves
expected_unique_idunused and drops the parametrized test’s coverage of serial/MAC config-entry identity.
assert result["result"].options == {ATTR_DURATION: 6, "zone_type": "switch"}
tests/components/rainbird/test_config_flow.py:492
- Exercise the new valve choice in this options-flow submission. The new valve tests construct options directly, while this only submits
switch, so the flow path never verifies that selecting and storingvalveworks.
result["flow_id"], user_input={ATTR_DURATION: 5, "zone_type": "switch"}
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 11 out of 11 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (2)
homeassistant/components/rainbird/init.py:299
- Preserve zone registry customizations when replacing the inactive entity. Removing the entry discards its custom name/entity ID, disabled and hidden state, area, icon, aliases, categories, and labels, so toggling the option back recreates a default entity; copy these fields to the replacement before deleting the old entry.
for entity_entry in er.async_entries_for_config_entry(entity_reg, entry.entry_id):
if entity_entry.domain == inactive_domain:
entity_reg.async_remove(entity_entry.entity_id)
tests/components/rainbird/test_config_flow.py:526
- Add an end-to-end option-change test that verifies the entity states and registry after the reload. Because
mock_setuppatches out integration setup, this test only proves that"valve"is stored and never exercises the new reload/migration path, including either transition direction and preservation of registry metadata.
result = await hass.config_entries.options.async_configure(
result["flow_id"], user_input={ATTR_DURATION: 6, "zone_type": "valve"}
)
assert result.get("type") is FlowResultType.CREATE_ENTRY
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 11 out of 11 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (1)
homeassistant/components/rainbird/init.py:322
- Copy aliases and category assignments before deleting the inactive entry. These are user-managed registry customizations too, so the current migration silently loses voice aliases and category membership whenever the zone type changes.
labels=old.labels,
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 12 out of 12 changed files in this pull request and generated 1 comment.
Comments suppressed due to low confidence (1)
homeassistant/components/rainbird/init.py:323
- Preserve entity aliases when replacing the registry entry.
RegistryEntry.aliasesis user-managed metadata, but it is not copied before the inactive entry is deleted, so changing the zone type permanently drops aliases configured for that zone.
entity_reg.async_update_entity(
active_entry.entity_id,
name=old.name,
icon=old.icon,
area_id=old.area_id,
disabled_by=old.disabled_by,
hidden_by=old.hidden_by,
labels=old.labels,
)
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 12 out of 12 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (1)
homeassistant/components/rainbird/init.py:319
- Preserve all user-editable registry metadata when replacing the zone entity. The migration currently drops a customized entity object ID, aliases, and categories when it removes the inactive entry, so users who renamed or categorized a zone lose those settings after changing type; generate the new-domain ID from the old object ID and copy the remaining domain-independent fields.
entity_reg.async_update_entity(
active_entry.entity_id,
name=old.name,
icon=old.icon,
area_id=old.area_id,
1932655 to
5b41444
Compare
Add a new options flow setting `zone_type` that lets users choose whether sprinkler zones are exposed as Switch entities (default, preserving existing behavior) or Valve entities. - Add CONF_ZONE_TYPE / ZONE_TYPE_SWITCH / ZONE_TYPE_VALVE constants - Add valve.py implementing RainBirdValve (ValveEntity) mirroring RainBirdSwitch - switch.py skips setup when zone_type == 'valve'; valve.py skips when == 'switch' - Options flow gains a SelectSelector for zone_type (default: switch) - Both platforms exist in PLATFORMS so a reload triggered by the options change cleanly removes the old entities and adds the new ones - Add strings/translations for the new selector and option description - Add tests/components/rainbird/test_valve.py covering the valve platform Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
- services.py: extend start_irrigation to work for valve entities Register using hass.services.async_register with a combined entity getter that merges both switch and valve entities from DATA_DOMAIN_PLATFORM_ENTITIES, dispatching to async_open_valve or async_turn_on based on entity type. - valve.py: add PARALLEL_UPDATES = 1 (matches Hydrawise valve pattern) - test_config_flow.py: update options assertions to include zone_type='switch' default that is now included in options on config entry creation; update options flow test user_input and assertion to match new schema shape. - test_valve.py: add test_irrigation_service covering start_irrigation in valve mode; use DOMAIN constant instead of hardcoded string; import DOMAIN. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
CoordinatorEntity-derived classes must live in the 'entity' module per the home-assistant-enforce-class-module pylint rule (C7411). - Create entity.py containing RainBirdValve - valve.py now only contains async_setup_entry and imports RainBirdValve Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
- services.py: combine same-module imports per combine-as-imports=true - valve.py: remove unused 'import logging' and _LOGGER after refactor Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
- services.py: wrap long homeassistant.core import into multi-line form - test_valve.py: move rainbird.const import before config_entries to satisfy isort ordering (components < config_entries alphabetically) Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
- services.yaml: Update start_irrigation target to include both switch and valve domains so entity picker shows both platform entities - __init__.py: Add _async_migrate_zone_entity_type to remove stale entity registry entries for inactive zone platform on setup/reload - test_config_flow.py: Restore unique_id assertion and add test_options_flow_valve test for switching to valve zone type Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Move the duplicated device metadata, API calls, exception mapping, and optimistic state updates from RainBirdSwitch and RainBirdValve into a common RainBirdZoneEntity base class in entity.py. Each platform class now only contains its platform-specific method adapters. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
…anges When switching between switch and valve zone types, copy user customizations (name, icon, area, disabled/hidden state, labels) from the old inactive-domain entry to the newly created active-domain entry before removing the stale entry. Run migration after platform setup so new entities exist in the registry when we copy the metadata. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Add test_zone_type_change covering both switch→valve and valve→switch directions. The test sets up real Switch and Valve platforms, changes the zone_type option via the options flow, waits for the reload, and asserts that the old entity is removed from both state machine and entity registry while the new entity is created. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Apply a custom name and icon to the initial entity before switching zone types, then assert the replacement entity carries those values forward, so the async_update_entity copying is actually exercised. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
5b41444 to
f0536bc
Compare
Proposed change
Add a new options flow setting (
zone_type) that lets users choose whether Rain Bird sprinkler zones are exposed as Switch entities (default, preserving existing behavior) or Valve entities.When the setting is changed, the existing
async_update_listenertriggers a config entry reload, which cleanly removes the old entities and creates the new ones.The
start_irrigationcustom service works in both modes — it dispatches toasync_turn_onfor switches andasync_open_valvefor valves, so automations usingrainbird.start_irrigationcontinue to work regardless of which zone type is selected.Type of change
Additional information
Checklist
ruff format homeassistant tests)If user exposed functionality or configuration variables are added/changed:
If the code communicates with devices, web services, or third-party tools:
Updated and included derived files by running:
python3 -m script.hassfest.requirements_all.txt.Updated by running
python3 -m script.gen_requirements_all.To help with the load of incoming pull requests: