I haven't heard about these and they are not currently supported by this lib nor by homeassistant.
Controlling these requires a separate hub (KH100), but as these are kasa-branded, adding support should be doable as soon as someone provides a traffic capture between the app and the hub, or goes and reverses the protocol.
Controlling these requires a separate hub (KH100), but as these are kasa-branded, adding support should be doable as soon as someone provides a traffic capture between the app and the hub, or goes and reverses the protocol.
I have 7 arriving today, could you point me in the right direction on how to do what you're saying and I'll do it.
I haven't done packet capture for devices before, but I have done it on browsers so I'm pretty rusty
As a first step you want to verify that the hub is actually using the kasa protocol. To do that, use kasa discover command to see if it can detect the device:
kasa discover
kasa --target 192.168.23.255 discover # if the device is in another network
Alternatively, you can directly try to request the sysinfo from it:
kasa -d --host 192.168.23.123 sysinfo
If you get responses for those commands, that's good news and the device is using the protocol implemented by this library.
Next step is to find out the commands to control the hub itself. The simplest way to do that is to install the kasa app in an android emulator (I have heard that bluestacks works on mac and windows), and use wireshark or tcpdump to capture traffic while playing with the available functionality in the app.
You can use the devtools/parse_pcap.py script in this repository to parse the contents of a pcap file, see #388 (reply in thread)
python devtools/parse_pcap.py capture_file.pcap
It will show you the sent commands and the device responses.
Let me know if you get stuck somewhere in the progress and we'll try to find a solution :-)
Output from terminal on my Mac after running those commands.
I installed kasa with the following command: pip3 install python-kasa
benmitchell@Scylla ~ % kasa discover
Discovering devices on 255.255.255.255 for 3 seconds
benmitchell@Scylla ~ % kasa --target 192.168.100.255 discover
Discovering devices on 192.168.100.255 for 3 seconds
benmitchell@Scylla ~ % kasa -d --host 192.168.100.153 sysinfo
No --type defined, discovering..
Traceback (most recent call last):
File "/opt/homebrew/lib/python3.10/site-packages/kasa/protocol.py", line 131, in _query
await self._connect(timeout)
File "/opt/homebrew/lib/python3.10/site-packages/kasa/protocol.py", line 81, in _connect
self.reader, self.writer = await asyncio.wait_for(task, timeout=timeout)
File "/opt/homebrew/Cellar/python@3.10/3.10.9/Frameworks/Python.framework/Versions/3.10/lib/python3.10/asyncio/tasks.py", line 445, in wait_for
return fut.result()
File "/opt/homebrew/Cellar/python@3.10/3.10.9/Frameworks/Python.framework/Versions/3.10/lib/python3.10/asyncio/streams.py", line 48, in open_connection
transport, _ = await loop.create_connection(
File "/opt/homebrew/Cellar/python@3.10/3.10.9/Frameworks/Python.framework/Versions/3.10/lib/python3.10/asyncio/base_events.py", line 1070, in create_connection
raise exceptions[0]
File "/opt/homebrew/Cellar/python@3.10/3.10.9/Frameworks/Python.framework/Versions/3.10/lib/python3.10/asyncio/base_events.py", line 1054, in create_connection
sock = await self._connect_sock(
File "/opt/homebrew/Cellar/python@3.10/3.10.9/Frameworks/Python.framework/Versions/3.10/lib/python3.10/asyncio/base_events.py", line 963, in _connect_sock
await self.sock_connect(sock, address)
File "/opt/homebrew/Cellar/python@3.10/3.10.9/Frameworks/Python.framework/Versions/3.10/lib/python3.10/asyncio/selector_events.py", line 501, in sock_connect
return await fut
File "/opt/homebrew/Cellar/python@3.10/3.10.9/Frameworks/Python.framework/Versions/3.10/lib/python3.10/asyncio/selector_events.py", line 541, in _sock_connect_cb
raise OSError(err, f'Connect call failed {address}')
ConnectionRefusedError: [Errno 61] Connect call failed ('192.168.100.153', 9999)
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/opt/homebrew/bin/kasa", line 8, in <module>
sys.exit(cli())
File "/opt/homebrew/lib/python3.10/site-packages/asyncclick/core.py", line 1157, in __call__
return anyio.run(self._main, main, args, kwargs, **opts)
File "/opt/homebrew/lib/python3.10/site-packages/anyio/_core/_eventloop.py", line 70, in run
return asynclib.run(func, *args, **backend_options)
File "/opt/homebrew/lib/python3.10/site-packages/anyio/_backends/_asyncio.py", line 292, in run
return native_run(wrapper(), debug=debug)
File "/opt/homebrew/Cellar/python@3.10/3.10.9/Frameworks/Python.framework/Versions/3.10/lib/python3.10/asyncio/runners.py", line 44, in run
return loop.run_until_complete(main)
File "/opt/homebrew/Cellar/python@3.10/3.10.9/Frameworks/Python.framework/Versions/3.10/lib/python3.10/asyncio/base_events.py", line 649, in run_until_complete
return future.result()
File "/opt/homebrew/lib/python3.10/site-packages/anyio/_backends/_asyncio.py", line 287, in wrapper
return await func(*args)
File "/opt/homebrew/lib/python3.10/site-packages/asyncclick/core.py", line 1160, in _main
return await main(*args, **kwargs)
File "/opt/homebrew/lib/python3.10/site-packages/asyncclick/core.py", line 1076, in main
rv = await self.invoke(ctx)
File "/opt/homebrew/lib/python3.10/site-packages/asyncclick/core.py", line 1684, in invoke
await super().invoke(ctx)
File "/opt/homebrew/lib/python3.10/site-packages/asyncclick/core.py", line 1434, in invoke
return await ctx.invoke(self.callback, **ctx.params)
File "/opt/homebrew/lib/python3.10/site-packages/asyncclick/core.py", line 780, in invoke
rv = await rv
File "/opt/homebrew/lib/python3.10/site-packages/kasa/cli.py", line 98, in cli
dev = await Discover.discover_single(host)
File "/opt/homebrew/lib/python3.10/site-packages/kasa/discover.py", line 204, in discover_single
info = await protocol.query(Discover.DISCOVERY_QUERY)
File "/opt/homebrew/lib/python3.10/site-packages/kasa/protocol.py", line 73, in query
return await self._query(request, retry_count, timeout)
File "/opt/homebrew/lib/python3.10/site-packages/kasa/protocol.py", line 134, in _query
raise SmartDeviceException(
kasa.exceptions.SmartDeviceException: Unable to connect to the device: 192.168.100.153: [Errno 61] Connect call failed ('192.168.100.153', 9999)
benmitchell@Scylla ~ %
C:\Users\Ben Mitchell\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\Scripts>kasa -d --host 192.168.100.153 sysinfo
No --type defined, discovering..
Traceback (most recent call last):
File "C:\Users\Ben Mitchell\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\kasa\protocol.py", line 131, in _query
await self._connect(timeout)
File "C:\Users\Ben Mitchell\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\kasa\protocol.py", line 81, in _connect
self.reader, self.writer = await asyncio.wait_for(task, timeout=timeout)
File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.10_3.10.2544.0_x64__qbz5n2kfra8p0\lib\asyncio\tasks.py", line 445, in wait_for
return fut.result()
File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.10_3.10.2544.0_x64__qbz5n2kfra8p0\lib\asyncio\streams.py", line 48, in open_connection
transport, _ = await loop.create_connection(
File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.10_3.10.2544.0_x64__qbz5n2kfra8p0\lib\asyncio\base_events.py", line 1070, in create_connection
raise exceptions[0]
File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.10_3.10.2544.0_x64__qbz5n2kfra8p0\lib\asyncio\base_events.py", line 1054, in create_connection
sock = await self._connect_sock(
File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.10_3.10.2544.0_x64__qbz5n2kfra8p0\lib\asyncio\base_events.py", line 963, in _connect_sock
await self.sock_connect(sock, address)
File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.10_3.10.2544.0_x64__qbz5n2kfra8p0\lib\asyncio\proactor_events.py", line 709, in sock_connect
return await self._proactor.connect(sock, address)
File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.10_3.10.2544.0_x64__qbz5n2kfra8p0\lib\asyncio\windows_events.py", line 821, in _poll
value = callback(transferred, key, ov)
File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.10_3.10.2544.0_x64__qbz5n2kfra8p0\lib\asyncio\windows_events.py", line 608, in finish_connect
ov.getresult()
ConnectionRefusedError: [WinError 1225] The remote computer refused the network connection
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.10_3.10.2544.0_x64__qbz5n2kfra8p0\lib\runpy.py", line 196, in _run_module_as_main
return _run_code(code, main_globals, None,
File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.10_3.10.2544.0_x64__qbz5n2kfra8p0\lib\runpy.py", line 86, in _run_code
exec(code, run_globals)
File "C:\Users\Ben Mitchell\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\Scripts\kasa.exe\__main__.py", line 7, in <module>
File "C:\Users\Ben Mitchell\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\asyncclick\core.py", line 1157, in __call__
return anyio.run(self._main, main, args, kwargs, **opts)
File "C:\Users\Ben Mitchell\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\anyio\_core\_eventloop.py", line 70, in run
return asynclib.run(func, *args, **backend_options)
File "C:\Users\Ben Mitchell\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\anyio\_backends\_asyncio.py", line 292, in run
return native_run(wrapper(), debug=debug)
File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.10_3.10.2544.0_x64__qbz5n2kfra8p0\lib\asyncio\runners.py", line 44, in run
return loop.run_until_complete(main)
File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.10_3.10.2544.0_x64__qbz5n2kfra8p0\lib\asyncio\base_events.py", line 649, in run_until_complete
return future.result()
File "C:\Users\Ben Mitchell\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\anyio\_backends\_asyncio.py", line 287, in wrapper
return await func(*args)
File "C:\Users\Ben Mitchell\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\asyncclick\core.py", line 1160, in _main
return await main(*args, **kwargs)
File "C:\Users\Ben Mitchell\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\asyncclick\core.py", line 1076, in main
rv = await self.invoke(ctx)
File "C:\Users\Ben Mitchell\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\asyncclick\core.py", line 1684, in invoke
await super().invoke(ctx)
File "C:\Users\Ben Mitchell\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\asyncclick\core.py", line 1434, in invoke
return await ctx.invoke(self.callback, **ctx.params)
File "C:\Users\Ben Mitchell\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\asyncclick\core.py", line 780, in invoke
rv = await rv
File "C:\Users\Ben Mitchell\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\kasa\cli.py", line 98, in cli
dev = await Discover.discover_single(host)
File "C:\Users\Ben Mitchell\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\kasa\discover.py", line 204, in discover_single
info = await protocol.query(Discover.DISCOVERY_QUERY)
File "C:\Users\Ben Mitchell\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\kasa\protocol.py", line 73, in query
return await self._query(request, retry_count, timeout)
File "C:\Users\Ben Mitchell\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\kasa\protocol.py", line 134, in _query
raise SmartDeviceException(
kasa.exceptions.SmartDeviceException: Unable to connect to the device: 192.168.100.153: [WinError 1225] The remote computer refused the network connection
C:\Users\Ben Mitchell\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\Scripts>
Yep it just uses Kasa. I've tried to packet capture using Charles proxy on iOS but they seem to use certificate pinning and thus i am unable to capture anything useful
Ouch, also for local communications? Or does it only communicate over some cloud endpoint, i.e., there's no direct communication between the app and the device?
Hi, I'm interested in this too. I tried to capture traffic between my android phone and the smart hub that came with the radiator thermostats. It's not SSL, but it's definitely not plain text! Here is me turning off a radiator for example. 192.168.21.17 is the hub, .89 is the phone:
Oh thank god someone else has this product. I was starting to think I and 3 others were the only one who bought TP-Link TRVs because there's zero YouTube videos or meaningful google results / articles on the device. Unlike other TP-Link devices like routers and stuff.
Thank you for chipping in to the conversation, hopefully we can find some integration because TP-Link haven't updated their IFTT interfaces and Google home is useless for automation.
My google nest controls my boiler, I might replace it with a relay instead if that would work better, but even so, the IFTT api doesn't support the thermostats yet.
So I basically want to find a way to have my Nest turn off if all radiators are turned off OR aren't requesting heat (they're at the desired temperature)... otherwise, set the nest to the maximum 32° as we installed the nest in the lounge about 2 years ago which went well.. but during the last summer we installed a wood burning stove in the lounge and so when we're using that, we need the nest to be set to the maximum temp (or above 25°) otherwise it won't ever turn the boiler on and the lounge gets toasty while the rest of the house freezes
Currently I have it set up to turn onto 32° at 05:45 and set to 9° (off) at 22:00. Then in the Kasa app I have the specific schedule setup.
This seems pretty wasteful to me as the nest is running even once all the radiators have reached the desired temperature and turned off. (The bathroom radiators aren't controlled by the valves though so they take all the heat)
I wrote some logic code if that's easier to understand my objective:
if all_radiators.state == off || all_radiators.roomtemp == desired_temp {
@AntonyKing7D those paths (and the TPLINK_SESSIONID) look similar to the protocol implemented in #267 that was never finished. Maybe you could give it a try to see if that's really the case?
To check the discovery, I suppose something like this should work:
kasa -d --user <user> --password <pw> discover
and even when there's no device support, maybe you can try to request the sysinfo data:
Is there any way I can help out with this? I see that code has now been added for unsupported devices in https://github.com/python-kasa/python-kasa/pull/488 , which I assume is the first step towards this working.
I have the KH100(UK) and a few KE100.
Though I can see that there's no comms over 9999 for the hub. The pcap I captured was all comms with AWS over https. Which the parse_pcap.py script, understandably, didn't know what to do with. The only open TCP port is 80 on the hub.
I've half an idea what I'm doing with python and tcpdump and willing to lend a hand.
It’s winter again now in the UK and there’s still no solution for turning on an off the boiler based on if the KE100 thermostats are trying to heat or not. I just have to have it on all day
The status is the same as written in #422 (comment) – This will require someone with a device (or enough time to try to obtain the information otherwise) to reverse engineer the necessary bits and create an implementation. So PRs are still welcome and I can help with code reviews to get it merged. If the AES one is similar to KLAP, #509 might be a helpful starting point to start implementing it. If it's a completely different, that PR still introduces an abstract interface to be implemented.
@laxdog the discovery part helps only to discover devices using the new discovery protocol (which is being used by some kasa devices as well as by tapo line), so it doesn't really help that much wrt. the issue at hand. Anyway, was there any direct communications that did not go via the cloud?
My Hubitat experience with the protocol for the Kasa Matter devices is that is is the EXACT API and Protocol (AES) as the TAPO devices. I think this extends to the Hub. So, look toward the TAPO hub integrations as a starting point with only a few mods to get the Hub working (look for KASA.SMARTHUB vice TAPO.SMARTHUB on the port 20002 discovery message).
@laxdog the discovery part helps only to discover devices using the new discovery protocol (which is being used by some kasa devices as well as by tapo line), so it doesn't really help that much wrt. the issue at hand. Anyway, was there any direct communications that did not go via the cloud?
Yes, I captured a pcap. There's quite a lot of chatter between my phone and the Smart Hub. I'll have a look at that other repo and see if I can work anything out.
Just got the main line working from plugp100 and recognising the hub and the TRVs, I just can't control them. I'll give that PR a go soon, then maybe look at doing something in here.
Just got the main line working from plugp100 and recognising the hub and the TRVs, I just can't control them. I'll give that PR a go soon, then maybe look at doing something in here.
Try sending the following command to the Hub: [method: "get_child_device_list"] and get me the data (private message). That will have clues as to the basic device commands.
You could also try the following command:
[
device_id: DEVICEID FROM ABOVE,
method: "get_child_device_component_list"
]
I'm diving to the bottom here and will read through this thread later.
Just letting you all know that I have been able to control these via IFTTT per-say but limited use.
use case example:
Create a Kasa "scenes" that includes the Thermostat functions you want on the Kasa App.
Then you can trigger these "scenes" via IFTTT.
While you may not be able to see the Thermostats directly or modify them through IFTTT you can manually assign these thermostats to "scenes" which can be triggered via IFTTT
Activity
rytilahti commented on Feb 6, 2023
Hi,
I haven't heard about these and they are not currently supported by this lib nor by homeassistant.
Controlling these requires a separate hub (KH100), but as these are kasa-branded, adding support should be doable as soon as someone provides a traffic capture between the app and the hub, or goes and reverses the protocol.
iambenmitchell commented on Feb 6, 2023
I have 7 arriving today, could you point me in the right direction on how to do what you're saying and I'll do it.
I haven't done packet capture for devices before, but I have done it on browsers so I'm pretty rusty
rytilahti commented on Feb 6, 2023
As a first step you want to verify that the hub is actually using the kasa protocol. To do that, use kasa discover command to see if it can detect the device:
Alternatively, you can directly try to request the sysinfo from it:
If you get responses for those commands, that's good news and the device is using the protocol implemented by this library.
Next step is to find out the commands to control the hub itself. The simplest way to do that is to install the kasa app in an android emulator (I have heard that bluestacks works on mac and windows), and use wireshark or tcpdump to capture traffic while playing with the available functionality in the app.
You can use the devtools/parse_pcap.py script in this repository to parse the contents of a pcap file, see #388 (reply in thread)
It will show you the sent commands and the device responses.
Let me know if you get stuck somewhere in the progress and we'll try to find a solution :-)
iambenmitchell commented on Feb 6, 2023
Output from terminal on my Mac after running those commands.
I installed kasa with the following command: pip3 install python-kasa
benmitchell@Scylla ~ % kasa discover Discovering devices on 255.255.255.255 for 3 seconds benmitchell@Scylla ~ % kasa --target 192.168.100.255 discover Discovering devices on 192.168.100.255 for 3 seconds benmitchell@Scylla ~ % kasa -d --host 192.168.100.153 sysinfo No --type defined, discovering.. Traceback (most recent call last): File "/opt/homebrew/lib/python3.10/site-packages/kasa/protocol.py", line 131, in _query await self._connect(timeout) File "/opt/homebrew/lib/python3.10/site-packages/kasa/protocol.py", line 81, in _connect self.reader, self.writer = await asyncio.wait_for(task, timeout=timeout) File "/opt/homebrew/Cellar/python@3.10/3.10.9/Frameworks/Python.framework/Versions/3.10/lib/python3.10/asyncio/tasks.py", line 445, in wait_for return fut.result() File "/opt/homebrew/Cellar/python@3.10/3.10.9/Frameworks/Python.framework/Versions/3.10/lib/python3.10/asyncio/streams.py", line 48, in open_connection transport, _ = await loop.create_connection( File "/opt/homebrew/Cellar/python@3.10/3.10.9/Frameworks/Python.framework/Versions/3.10/lib/python3.10/asyncio/base_events.py", line 1070, in create_connection raise exceptions[0] File "/opt/homebrew/Cellar/python@3.10/3.10.9/Frameworks/Python.framework/Versions/3.10/lib/python3.10/asyncio/base_events.py", line 1054, in create_connection sock = await self._connect_sock( File "/opt/homebrew/Cellar/python@3.10/3.10.9/Frameworks/Python.framework/Versions/3.10/lib/python3.10/asyncio/base_events.py", line 963, in _connect_sock await self.sock_connect(sock, address) File "/opt/homebrew/Cellar/python@3.10/3.10.9/Frameworks/Python.framework/Versions/3.10/lib/python3.10/asyncio/selector_events.py", line 501, in sock_connect return await fut File "/opt/homebrew/Cellar/python@3.10/3.10.9/Frameworks/Python.framework/Versions/3.10/lib/python3.10/asyncio/selector_events.py", line 541, in _sock_connect_cb raise OSError(err, f'Connect call failed {address}') ConnectionRefusedError: [Errno 61] Connect call failed ('192.168.100.153', 9999) During handling of the above exception, another exception occurred: Traceback (most recent call last): File "/opt/homebrew/bin/kasa", line 8, in <module> sys.exit(cli()) File "/opt/homebrew/lib/python3.10/site-packages/asyncclick/core.py", line 1157, in __call__ return anyio.run(self._main, main, args, kwargs, **opts) File "/opt/homebrew/lib/python3.10/site-packages/anyio/_core/_eventloop.py", line 70, in run return asynclib.run(func, *args, **backend_options) File "/opt/homebrew/lib/python3.10/site-packages/anyio/_backends/_asyncio.py", line 292, in run return native_run(wrapper(), debug=debug) File "/opt/homebrew/Cellar/python@3.10/3.10.9/Frameworks/Python.framework/Versions/3.10/lib/python3.10/asyncio/runners.py", line 44, in run return loop.run_until_complete(main) File "/opt/homebrew/Cellar/python@3.10/3.10.9/Frameworks/Python.framework/Versions/3.10/lib/python3.10/asyncio/base_events.py", line 649, in run_until_complete return future.result() File "/opt/homebrew/lib/python3.10/site-packages/anyio/_backends/_asyncio.py", line 287, in wrapper return await func(*args) File "/opt/homebrew/lib/python3.10/site-packages/asyncclick/core.py", line 1160, in _main return await main(*args, **kwargs) File "/opt/homebrew/lib/python3.10/site-packages/asyncclick/core.py", line 1076, in main rv = await self.invoke(ctx) File "/opt/homebrew/lib/python3.10/site-packages/asyncclick/core.py", line 1684, in invoke await super().invoke(ctx) File "/opt/homebrew/lib/python3.10/site-packages/asyncclick/core.py", line 1434, in invoke return await ctx.invoke(self.callback, **ctx.params) File "/opt/homebrew/lib/python3.10/site-packages/asyncclick/core.py", line 780, in invoke rv = await rv File "/opt/homebrew/lib/python3.10/site-packages/kasa/cli.py", line 98, in cli dev = await Discover.discover_single(host) File "/opt/homebrew/lib/python3.10/site-packages/kasa/discover.py", line 204, in discover_single info = await protocol.query(Discover.DISCOVERY_QUERY) File "/opt/homebrew/lib/python3.10/site-packages/kasa/protocol.py", line 73, in query return await self._query(request, retry_count, timeout) File "/opt/homebrew/lib/python3.10/site-packages/kasa/protocol.py", line 134, in _query raise SmartDeviceException( kasa.exceptions.SmartDeviceException: Unable to connect to the device: 192.168.100.153: [Errno 61] Connect call failed ('192.168.100.153', 9999) benmitchell@Scylla ~ %iambenmitchell commented on Feb 6, 2023
ps. according to OpenWRT, the hub IP is 192.168.100.153
visiting the page in a browser brings a http ok code.

iambenmitchell commented on Feb 6, 2023
This is the result of running it on Windows:
C:\Users\Ben Mitchell\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\Scripts>kasa -d --host 192.168.100.153 sysinfo No --type defined, discovering.. Traceback (most recent call last): File "C:\Users\Ben Mitchell\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\kasa\protocol.py", line 131, in _query await self._connect(timeout) File "C:\Users\Ben Mitchell\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\kasa\protocol.py", line 81, in _connect self.reader, self.writer = await asyncio.wait_for(task, timeout=timeout) File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.10_3.10.2544.0_x64__qbz5n2kfra8p0\lib\asyncio\tasks.py", line 445, in wait_for return fut.result() File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.10_3.10.2544.0_x64__qbz5n2kfra8p0\lib\asyncio\streams.py", line 48, in open_connection transport, _ = await loop.create_connection( File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.10_3.10.2544.0_x64__qbz5n2kfra8p0\lib\asyncio\base_events.py", line 1070, in create_connection raise exceptions[0] File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.10_3.10.2544.0_x64__qbz5n2kfra8p0\lib\asyncio\base_events.py", line 1054, in create_connection sock = await self._connect_sock( File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.10_3.10.2544.0_x64__qbz5n2kfra8p0\lib\asyncio\base_events.py", line 963, in _connect_sock await self.sock_connect(sock, address) File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.10_3.10.2544.0_x64__qbz5n2kfra8p0\lib\asyncio\proactor_events.py", line 709, in sock_connect return await self._proactor.connect(sock, address) File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.10_3.10.2544.0_x64__qbz5n2kfra8p0\lib\asyncio\windows_events.py", line 821, in _poll value = callback(transferred, key, ov) File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.10_3.10.2544.0_x64__qbz5n2kfra8p0\lib\asyncio\windows_events.py", line 608, in finish_connect ov.getresult() ConnectionRefusedError: [WinError 1225] The remote computer refused the network connection During handling of the above exception, another exception occurred: Traceback (most recent call last): File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.10_3.10.2544.0_x64__qbz5n2kfra8p0\lib\runpy.py", line 196, in _run_module_as_main return _run_code(code, main_globals, None, File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.10_3.10.2544.0_x64__qbz5n2kfra8p0\lib\runpy.py", line 86, in _run_code exec(code, run_globals) File "C:\Users\Ben Mitchell\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\Scripts\kasa.exe\__main__.py", line 7, in <module> File "C:\Users\Ben Mitchell\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\asyncclick\core.py", line 1157, in __call__ return anyio.run(self._main, main, args, kwargs, **opts) File "C:\Users\Ben Mitchell\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\anyio\_core\_eventloop.py", line 70, in run return asynclib.run(func, *args, **backend_options) File "C:\Users\Ben Mitchell\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\anyio\_backends\_asyncio.py", line 292, in run return native_run(wrapper(), debug=debug) File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.10_3.10.2544.0_x64__qbz5n2kfra8p0\lib\asyncio\runners.py", line 44, in run return loop.run_until_complete(main) File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.10_3.10.2544.0_x64__qbz5n2kfra8p0\lib\asyncio\base_events.py", line 649, in run_until_complete return future.result() File "C:\Users\Ben Mitchell\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\anyio\_backends\_asyncio.py", line 287, in wrapper return await func(*args) File "C:\Users\Ben Mitchell\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\asyncclick\core.py", line 1160, in _main return await main(*args, **kwargs) File "C:\Users\Ben Mitchell\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\asyncclick\core.py", line 1076, in main rv = await self.invoke(ctx) File "C:\Users\Ben Mitchell\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\asyncclick\core.py", line 1684, in invoke await super().invoke(ctx) File "C:\Users\Ben Mitchell\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\asyncclick\core.py", line 1434, in invoke return await ctx.invoke(self.callback, **ctx.params) File "C:\Users\Ben Mitchell\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\asyncclick\core.py", line 780, in invoke rv = await rv File "C:\Users\Ben Mitchell\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\kasa\cli.py", line 98, in cli dev = await Discover.discover_single(host) File "C:\Users\Ben Mitchell\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\kasa\discover.py", line 204, in discover_single info = await protocol.query(Discover.DISCOVERY_QUERY) File "C:\Users\Ben Mitchell\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\kasa\protocol.py", line 73, in query return await self._query(request, retry_count, timeout) File "C:\Users\Ben Mitchell\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\kasa\protocol.py", line 134, in _query raise SmartDeviceException( kasa.exceptions.SmartDeviceException: Unable to connect to the device: 192.168.100.153: [WinError 1225] The remote computer refused the network connection C:\Users\Ben Mitchell\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\Scripts>rytilahti commented on Feb 6, 2023
Looks like it's not using the same communication protocol. Is the mobile app you are using called kasa or something else?
Did you already try to do a traffic capture? Few devices use a different protocol for comms which is not currently implemented: #115 #267
iambenmitchell commented on Feb 6, 2023
Yep it just uses Kasa. I've tried to packet capture using Charles proxy on iOS but they seem to use certificate pinning and thus i am unable to capture anything useful
iambenmitchell commented on Feb 6, 2023
Found these issues from other projects that reference the same product I'm using, might be worth watching them
RaresAil/homebridge-tp-link-tapo#30
caseyjhol/node-red-contrib-tplink#67
rytilahti commented on Feb 6, 2023
Ouch, also for local communications? Or does it only communicate over some cloud endpoint, i.e., there's no direct communication between the app and the device?
AntonyKing7D commented on Feb 7, 2023
Hi, I'm interested in this too. I tried to capture traffic between my android phone and the smart hub that came with the radiator thermostats. It's not SSL, but it's definitely not plain text! Here is me turning off a radiator for example. 192.168.21.17 is the hub, .89 is the phone:
192.168.21.89.58728 > 192.168.21.17.www: Flags [P.], cksum 0x685b (correct), seq 1620:2474, ack 1788, win 65376, length 854: HTTP, length: 854 POST /app?token=33B6ABCDEF12211234567ACBDEF1C HTTP/1.1 Referer: http://192.168.21.17:80 Accept: application/json requestByApp: true Content-Type: application/json; charset=UTF-8 Content-Length: 494 Host: 192.168.21.17 Connection: Keep-Alive Accept-Encoding: gzip Cookie: TP_SESSIONID=BA9D8436E1ED051D11408E1DBCB80E18 User-Agent: okhttp/3.12.13 {"method":"securePassthrough","params":{"request":"t8Cz5bIl6eZvagrw5wCo0hG3EW3j83l1w0lkwSNZbV4/dc3qSTX3Po13K0ZPUQZ6LU2huzJQNLvZ\nw7zu9DvDvXU2gpp+Jz+EvwZ51VlhJpe1t0lg4+ZPDRpvFXlP9CsDJlrTCAtPTf9u8GxkDF02c3Uy\nQx+EbDuI5ZwmIDkqf+B4xjj9K0z8Hhtpy1sJwlfCKKyiq0lzGQ47MoXLylOGlIXKgh2OVVZxj+1j\notgsmXs224CoM26MEFHwHFidZW/1XCTrJbo4fk/BpB+F8iYJkToxZs4Kpi1lh8gdgOLlsuowIHKK\n0V5fzKpHWv1VfGsTNVuMr8KAnb045sOBOWodG/dHtFcVHlihCmJv+1jyPVSN8u3kzmMCR8/Dfkqo\nWXAJ6Rg/En2hFfs71fmQ8CYmXOSB5YP9axhYOiE7bezQiTg=\n"}} [|http] 17:25:15.929476 IP (tos 0x0, ttl 255, id 55319, offset 0, flags [none], proto TCP (6), length 40) 192.168.21.17.www > 192.168.21.89.58728: Flags [.], cksum 0x8ffd (correct), seq 1788, ack 2474, win 2066, length 0 17:25:16.794168 IP (tos 0x0, ttl 255, id 55321, offset 0, flags [none], proto TCP (6), length 357) 192.168.21.17.www > 192.168.21.89.58728: Flags [P.], cksum 0xb6b1 (correct), seq 1788:2105, ack 2474, win 2066, length 317: HTTP, length: 317 HTTP/1.1 200 OK Content-Type: application/json;charset=UTF-8 Server: SHIP 2.0 Content-Length: 213 {"error_code":0,"result":{"response":"22pcku5YBdO+v9EvYOiRzGa6m0Ygd/D7Jl9qIhw3ALvZqKtGvJ7Pmb5LjWSzvuyzOvwEZncEFhRyLTlWbWNlkB8lCAke9d0fkbiqZ+jn7eunQsZWtKFWaye8w+ARZ2IelQ5V46QiqNrL1Ugkxme2bqaJhlPayuDEI4LrXHVo8DM="}} [|http]I've changed the token as I suspect that's a long-lived one and I don't want anyone turning my house into a sauna!
Happy to poke things at this and collect data if someone can give me some guidance.
iambenmitchell commented on Feb 7, 2023
Oh thank god someone else has this product. I was starting to think I and 3 others were the only one who bought TP-Link TRVs because there's zero YouTube videos or meaningful google results / articles on the device. Unlike other TP-Link devices like routers and stuff.
Thank you for chipping in to the conversation, hopefully we can find some integration because TP-Link haven't updated their IFTT interfaces and Google home is useless for automation.
My google nest controls my boiler, I might replace it with a relay instead if that would work better, but even so, the IFTT api doesn't support the thermostats yet.
So I basically want to find a way to have my Nest turn off if all radiators are turned off OR aren't requesting heat (they're at the desired temperature)... otherwise, set the nest to the maximum 32° as we installed the nest in the lounge about 2 years ago which went well.. but during the last summer we installed a wood burning stove in the lounge and so when we're using that, we need the nest to be set to the maximum temp (or above 25°) otherwise it won't ever turn the boiler on and the lounge gets toasty while the rest of the house freezes
Currently I have it set up to turn onto 32° at 05:45 and set to 9° (off) at 22:00. Then in the Kasa app I have the specific schedule setup.
This seems pretty wasteful to me as the nest is running even once all the radiators have reached the desired temperature and turned off. (The bathroom radiators aren't controlled by the valves though so they take all the heat)
I wrote some logic code if that's easier to understand my objective:
if all_radiators.state == off || all_radiators.roomtemp == desired_temp {
set_nest.temp(0)
}
else {
set_nest.temp(30) }
rytilahti commented on Feb 7, 2023
@AntonyKing7D those paths (and the TPLINK_SESSIONID) look similar to the protocol implemented in #267 that was never finished. Maybe you could give it a try to see if that's really the case?
To check the discovery, I suppose something like this should work:
and even when there's no device support, maybe you can try to request the sysinfo data:
AntonyKing7D commented on Feb 7, 2023
I don't see --user or --password as parameters for kasa? Without those parameters I get a connection refused error:
sudo /home/ant/.local/bin/kasa -d --host 192.168.21.17 --type plug sysinfo
ConnectionRefusedError: [Errno 111] Connect call failed ('192.168.21.17', 9999)
tried with and without sudo .
[edit] I've just discovered the fork which implements this , https://github.com/TokonatsuFestival/python-kasa/tree/new-enc-protocol . That's going to take me a while to figure out, I suspect .
36 remaining items
Mikey887 commented on Jul 11, 2023
Error: Tapo(InvalidCredentials)
I used my kasa app credentials (I did also double check they were right)
cargo run --example tapo_generic_device
Finished dev [unoptimized + debuginfo] target(s) in 0.20s
Running target/debug/examples/tapo_generic_device
Error: Tapo(InvalidCredentials)
laxdog commented on Aug 31, 2023
Is there any way I can help out with this? I see that code has now been added for unsupported devices in https://github.com/python-kasa/python-kasa/pull/488 , which I assume is the first step towards this working.
I have the KH100(UK) and a few KE100.
Though I can see that there's no comms over 9999 for the hub. The pcap I captured was all comms with AWS over https. Which the parse_pcap.py script, understandably, didn't know what to do with. The only open TCP port is 80 on the hub.
I've half an idea what I'm doing with python and tcpdump and willing to lend a hand.
iambenmitchell commented on Oct 18, 2023
Still no progress with this?
It’s winter again now in the UK and there’s still no solution for turning on an off the boiler based on if the KE100 thermostats are trying to heat or not. I just have to have it on all day
rytilahti commented on Oct 18, 2023
The status is the same as written in #422 (comment) – This will require someone with a device (or enough time to try to obtain the information otherwise) to reverse engineer the necessary bits and create an implementation. So PRs are still welcome and I can help with code reviews to get it merged. If the AES one is similar to KLAP, #509 might be a helpful starting point to start implementing it. If it's a completely different, that PR still introduces an abstract interface to be implemented.
@laxdog the discovery part helps only to discover devices using the new discovery protocol (which is being used by some kasa devices as well as by tapo line), so it doesn't really help that much wrt. the issue at hand. Anyway, was there any direct communications that did not go via the cloud?
DaveGut commented on Oct 18, 2023
My Hubitat experience with the protocol for the Kasa Matter devices is that is is the EXACT API and Protocol (AES) as the TAPO devices. I think this extends to the Hub. So, look toward the TAPO hub integrations as a starting point with only a few mods to get the Hub working (look for KASA.SMARTHUB vice TAPO.SMARTHUB on the port 20002 discovery message).
rytilahti commented on Oct 18, 2023
Okay, great! Then it might be useful to take a look at https://github.com/petretiandrea/plugp100 which implements support for tapo hubs to my understanding.
DaveGut commented on Oct 18, 2023
Yes. Even has the KLAP protocol (which is not used yet on the Kasa devices but i a good risk mitigation).
laxdog commented on Nov 13, 2023
Yes, I captured a pcap. There's quite a lot of chatter between my phone and the Smart Hub. I'll have a look at that other repo and see if I can work anything out.
rytilahti commented on Nov 13, 2023
petretiandrea/plugp100#153 this might be interesting for you.
laxdog commented on Nov 13, 2023
Just got the main line working from plugp100 and recognising the hub and the TRVs, I just can't control them. I'll give that PR a go soon, then maybe look at doing something in here.
DaveGut commented on Nov 14, 2023
Try sending the following command to the Hub: [method: "get_child_device_list"] and get me the data (private message). That will have clues as to the basic device commands.
You could also try the following command:
[
device_id: DEVICEID FROM ABOVE,
method: "get_child_device_component_list"
]
delatt commented on Nov 14, 2023
I had no idea this project existed!
I should have a PR which adds functionality to HA in https://github.com/petretiandrea/home-assistant-tapo-p100 up soon. Just need to finish up my tests
delatt commented on Nov 27, 2023
It's been released now: petretiandrea/home-assistant-tapo-p100#611. Let me know if you have any issues 🙂
cygnus-atratus commented on Jan 10, 2024
I'm diving to the bottom here and will read through this thread later.
Just letting you all know that I have been able to control these via IFTTT per-say but limited use.
use case example:
Create a Kasa "scenes" that includes the Thermostat functions you want on the Kasa App.
Then you can trigger these "scenes" via IFTTT.
While you may not be able to see the Thermostats directly or modify them through IFTTT you can manually assign these thermostats to "scenes" which can be triggered via IFTTT