Skip to content

Add button platform to Vistapool#172550

Open
fdebrus wants to merge 8 commits into
home-assistant:devfrom
fdebrus:vistapool-button
Open

Add button platform to Vistapool#172550
fdebrus wants to merge 8 commits into
home-assistant:devfrom
fdebrus:vistapool-button

Conversation

@fdebrus
Copy link
Copy Markdown
Contributor

@fdebrus fdebrus commented May 29, 2026

Breaking change

Proposed change

Adds the button platform — a single LED next colour entity gated on main.hasLED. Mirrors the "Next" button under LED Color in the Vistapool app's Illumination screen.

When pressed, the button advances the physical LED fixture's colour by briefly power-cycling light.status:

  • If the light is currently on (light.status truthy): writes light.status=0, waits 1s, writes light.status=1 — the brief power-cycle is what advances the LED.
  • If the light is off: writes light.status=1 directly. The physical fixture advances to its next colour on power-on.

Implementation notes

  • Gated on main.hasLED at setup time — pools without an LED fixture don't see the button.
  • Iterates entity.runtime_data.coordinators.values() for multi-pool support.
  • Writes go through aioaquarite.AquariteClient.set_value; AquariteError becomes a translated HomeAssistantError using the existing set_failed translation key.
  • The 1-second pulse delay is a module constant (_LED_PULSE_DELAY_SECONDS) — the LED firmware needs a brief off period to register the colour-advance.
  • quality_scale.yaml action-exceptions moves from exempt to done.

Tests

tests/components/vistapool/test_button.py covers:

  • Snapshot of the registered entity when hasLED=1.
  • Entity not created when hasLED=0 (default fixture).
  • Press when light is off: exactly one set_value(light.status, 1) call.
  • Press when light is on: two set_value calls in order (light.status, 0) then (light.status, 1).
  • Error path: AquariteError re-raised as HomeAssistantError.

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:

  • I have reviewed two other [open pull requests][prs] in this repository.

Exposes a single LED-pulse button gated on main.hasLED. Pressing the
button advances the physical LED fixture's colour:

- If light.status is currently 1, the button writes light.status=0,
  waits a moment, then writes light.status=1. The brief power-cycle
  is what advances the LED to its next colour.
- If the light is off, the button just writes light.status=1.

Mirrors the "Next" button under LED Color in the Vistapool app's
Illumination screen. AquariteError becomes a translated
HomeAssistantError using the existing set_failed translation key.
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Adds a new Button platform to the Vistapool integration providing an "LED next colour" button that power-cycles the pool light to advance the LED fixture color, mirroring the Vistapool app's behavior.

Changes:

  • New button.py platform with VistapoolLEDPulseButton entity created when main.hasLED is truthy.
  • Strings, quality scale, and PLATFORMS updated to include the button platform and set_failed error.
  • Tests and snapshot coverage for entity creation, press behaviors, and error handling.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
homeassistant/components/vistapool/init.py Register Platform.BUTTON alongside sensor.
homeassistant/components/vistapool/button.py New button platform implementing LED color-advance pulse.
homeassistant/components/vistapool/strings.json Add button name and set_failed error message translations.
homeassistant/components/vistapool/quality_scale.yaml Update rule statuses now that actions exist.
tests/components/vistapool/test_button.py Add tests covering presence, press behavior, and error path.
tests/components/vistapool/snapshots/test_button.ambr Snapshot for the new button entity.

Comment thread homeassistant/components/vistapool/button.py Outdated
Comment thread homeassistant/components/vistapool/button.py
Comment thread tests/components/vistapool/test_button.py
claude added 2 commits May 30, 2026 15:48
Confirms the HomeAssistantError raised by the press handler is the
expected set_failed one rather than an unrelated HomeAssistantError.
(True, "1", 1) is equivalent to (True, "1") because 1 == True in
Python, so the explicit 1 is matched by True. Aligns with the
(True, "1") form used in binary_sensor.py and light.py.
Copilot AI review requested due to automatic review settings May 30, 2026 16:07
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

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 6 out of 6 changed files in this pull request and generated 2 comments.

Comment thread homeassistant/components/vistapool/button.py
Comment thread homeassistant/components/vistapool/strings.json
@fdebrus fdebrus marked this pull request as ready for review May 30, 2026 16:11
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f0fbd4d913

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread homeassistant/components/vistapool/button.py
Comment thread tests/components/vistapool/test_button.py
"entity": {
"button": {
"led_pulse": {
"name": "LED next colour"
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We use the english that does color instead of colour

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Oups,/// will apply

Comment on lines +38 to +44
"""Power-cycle the pool light to advance the LED fixture's colour.

Mirrors the "Next" button under LED Color in the Vistapool app's
Illumination screen. If the light is on, sends light.status=0, waits a
moment, then light.status=1; the physical LED fixture advances to the
next colour on power-on. If the light is off, just turns it on.
"""
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

So this just turns the light off and on? Isn't that weird?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Not as weird as it looks :) power-cycling is the manufacturer-intended way to advance the ColorLogic LED fixture's color/program on these controllers. From Hayward's own operating manual: "to advance to the next program, turn the switch off, then back on within 10 seconds" the fixture has 12 colors/shows that are selected purely by power-cycle timing, with no addressable control wire. The Vistapool/Hayward mobile app's Next button under LED Color does exactly this, and our button automates it (off → 1s wait → on, or just on if it was off). Reference: Hayward Multi-Color LED Operating Manual.

@home-assistant home-assistant Bot marked this pull request as draft May 30, 2026 17:44
@home-assistant
Copy link
Copy Markdown
Contributor

Please take a look at the requested changes, and use the Ready for review button when you are done, thanks 👍

Learn more about our pull request process.

claude added 2 commits May 30, 2026 17:56
Patches _LED_PULSE_DELAY_SECONDS to 0 instead of mocking asyncio.sleep,
so the real sleep(0) call still runs (yields to the loop) and only the
wall-clock delay is removed.
Home Assistant standardises on American English. Renames the friendly
name "LED next colour" -> "LED next color"; the auto-derived
entity_id cascades to button.my_pool_led_next_color. Also updates the
docstring/comment spellings in button.py.
Copilot AI review requested due to automatic review settings May 30, 2026 18:00
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

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 6 out of 6 changed files in this pull request and generated 2 comments.

Comment thread homeassistant/components/vistapool/button.py
Comment thread homeassistant/components/vistapool/strings.json
@fdebrus fdebrus marked this pull request as ready for review May 30, 2026 18:14
@home-assistant home-assistant Bot requested a review from joostlek May 30, 2026 18:14
claude added 2 commits June 1, 2026 12:12
A rapid second press inside the Firestore push round-trip window
otherwise reads the stale off-state and just sends another
light.status=1, a no-op on the wire that doesn't advance the color.
Writing the new value into coordinator.data and notifying listeners
makes the next press immediately see the just-written value.
0.5.1 wraps aiohttp.ClientError and asyncio.TimeoutError from both the
REST send_command path and the upstream auth client refresh in
ConnectionError (an AquariteError subclass), so transport failures
surface as the translated set_failed HomeAssistantError via the
existing except AquariteError clause.
Copilot AI review requested due to automatic review settings June 1, 2026 12:47
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

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 8 out of 8 changed files in this pull request and generated 4 comments.

Comment on lines +56 to +63
if self.coordinator.get_value(_LIGHT_STATUS_PATH) in (True, "1"):
await self.coordinator.api.set_value(
self.coordinator.pool_id, _LIGHT_STATUS_PATH, 0
)
await asyncio.sleep(_LED_PULSE_DELAY_SECONDS)
await self.coordinator.api.set_value(
self.coordinator.pool_id, _LIGHT_STATUS_PATH, 1
)
Comment on lines +72 to +73
self.coordinator.data.setdefault("light", {})["status"] = 1
self.coordinator.async_set_updated_data(self.coordinator.data)
Comment on lines +55 to +64
try:
if self.coordinator.get_value(_LIGHT_STATUS_PATH) in (True, "1"):
await self.coordinator.api.set_value(
self.coordinator.pool_id, _LIGHT_STATUS_PATH, 0
)
await asyncio.sleep(_LED_PULSE_DELAY_SECONDS)
await self.coordinator.api.set_value(
self.coordinator.pool_id, _LIGHT_STATUS_PATH, 1
)
except AquariteError as err:
Comment on lines +67 to +69
"set_failed": {
"message": "Failed to set {entity}."
},
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.

4 participants