Skip to content
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

Add more tests/support for VeSync device variants #138176

Open
wants to merge 3 commits into
base: dev
Choose a base branch
from

Conversation

kevin-brown
Copy link

@kevin-brown kevin-brown commented Feb 10, 2025

Proposed change

The current VeSync plugin makes uses of long lists of hard-coded device SKUs and device types, which results in many issues and pull requests to support new devices after they are added to the underlying pyvesync library. This is further complicated by VeSync's love of adding new device SKUs for the same device, long after the original device was released.

In order to simplify handling within the Home Assistant integration for VeSync, this refactors the logic for detecting devices and SKUs to build the list based on the devices exposed by the pyvesync library. Additionally, this adds additional tests for newer VeSync devices that were previously supported by the integration but were not well-covered.

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

  • This PR fixes or closes issue: fixes Vesync: Dual 200S missing #128183
  • Link to documentation pull request: N/A
  • Link to developer documentation pull request: N/A
  • Link to frontend pull request: N/A

Checklist

  • 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.

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 link to the changelog, or at minimum a diff between library versions is added to the PR description.

To help with the load of incoming pull requests:

@home-assistant
Copy link

Hey there @markperdue, @webdjoe, @TheGardenMonkey, @cdnninja, @iprak, mind taking a look at this pull request as it has been labeled with an integration (vesync) you are listed as a code owner for? Thanks!

Code owner commands

Code owners of vesync can trigger bot actions by commenting:

  • @home-assistant close Closes the pull request.
  • @home-assistant rename Awesome new title Renames the pull request.
  • @home-assistant reopen Reopen the pull request.
  • @home-assistant unassign vesync Removes the current integration label and assignees on the pull request, add the integration domain after the command.
  • @home-assistant add-label needs-more-information Add a label (needs-more-information, problem in dependency, problem in custom component) to the pull request.
  • @home-assistant remove-label needs-more-information Remove a label (needs-more-information, problem in dependency, problem in custom component) on the pull request.

This improves the two VeSync static constants, `DEV_TYPE_TO_HA` and
`SKU_TO_BASE_DEVICE`, to make them built automatically based on the
supported devices within pyvesync. This should reduce the amount of
changes necessary in the future to support new devices and makes the
integration slightly more resilient to new skus released for devices
that already exist.

Since switches and bulbs use multiple device types, we need to detect
the supported device based on the features that are exposed.
This adds tests for support of the following VeSync devices:
* Humidifier Classic 300s
* Air Purifier Core 300s
* Outlet ESW01-EU (10A Indoor Round Plug)
* Outlet ESO15-TB (Outdoor Plug)

These devices were all either supported by the VeSync plugin previously
or enabled within the plugin with the changes made in the previous
commits to pull supported devices from the pyvesync module.

This renames the previous "Outlet" test entity to "Outlet 7A" to reflect
the fact that it is no longer the only outlet being tested, but it is
the only 7A outlet currently supported.

A custom API response for the outdoor plug details needed to be added
because it supports sub-devices for the two individual sockets it
controls which requires a new flavor of details response in order for
the pyvesync module to correctly parse the details.
@kevin-brown kevin-brown marked this pull request as ready for review February 10, 2025 00:08
@cdnninja
Copy link
Contributor

Interesting to see this approach. the Is humidifier approach also is checking the library data to see if it is a humidifier. It is the new approach each platform is moving to with the intent to move away from those lookup tables. I am interested to hear @iprak s thoughts on this.

Two other thoughts, for this PR to get merged in my experience it would be better to shrink it, most likely the tests should be a separate PR from any other changes. Smaller the PRs the faster they move.

As for #128183 it should be resolved as of 2025.2 when humidifier was released. The person commenting they still get an error posted a screenshot showing line 79 of fan.py with a log message that was removed in 2025.2 so I don't think they updated.

@iprak
Copy link
Contributor

iprak commented Feb 10, 2025

This automatically means that all devices of a type are supported. Are we actually doing that verification?

@iprak
Copy link
Contributor

iprak commented Feb 10, 2025

Documentation changes need to be included as well.

@cdnninja
Copy link
Contributor

This automatically means that all devices of a type are supported. Are we actually doing that verification?

I do think that is our goal as a whole. The is_humidifer approach does the same all inclusive approach as the two class definitions cover all humidifiers.

My on concern of using this approach is it needs to be unique approach for each device type, vs the class approach will always exist. is_type also reads easier.

@kevin-brown
Copy link
Author

Are we actually doing that verification?

According to the documentation for each device type (pyvesync readme), yes there is a stable API that we are making use of here so it should be safe to do.

It is the new approach each platform is moving to with the intent to move away from those lookup tables.

Generally speaking I'm in favor of this. Switches, outlets, and bulbs all extend from a common type class within pyvesync so that should be fairly easy to work with. Unfortunately fans (and by extension, humidifiers) do not which makes that a moving target until pyvesync moves to a common base class for those as well.

@iprak
Copy link
Contributor

iprak commented Feb 11, 2025

This automatically means that all devices of a type are supported. Are we actually doing that verification?

I do think that is our goal as a whole. The is_humidifer approach does the same all inclusive approach as the two class definitions cover all humidifiers.

My on concern of using this approach is it needs to be unique approach for each device type, vs the class approach will always exist. is_type also reads easier.

I think it all depends on how we can confirm that the unified class or separate classes perform in contrast to the device. A unified base class for humidifier would be neat.

When I first looked at the device fixture, they felt to have been duplicated with invalid humidifier related data items.

I am also in favor of the feature based approach since the library is the source of truth. I think the library can tell if a device is "humidifier" instead of maintaining 2 mappings DEV_TYPE_TO_HA, SKU_TO_BASE_DEVICE. Can the base device perhaps provide an enum representing different features/device_type?

@kevin-brown
Copy link
Author

Can the base device perhaps provide an enum representing different features/device_type?

The devices themselves provide most of this information for us already. As far as I can tell, fan.PRESET_MODES returns the same information as device.modes without off and manual. Looking at fan.SPEED_RANGE though, it doesn't match levels in the pyvesync config dictionary for all devices which is... strange. That also isn't exposed as a property on the device so we wouldn't be able to duck type it.

@cdnninja
Copy link
Contributor

#135744 does the alternate approach to remove these mapping tables. Only items left are the mode constants and speeds. I don't think speed ranges were in the library but could be added.

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.

Vesync: Dual 200S missing
3 participants