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

Implement embedding DeviceStatus containers #1526

Merged
merged 4 commits into from
Sep 20, 2022

Conversation

rytilahti
Copy link
Owner

@rytilahti rytilahti commented Sep 15, 2022

Adds DeviceStatus.embed(self, other: DeviceStatus) method that allows embedding separate DeviceStatus containers into a single one. This will copy over the switch, setting, and sensor descriptors to the container and prefixing their names with the name of the other class.

Internally, __getattribute__ is overridden to check if the property name contains ':' and if so, the attribute lookup is done in an embedded class named after the first part of the key.

This PR also converts roborock vacuum integration to expose cleaning summary and consumable statuses using this functionality.

Adds DeviceStatus.embed(self, other: DeviceStatus) method that allows
embedding separate DeviceStatus containers into a single one.
This will copy over the switch, setting, and sensor descriptors to the
container and prefixing their names with the name of the other class.

Internally, __getattribute__ is overridden to check if the property name
contains ':' and if so, the attribute lookup is done in an embedded class
named after the first part of the key.
@rytilahti
Copy link
Owner Author

@starkillerOG feel free to give this PR a try on your vacuum to see if the embedding works as expected! I haven't tested this as of yet as I don't have access to my vacuum at the moment.

@codecov-commenter
Copy link

codecov-commenter commented Sep 15, 2022

Codecov Report

Merging #1526 (789b58b) into master (ff4e18f) will increase coverage by 0.15%.
The diff coverage is 76.92%.

@@            Coverage Diff             @@
##           master    #1526      +/-   ##
==========================================
+ Coverage   82.13%   82.29%   +0.15%     
==========================================
  Files         145      145              
  Lines       14165    14195      +30     
  Branches     3416     3422       +6     
==========================================
+ Hits        11635    11682      +47     
+ Misses       2305     2286      -19     
- Partials      225      227       +2     
Impacted Files Coverage Δ
miio/devicestatus.py 88.23% <68.42%> (-5.71%) ⬇️
.../integrations/vacuum/roborock/tests/test_vacuum.py 98.27% <100.00%> (+<0.01%) ⬆️
miio/integrations/vacuum/roborock/vacuum.py 65.59% <100.00%> (+0.38%) ⬆️
...o/integrations/vacuum/roborock/vacuumcontainers.py 86.07% <0.00%> (+8.41%) ⬆️

📣 We’re building smart automated test selection to slash your CI/CD build times. Learn more

@rytilahti rytilahti merged commit 1129167 into master Sep 20, 2022
@rytilahti rytilahti deleted the feat/devicestatus_embedding branch September 20, 2022 17:11
@@ -403,7 +403,10 @@ def manual_control(
@command()
def status(self) -> VacuumStatus:
"""Return status of the vacuum."""
return VacuumStatus(self.send("get_status")[0])
Copy link
Contributor

Choose a reason for hiding this comment

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

@rytilahti very nice, this simplifies it quite a bit.
However now there is no way to only get the VucuumStatus withouth calling the consumable_status and clean_history.
For HomeAssistant it is optimal to have every endpoint a diffrent UpdateCoordinator such that if some entities are disabled, no needless calls are made to the roborock.

However this would complicate the code quite a bit, so I am okay with just having a single coordinator that always calls all endpoints and just accept the possible unneeded calls.

Copy link
Contributor

Choose a reason for hiding this comment

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

I will try to test this tonight

Copy link
Owner Author

Choose a reason for hiding this comment

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

I'm slowly working the backlog after returning back home. You have a good point about having separate functions to make it possible to avoid unnecessary I/O that I was not considering while working on the initial implementation. This is not only relevant to save some I/O requests, but the current way has another issue, namely that handling of error cases (e.g., a device not supporting some feature) needs to be done case-by-case...

Instead of embedding, another approach could be to extend the API to add a way to expose references to methods that can be used to obtain the status information, and leave it to the downstream like homeassistant to choose if they want to use it. The problem I'm seeing though is that when the sensors & co are dynamic, homeassistant would need to hardcode what it wants as long as there is no way to check which entities are disabled, so I don't think that's a good idea for now. Your solution to add a separate "raw update" for cli and other users to allow obtaining just the get_status results sounds good to me.

Back to the issue of error handling / avoiding unsupported calls: maybe the embed should rather acts as a builder and take a callable instead of a status container as an input. This would make it easier to implement generic handling to avoid crashing on unsupported features, as well as to avoid doing unnecessary I/O on subsequent update cycles. I think this needs some thinking and experimenting to see what works the best.

@starkillerOG
Copy link
Contributor

@rytilahti I have tested this today.
It works niceley, but the getattribute does not work.
I made a fix in this PR: #1542

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