Add button platform to Vistapool#172550
Conversation
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.
There was a problem hiding this comment.
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.pyplatform withVistapoolLEDPulseButtonentity created whenmain.hasLEDis truthy. - Strings, quality scale, and
PLATFORMSupdated to include the button platform andset_failederror. - 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. |
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.
There was a problem hiding this comment.
💡 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".
| "entity": { | ||
| "button": { | ||
| "led_pulse": { | ||
| "name": "LED next colour" |
There was a problem hiding this comment.
We use the english that does color instead of colour
There was a problem hiding this comment.
Oups,/// will apply
| """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. | ||
| """ |
There was a problem hiding this comment.
So this just turns the light off and on? Isn't that weird?
There was a problem hiding this comment.
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.
|
Please take a look at the requested changes, and use the Ready for review button when you are done, thanks 👍 |
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.
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.
| 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 | ||
| ) |
| self.coordinator.data.setdefault("light", {})["status"] = 1 | ||
| self.coordinator.async_set_updated_data(self.coordinator.data) |
| 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: |
| "set_failed": { | ||
| "message": "Failed to set {entity}." | ||
| }, |
This reverts commit ab5148c.
Breaking change
Proposed change
Adds the button platform — a single
LED next colourentity gated onmain.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:light.statustruthy): writeslight.status=0, waits 1s, writeslight.status=1— the brief power-cycle is what advances the LED.light.status=1directly. The physical fixture advances to its next colour on power-on.Implementation notes
main.hasLEDat setup time — pools without an LED fixture don't see the button.entity.runtime_data.coordinators.values()for multi-pool support.aioaquarite.AquariteClient.set_value;AquariteErrorbecomes a translatedHomeAssistantErrorusing the existingset_failedtranslation key._LED_PULSE_DELAY_SECONDS) — the LED firmware needs a brief off period to register the colour-advance.quality_scale.yamlaction-exceptionsmoves fromexempttodone.Tests
tests/components/vistapool/test_button.pycovers:hasLED=1.hasLED=0(default fixture).set_value(light.status, 1)call.set_valuecalls in order(light.status, 0)then(light.status, 1).AquariteErrorre-raised asHomeAssistantError.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: