-
-
Notifications
You must be signed in to change notification settings - Fork 189
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
Move connect_single to SmartDevice.connect #538
Move connect_single to SmartDevice.connect #538
Conversation
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## master #538 +/- ##
==========================================
+ Coverage 81.74% 82.22% +0.47%
==========================================
Files 28 30 +2
Lines 2421 2458 +37
Branches 685 692 +7
==========================================
+ Hits 1979 2021 +42
+ Misses 382 379 -3
+ Partials 60 58 -2 ☔ View full report in Codecov by Sentry. |
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.
My first impression is that this looks good. Would you mind adapting the cli tool to use the same mapping?
Line 45 in 805e4b8
TYPE_TO_CLASS = { |
I changed the enum values to match the cli and built the dict lookup from it |
Hi @bdraco, apologies, I don't really understand this PR so wanted to ask you about it. It seems like the change will bypass any connection in connect_single if a device_type is passed into the connect_single function. This seems counter-intuitive as the function is called connect_single so you would expect it to connect. If you want to bypass the connection why would you call connect_single at all? Wouldn't it be simpler and clearer what's happening to just construct the device in HA if that's what you want.
Two other questions:
Apologies in advance if I missed something obvious here. |
Ideally ha knows as little as possible about how to construct the device and the library takes care of it. It's more about abstracting that complexity away from HA |
I don’t think there’s really much complexity as it’s only one line of code as per my example above. You could anyway wrap that in a function call. It just doesn’t seem to make sense to introduce a new function Sorry, I’m not trying to be difficult but these changes seem designed to solve a specific HA problem that I’m worried they won’t solve, and will make the api confusing in the process. N.B. @rytilahti asked me to modify discover_single to use the same UDP logic path as |
What you are proposing above won't work because it makes the exception catch and retry ineffective since
will never run with that change and if the device is offline, the config entry will fail to load without retry. |
Agreed, that's what I was saying when I asked this:
What I was suggesting above was that IF you're going to avoid a device.update() with your device_type PR home-assistant/core#103150 do it in a new method rather than a Taking a step back all this started with trying to avoid UDP but as we've agreed UDP isn't the issue because it isn't live yet. There will still be connection errors whether they happen in setup_entry or data update. However one of the advantages of the UDP change is that it will tell us if the connection issues are related to firmware updates because it will report the devices as unsupported. Anyway, to help re-iterate that I'm really trying to help here :) I tested the 0.5.4 implementation of connect_single with HA and I think there is an issue. It errors here in
because the new device has not had
However if you go ahead with this PR and the associated HA PR and avoid calling device.update() altogether I think you will error on the same line in I do have a suggestion to try to improve the resilience here and maybe get to the bottom of the causes of 99449: If async_setup_entry can't find the device, we could schedule a full |
While you guys are debating what the ultimate correct fix should be, please bear in mind that for many people this integration is currently just totally broken... So getting it working even imperfectly would be a good start, and maybe the code can be finessed later ? Thanks for all the efforts so far, of course. |
👍
I get that, and thats why I'm continuing to engage on the subject.
home-assistant/core#103150 is marked a draft and needs #538 because of this problem which is why https://github.com/python-kasa/python-kasa/pull/538/files#diff-5e81b58a19fa4037d13d8a879cd13f4619ee94c91e8c2e889a7991c552e06afbR361 was added
I think there are multiple problems
Discovery is already run periodically in the background and any ip changes are fed into integration discovery which calls https://github.com/home-assistant/core/blob/401bb90215091b933671ab138315bd851d0a1aee/homeassistant/components/tplink/config_flow.py#L38 and https://github.com/home-assistant/core/blob/401bb90215091b933671ab138315bd851d0a1aee/homeassistant/components/tplink/config_flow.py#L49 which will update the ip address if it changes which will reload the config entry so the next attempt will use the newly discovered ip. |
So, to my understanding
I'm starting to wonder if whole idea of having these methods inside the discover class was completely wrong in the first place, and maybe there should be a separate factory class (or a classmethod inside the The classmethod-based approach would have a signature maybe like this:
|
The question for me is that I'm not sure why there's a need for
I've been trying to recreate the reported errors on my devices and yesterday I was having some luck with one of the devices. A few of the errors we don't currently retry like ConnectionRefused and HostUnreachable were actually intermittent. Also if I did a small delay between retries on connection errors I was getting a connection whereas if I removed the delay I wasn't. I was hoping to get some log data together for @bdraco but I can't get it to behave in quite the same way today. I think there's some fairly safe and simple work we could do to the EDIT: Some log snippets: Connection errors during discovery:
Connection and timeout errors during data refresh:
Timeout errors during data refresh:
|
I'm tempted to wait until #542 is released to see if makes a difference, and if we still have a problem, than proceed with this refactor |
It seems like we do need to get rid of the UDP based on home-assistant/core#103977 |
I am going to attempt a fix for #103977 via python-kasa/python-kasa#538 I am picking up codeowner on this for the forseeable future to watch for issues as well
no really surprising why the power strips failed before |
The other devices are nice and fast. ... its the children that kill it
|
retested this with home-assistant/core#104213 + home-assistant/core#104208. All my power strips are solid now I think we can backport home-assistant/core#104213 but home-assistant/core#104208 will have to wait for 2023.12.x since its technically a breaking change. I can get the strip thats not responding to UDP to set up after home-assistant/core#104213 and its mostly working even if its sugglish/fails to respond sometimes |
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.
Please add a short "Initialization" section to the docs describing how downstreams should use the lib, either in https://python-kasa.readthedocs.io/en/latest/smartdevice.html or https://python-kasa.readthedocs.io/en/latest/design.html
Uhh, messed up by splitting the review comments... Oh well, this approach looks good to me especially as it clearly separates the concerns and simplifies the code. This will be a breaking change as we remove the @sdb9696 it should be enough to do the discovery only once and then re-use the connection parameters for future accesses. This way we can get rid off the whole discovery data path inside homeassistant for the devices that are already configured. |
I'll retest this in HA shortly |
Retested in HA. Everything still works |
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.
Just a very minor doc nit, I tested that all my devices work as expected using the cli tool.
docs/source/design.rst
Outdated
************** | ||
|
||
When the IP Address of a device is known, it can be connected with :meth:`~kasa.SmartDevice.connect()`. | ||
If the IP Address is not known, it can be discovered using :func:`~kasa.Discover.discover_devices`. |
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.
If the IP Address is not known, it can be discovered using :func:`~kasa.Discover.discover_devices`. | |
If the IP Address is not known, it can be discovered using :func:`~kasa.Discover.discover`. |
Note the wrong function name. I would also swap this and the previous sentence, so something like:
Use to perform broadcast, udp-based discovery on the network. This will return you a list of device instances based on the discovery replies.
If the device's host is already known, you can use to construct a device instance.
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 think it looks good now, but I'm really jet lagged so I'll check it again in the morning. Than I think we should get a release out to address the linked issues in HA
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.
Ah, it looked fine to me so I went and merged it already... I can do release prep on the weekend if that works.
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.
@bdraco I think it might be prudent to keep HA doing discover_single
instead of direct tcp connection for the next HA release. I understand there are some issues at the moment with subnets and udp but the klap changes might not fully work with TCP connect and we may need to sync up on the error handling in HA.
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'd rather get the users who are using the integration today fixed before we focus on adding new things.
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 this changes anything regarding to klap, or auth support in general. The discovery will still done using the discovery protocol and what changes is only that homeassistant can optimize after-discovery accesses when it knows the connection parameters.
So basically the discovered (or inputted) connection settings are stored inside the config entry, which are then used for future connections. What this means for authenticated devices is that the integration will need to be modified to catch the exception on invalid creds / creds needed to let the user to change them, but that should be enough. Or am I mistaken?
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.
That seems like a great path forward to me unless I'm missing something as well 👍
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.
Agreed. Sorry, I just meant that we should incorporate that error handling and connection parameters before going ahead with the draft HA PR as-is.
It’s not essential because as @bdraco says, it’s new functionality, but atm it could raise errors for anyone who adds a klap device via discovery then restarts.
If we can fix rapidly in HA then not so much of a problem.
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 a commit to home-assistant/core@4d3b86b to make sure klap devices don't start a discovery flow so they don't appear before we have code in place to support them in HA
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.
Please let me know if there are any other places we should check as well.
Once we get this one bumped in HA and that PR out the door, we can start on a KLAP one to get it supported in HA
Co-authored-by: Teemu R. <tpr@iki.fi>
home-assistant/core#104213 will save the device type so we can avoid an update cycle to probe the device type at HA startup which will connect the device faster and reduce the risk of timeout during startup.
The power strips currently take upwards of 6-7s to do an update cycle:
2023-11-19 11:00:12.099 DEBUG (MainThread) [kasa.device_factory] Device 192.168.211.141 with known type (strip) took 6.90 seconds to connect
which causes them to fail to connect. By saving the device type we decrease the chance the connect will fail since we only have to do one cycle in the allotted 10s.Backstory: The HA tplink integration used to require UDP to set up devices. We rewrote the whole HA integration a few years ago to avoid needing to having working discovery to set up the devices since UDP is unreliable with these devices. Unfortunately, 0.5.4 brought back the UDP requirement so we now have a regression as seen in:
Fixes #543
Fixes #545