-
-
Notifications
You must be signed in to change notification settings - Fork 32.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Refactor switch for vesync #134409
base: dev
Are you sure you want to change the base?
Refactor switch for vesync #134409
Conversation
Hey there @markperdue, @webdjoe, @TheGardenMonkey, mind taking a look at this pull request as it has been labeled with an integration ( Code owner commandsCode owners of
|
@iprak FYI. As two side notes you should add yourself as a code owner on this integration, your support has been incredible. Would love to connect more on the HA discord too. |
I am thinking this PR should probably split the removal of the VeSyncDevice entity to a different PR. I don't see value in that class. Just complicates things. Thoughts? |
My one thought is I am not certain the names of the entities are unchanged for the two existing. I also can't test that hardware as I don't own it. |
Sure, it definitely helps to keep PR small. |
Other portion has been split to #134499. |
# Other types of wall switches support dimming. Those use light.py platform. | ||
exists_fn=lambda device: is_wall_switch(device) or is_outlet(device), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, but how come only these 2 are switches? As in, is_wall_switch
doesnt sound to incorporate dimming
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought I had handled this different maybe lost in a merge - so here is the challenge. The old lookup table takes two model of switches and calls them a dimmer switch. Goal is to not need that lookup table for models in the future.
These devices in the old method didn't create a switch entity just a light entity. Currently with my code it would also get a switch. Should we leave it like that so if dimmable switch or outlet you still get a switch toggle? This is the easier way, other option is adjust the exists to exclude the type of VeSyncDimmerSwitch which is a type of switch within the library.
@iprak Thoughts?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we need to provided a separate switch for dimmer. LightEntity extends from ToggleEntity and so it provided on/off capability natively.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Went back to fix this and realized I was correct up front. In pyvesync vesyncswitch has two child classes, VeSyncWallSwitch and VeSyncDimmerSwitch. The above filters to just wall switch so dimmer isn't used. As such this won't show for dimmers. No changes required. I updated the helper comment some to try make this more clear.
self.device.turn_off() | ||
self.schedule_update_ha_state() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we do that with the state?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Without it HA toggles it back the other way until next scan interval which gives it a poor user experience as it appears to have not worked.
Co-authored-by: Joost Lekkerkerker <[email protected]>
Co-authored-by: Joost Lekkerkerker <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added some code comments which I encountered while trying to use your branch.
I have added humidifier related switches on top of your branch with some adjustments. You can take a look at my branch here- https://github.com/iprak/core-fork/tree/added-switch-for-humidifier. I will submit a PR for that separately once yours is approved.
def turn_on(self, **kwargs: Any) -> None: | ||
"""Turn the device on.""" | ||
self.device.turn_on() | ||
def __init__( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need to define _attr_unique_id
otherwise adding another switch entity fails.
Something like this will work - self._attr_unique_id = f"{super().unique_id}-{description.key}"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For the two devices exposed today if we change this it will be a breaking change. However I could add a filter to only do the above unique ID on ones other than the outlet and switch on we offer today. It would set us up for future.
Thoughts on that approach?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suppose that will work. @joostlek might have reviewed code which ran into similar shortcoming and if the _attr_unique_id was defined as a breaking change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh that is a good catch. If that is the case we should migrate first. I don't feel like merging this as it will create entities with not unique unique ids. So we should have a preliminary PR where we migrate all the unique ids of the switches to something else and then we can set up new ones
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, today this code doesn't conflict or impact unique ID, however since trying to setup for growth makes sense we fix this now. I will update this code to have the unique ID as mentioned above and chat with iprak around getting a PR for that migration that will merge first.
self.device.turn_off() | ||
self.schedule_update_ha_state() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't schedule_update_ha_state be only called if turn_off succeeds?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some other spots have it this way - my theory was after touching devices we should check the source data regardless to ensure we are updated. Both approaches though in most cases would show correctly I would think. Which do you prefer?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The turn_on/off return true if operation succeeds and I think that should be respected and used as the basis of state refresh. Yes I do see some integration call this all the time and I would like @joostlek 's input on this.
I think without this, the entity would show the new data when it is refreshed but I am not sure if the underlying framework does the same. Some other integrations invoke a refresh and I think that takes care of cases where multiple entities get updated in response to one action.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Switch returns true if the web call succeeded, we should use that return value to schedule_update_ha_state.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Adjusted.
self.switch = switch | ||
def turn_on(self, **kwargs: Any) -> None: | ||
"""Turn the entity on.""" | ||
self.device.turn_on() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't schedule_update_ha_state be only called if turn_on succeeds?
Hopefully it is okay - I factored in some of your items for on_fn and off_fn into this one so it is ready to add future switches easily. |
I think I might need to rework this for humidifier. The pyvesync methods for humidifier related switches do not update the internal device state. It is inconsistent, some do and some don't. So I might have to force a refresh instead of state update. |
Okay - I suspect we will have a few things like that as we work through adding items to it. Hopefully the base sets us up for that. |
def turn_on(self, **kwargs: Any) -> None: | ||
"""Turn the device on.""" | ||
self.device.turn_on() | ||
def __init__( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh that is a good catch. If that is the case we should migrate first. I don't feel like merging this as it will create entities with not unique unique ids. So we should have a preliminary PR where we migrate all the unique ids of the switches to something else and then we can set up new ones
Unique IDs added, tests will fail until migration code is done as I think the tests need to exist in that. Once this branch is updated with the migration and tests PR it should pass. |
Unique ID migration PR is ready for review. Once that is merged I will update this branch and it will also be ready for review. |
self.device.turn_off() | ||
self.schedule_update_ha_state() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Switch returns true if the web call succeeded, we should use that return value to schedule_update_ha_state.
@@ -32,6 +37,9 @@ | |||
VeSyncHumidifierDevice = VeSyncHumid200300S | VeSyncSuperior6000S | |||
"""Humidifier device types""" | |||
|
|||
VeSyncFanDevice = VeSyncAirBypass | VeSyncAir131 | |||
"""Humidifier device types""" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is incorrect.
Proposed change
Refactor of switch sensor to support it offering more switches in the future, such as screen on off. This one will wait on the update coordinator merge first then update to reflect those changes. Creating a draft PR for early feedback.
I do not own a vesync switch or outlet so I would love to have someone test this on real hardware.
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: