Skip to content

rainbird: Add config option to display zones as switches or valves - #177435

Open
donavanbecker wants to merge 13 commits into
home-assistant:devfrom
donavanbecker:donavanbecker-rainbird-switch-valve-config
Open

rainbird: Add config option to display zones as switches or valves#177435
donavanbecker wants to merge 13 commits into
home-assistant:devfrom
donavanbecker:donavanbecker-rainbird-switch-valve-config

Conversation

@donavanbecker

@donavanbecker donavanbecker commented Jul 28, 2026

Copy link
Copy Markdown

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_listener triggers a config entry reload, which cleanly removes the old entities and creates the new ones.

The start_irrigation custom service works in both modes — it dispatches to async_turn_on for switches and async_open_valve for valves, so automations using rainbird.start_irrigation continue to work regardless of which zone type is selected.

Type of change

  • Dependency upgrade
  • Bugfix (non-breaking change which fixes an issue)
  • New integration (thank you!)
  • New feature (which adds functionality to an existing integration)
  • Deprecation (breaking change to happen in the future)
  • Breaking change (fix/feature causing existing functionality to break)
  • Code quality improvements to existing code or addition of tests

Additional information

Checklist

  • I understand the code I am submitting and can explain how it works.
  • The code change is tested and works locally.
  • Local tests pass. Your PR cannot be merged unless tests pass
  • There is no commented out code in this PR.
  • I have followed the development checklist
  • I have followed the perfect PR recommendations
  • The code has been formatted using Ruff (ruff format homeassistant tests)
  • Tests have been added to verify that the new code works.
  • Any generated code has been carefully reviewed for correctness and compliance with project standards.

If user exposed functionality or configuration variables are added/changed:

If the code communicates with devices, web services, or third-party tools:

  • The manifest file has all fields filled out correctly.
    Updated and included derived files by running: python3 -m script.hassfest.
  • New or updated dependencies have been added to requirements_all.txt.
    Updated by running python3 -m script.gen_requirements_all.
  • For the updated dependencies a diff between library versions and ideally a link to the changelog/release notes is added to the PR description.

To help with the load of incoming pull requests:

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@home-assistant

Copy link
Copy Markdown
Contributor

Hey there @konikvranik, @allenporter, mind taking a look at this pull request as it has been labeled with an integration (rainbird) you are listed as a code owner for? Thanks!

Code owner commands

Code owners of rainbird can trigger bot actions by commenting:

  • @home-assistant close Closes the pull request.
  • @home-assistant mark-draft Mark the pull request as draft.
  • @home-assistant ready-for-review Remove the draft status from the pull request.
  • @home-assistant rename Awesome new title Renames the pull request.
  • @home-assistant reopen Reopen the pull request.
  • @home-assistant unassign rainbird Removes the current integration label and assignees on the pull request, add the integration domain after the command.
  • @home-assistant update-branch Update the pull request branch with the base branch.
  • @home-assistant add-label needs-more-information Add a label (needs-more-information, problem in dependency, problem in custom component, problem in config, problem in device, feature-request) to the pull request.
  • @home-assistant remove-label needs-more-information Remove a label (needs-more-information, problem in dependency, problem in custom component, problem in config, problem in device, feature-request) on the pull request.

Copilot AI review requested due to automatic review settings July 28, 2026 03:13

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated 5 comments.

Comment thread homeassistant/components/rainbird/services.py
Comment thread tests/components/rainbird/test_config_flow.py
Comment thread homeassistant/components/rainbird/strings.json
Comment thread homeassistant/components/rainbird/config_flow.py
Comment thread tests/components/rainbird/test_config_flow.py
Copilot AI review requested due to automatic review settings July 28, 2026 03:22

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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:5 still declares domain: 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_id unused 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 storing valve works.
        result["flow_id"], user_input={ATTR_DURATION: 5, "zone_type": "switch"}

Comment thread homeassistant/components/rainbird/entity.py Outdated
Copilot AI review requested due to automatic review settings July 28, 2026 03:27

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 11 out of 11 changed files in this pull request and generated 1 comment.

Comment thread homeassistant/components/rainbird/__init__.py Outdated
Copilot AI review requested due to automatic review settings July 28, 2026 03:31

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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_setup patches 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

Copilot AI review requested due to automatic review settings July 28, 2026 03:35

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 11 out of 11 changed files in this pull request and generated 1 comment.

Comment thread tests/components/rainbird/test_config_flow.py
Copilot AI review requested due to automatic review settings July 28, 2026 03:40
Copilot AI review requested due to automatic review settings July 28, 2026 03:45

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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,

@donavanbecker
donavanbecker marked this pull request as ready for review July 28, 2026 03:50
Copilot AI review requested due to automatic review settings July 28, 2026 04:02

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.aliases is 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,
        )

Comment thread tests/components/rainbird/test_init.py Outdated
Copilot AI review requested due to automatic review settings July 28, 2026 04:07

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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,

Copilot AI review requested due to automatic review settings July 28, 2026 04:13

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@donavanbecker
donavanbecker force-pushed the donavanbecker-rainbird-switch-valve-config branch 3 times, most recently from 1932655 to 5b41444 Compare July 29, 2026 13:22
donavanbecker and others added 13 commits July 29, 2026 12:04
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>
@donavanbecker
donavanbecker force-pushed the donavanbecker-rainbird-switch-valve-config branch from 5b41444 to f0536bc Compare July 29, 2026 17:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants