Skip to content

Implement KlapTransportV2 for new_klap#1580

Open
ZeliardM wants to merge 34 commits intopython-kasa:masterfrom
ZeliardM:feature/new-klap
Open

Implement KlapTransportV2 for new_klap#1580
ZeliardM wants to merge 34 commits intopython-kasa:masterfrom
ZeliardM:feature/new-klap

Conversation

@ZeliardM
Copy link
Copy Markdown
Contributor

@ZeliardM ZeliardM commented Sep 29, 2025

Implementing KlapTranportV2 to handle IoT devices with newer firmware and a new_klap flag and all associated tests hopefully.

With this PR, I will get the user to pull the specific branch for testing on their end, and I will test on my end to make sure that the old stuff still functions as well.

@codecov
Copy link
Copy Markdown

codecov bot commented Sep 29, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 93.43%. Comparing base (be5ce08) to head (74b0452).
⚠️ Report is 1 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #1580      +/-   ##
==========================================
+ Coverage   93.22%   93.43%   +0.21%     
==========================================
  Files         157      157              
  Lines        9815     9860      +45     
  Branches     1003     1010       +7     
==========================================
+ Hits         9150     9213      +63     
+ Misses        472      460      -12     
+ Partials      193      187       -6     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@ZeliardM
Copy link
Copy Markdown
Contributor Author

@rytilahti I haven't seen this before:
GitHub Advanced Security / CodeQL
failed 44 minutes ago in 3s
1 new alert including 1 high severity security vulnerability
New alerts in code changed by this pull request
Security Alerts:

1 high
See annotations below for details.

View all branch alerts.

Annotations
Check failure on line 85 in kasa/transports/klaptransport.py

Code scanning
/ CodeQL

Use of a broken or weak cryptographic hashing algorithm on sensitive data
High

is used in a hashing algorithm (SHA1) that is insecure.
is used in a hashing algorithm (SHA1) that is insecure.
is used in a hashing algorithm (SHA1) that is insecure for password hashing, since it is not a computationally expensive hash function.
is used in a hashing algorithm (SHA1) that is insecure for password hashing, since it is not a computationally expensive hash function.

Is this because I modified this file and now it's looking at it? You had the code they flag already in your code, but I'm not sure why it's being flagged as a problem now.

@ZeliardM
Copy link
Copy Markdown
Contributor Author

Ok, had my user test and the discovery and CLI tests were successful, but we're getting 400 error responses at first with handshake1 one or two times and then it works. Not sure what that's about yet, will keep poking around.

@ZeliardM
Copy link
Copy Markdown
Contributor Author

ZeliardM commented Oct 1, 2025

@rytilahti Ok, here's where it gets weird. I found that it actually isn't a new KLAP, it still uses XOR. The issue isn't the actual transport, it's how it's selecting the transport. I will modify things so that in the device factory, it's still forcing XOR if the device has new_klap. It's a much easier fix and has been working consistently on my end.

Copilot AI review requested due to automatic review settings October 2, 2025 15:07
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR implements KlapTransportV3 for the new_klap protocol by adding support for a new "new_klap" parameter throughout the discovery and device configuration system. The implementation allows devices that support this new KLAP variant to be properly detected and configured to use XorTransport instead of the standard KlapTransport.

Key changes:

  • Added new_klap parameter to device configuration and discovery classes
  • Implemented special handling in discovery protocol to finalize devices with new_klap capability
  • Updated device factory to route new_klap devices to XorTransport instead of KlapTransport

Reviewed Changes

Copilot reviewed 14 out of 14 changed files in this pull request and generated no comments.

Show a summary per file
File Description
kasa/deviceconfig.py Added new_klap field to DeviceConnectionParameters with custom serialization
kasa/discover.py Added new_klap support to discovery protocol with special finalization logic
kasa/device_factory.py Added routing logic to use XorTransport for new_klap devices
tests/test_discovery.py Added comprehensive test for new_klap discovery finalization behavior
tests/test_deviceconfig.py Added test configuration and serialization test for new_klap
tests/test_device_factory.py Added test case for new_klap protocol selection
devtools/dump_devinfo.py Updated device info capture to include new_klap parameter
Comments suppressed due to low confidence (1)

tests/test_cli.py:1

  • [nitpick] The test logic has changed from using explicit assert_not_called() and assert_called() to comparing call counts. This approach is less clear about the expected behavior and makes the test harder to understand. Consider using more descriptive assertions or adding comments explaining why call counts are being compared.
import json

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

@ZeliardM
Copy link
Copy Markdown
Contributor Author

ZeliardM commented Oct 2, 2025

@rytilahti Ok, so you can understand what I did here. I managed to make it where during discovery, it adds a new_klap portion to the management schema if it exists. Then it checks if that exists and if so, it runs the XOR transport on the IOT protocol. Otherwise, it was trying to actually use the KLAP transport which even though it says KLAP it's XOR. This allows the device to initially be discovered, but the problem comes up where the KLAP discovery results don't allow for the segmented device types for IOT. So, I update the device one time, pull the sysinfo, then mutate that back to what a XOR discovery result would be and re-initialize the device from the sysinfo. This seems to be working quite well and reliably for me and the one user who has been testing this with me, @allenrabinovich. Old IOT and new SMART devices are working correctly for me as well.

Copy link
Copy Markdown
Member

@rytilahti rytilahti left a comment

Choose a reason for hiding this comment

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

A couple of quick comments, also, please do not forget to change the title of this PR when this is ready for a review :-)

@ZeliardM ZeliardM changed the title Implement KlapTransportV3 for new_klap Implement KlapTransportV2 for new_klap Oct 7, 2025
@ZeliardM
Copy link
Copy Markdown
Contributor Author

ZeliardM commented Oct 7, 2025

@rytilahti Ok, I think I got everything figured out. It is actually KlapTransportV2. I have modified everything to handle this and updated all of the test coverage as well. Everything looks good on my end as well.

Copy link
Copy Markdown
Member

@rytilahti rytilahti left a comment

Choose a reason for hiding this comment

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

I cannot test this mysef, but it looks good on surface. I would suggest tidying it up a bit to keep the code more maintainable if and when new authentication methods pop up, but your call!

@rytilahti rytilahti added the enhancement New feature or request label Oct 11, 2025
@rytilahti rytilahti added this to the 0.11 milestone Oct 11, 2025
@Hashcode
Copy link
Copy Markdown

I tested this locally and it's working well so far.
Model: HS300 (power strip)
Firmware: 1.1.2 Build 241220 Rel.171333 (I think this is the latest as of 2025-10-30)

Thanks!

@ZeliardM
Copy link
Copy Markdown
Contributor Author

Ok, sounds good. I will see if there is a way to add something about failing to connect to try KLAPV2 for encrypt_type, will see what I can put together and push out.

@ZeliardM
Copy link
Copy Markdown
Contributor Author

ZeliardM commented Dec 9, 2025

@rytilahti @Hashcode Ok, I have added in the CLI --encrypt-type KLAPV2 for this and that should resolve the remaining CLI issues. Let me know what you think and if we're good, this should be good to merge now.

@ZeliardM
Copy link
Copy Markdown
Contributor Author

ZeliardM commented Dec 9, 2025

Found a few errors while testing, this last commit should fix them. @Hashcode Again, give it a test and let me know. @rytilahti Let me know when you want to proceed with this one, I am still working on the TPAP implementation, I think it should be in a new version with this one.

@Hashcode
Copy link
Copy Markdown

@ZeliardM Sorry for the delay. I was out all last week with the flu.

From my tests, this solves the issues I was seeing:

uv run kasa --type smart --device-family "IOT.SMARTPLUGSWITCH" --encrypt-type KLAPV2 --host $KASA_SERVER --credentials-hash "$KASA_CREDENTIALS_HASH" device --index 0 state

Targeting child device Plug 1
== Plug 1 - Socket for HS300(US) ==
Host: ###.###.###.###
Port: 80
Device state: True
Time:         2025-12-15 12:49:25-08:00 (tz: PST8PDT)
Hardware:     2.0 (US)
Firmware:     1.1.2 Build 241220 Rel.171333
MAC (rssi):   ##:##:##:##:##:## (-27)

== Primary features ==
State (state): True
Current consumption (current_consumption): 0.0 W
Voltage (voltage): 126.2 V
Current (current): 0.0 A

== Information ==
On since (on_since): 2025-11-11 12:47:24-08:00
Today's consumption (consumption_today): 0.0 kWh
This month's consumption (consumption_this_month): 0.0 kWh
Total consumption since reboot (consumption_total): 1.237 kWh

== Configuration ==

== Debug ==

Thanks for the hard work on this!

@ZeliardM
Copy link
Copy Markdown
Contributor Author

ZeliardM commented Dec 15, 2025

@Hashcode Excellent, thanks! @rytilahti This looks like it's good to go if you are.

@Allowencer
Copy link
Copy Markdown

Allowencer commented Feb 19, 2026

Need anymore testing on this? I use this module within MaaSPower https://github.com/gilesknap/maaspower (I'll sync with them once this is merged to a new version to update their project), but I can run the kasa commands on my utility Linux server as a webservice as I use the power commands within Canonical's MaaS (Metal as a Service) solution which manages my k8s master nodes in my home environment. Constantly heartbeats for power states - could be a good test?

@Allowencer
Copy link
Copy Markdown

I pulled the PR and it's working for me in a test venv:

(kasa-pr-test) server:/opt/maas_power/python-kasa# kasa --host 192.168.x.y sysinfo
Discovering device 192.168.x.y for 10 seconds
== System info ==
{'alias': 'TP-LINK_Power Strip_CE60',
 'child_num': 6,
 'children': [{'alias': 'Plug 1',
               'id': '80062DCE3BB0AE17EF9B7632315F8F9E236BCD8C00',
               'next_action': {'type': -1},
               'on_time': 55836,
               'state': 1},
              {'alias': 'Plug 2',
               'id': '80062DCE3BB0AE17EF9B7632315F8F9E236BCD8C01',
               'next_action': {'type': -1},
               'on_time': 0,
               'state': 0},
              {'alias': 'Plug 3',
               'id': '80062DCE3BB0AE17EF9B7632315F8F9E236BCD8C02',
               'next_action': {'type': -1},
               'on_time': 0,
               'state': 0},
              {'alias': 'Plug 4',
               'id': '80062DCE3BB0AE17EF9B7632315F8F9E236BCD8C03',
               'next_action': {'type': -1},
               'on_time': 55836,
               'state': 1},
              {'alias': 'Plug 5',
               'id': '80062DCE3BB0AE17EF9B7632315F8F9E236BCD8C04',
               'next_action': {'type': -1},
               'on_time': 55836,
               'state': 1},
              {'alias': 'Plug 6',
               'id': '80062DCE3BB0AE17EF9B7632315F8F9E236BCD8C05',
               'next_action': {'type': -1},
               'on_time': 55836,
               'state': 1}],
 'deviceId': '80062DCE3BB0AE17EF9B7632315F8F9E236B',
 'err_code': 0,
 'feature': 'TIM:ENE',
 'hwId': '955F433CBA24823A248A59AA6457',
 'hw_ver': '2.0',
 'latitude_i': -1,
 'led_off': 0,
 'lnk_on': 1,
 'longitude_i': -1,
 'mac': ' ..:..:..:..:..',
 'mic_type': 'IOT.SMARTPLUGSWITCH',
 'model': 'HS300(US)',
 'obd_src': 'tplink',
 'oemId': '32BD0B21AA9BF8E84737D1DB1C66E883',
 'rssi': -35,
 'status': 'new',
 'sw_ver': '1.1.2 Build 241220 Rel.171333',
 'updating': 0}


(kasa-pr-test) server:/opt/maas_power/python-kasa# kasa --host 192.168.x.y device state --child-index 5
Discovering device 192.168.x.y for 10 seconds
Targeting child device Plug 6
== Plug 6 - Socket for HS300(US) ==
Host: 192.168.x.y
Port: 9999
Device state: True
Time:         2026-02-19 15:29:33-05:00 (tz: EST)
Hardware:     2.0 (US)
Firmware:     1.1.2 Build 241220 Rel.171333
MAC (rssi):   ..:..:..:..:.. (-35)

== Primary features ==
State (state): True
Current consumption (current_consumption): 16.0 W
Voltage (voltage): 121.2 V
Current (current): 0.25 A

== Information ==
On since (on_since): 2026-02-18 23:58:13-05:00
Today's consumption (consumption_today): 0.265 kWh
This month's consumption (consumption_this_month): 7.759 kWh
Total consumption since reboot (consumption_total): 0.266 kWh

== Configuration ==

== Debug ==

if issubclass(device_class, IotDevice):
info = await protocol.query(GET_SYSINFO_QUERY)
_perf_log(True, "get_sysinfo")
device_class = get_device_class_from_sys_info(info)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Having checks like this indicates usually a code smell. Looking at the discovery response in the fixture, should it not be enough for us to decide on the device class?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

So, the biggest problem here is that with new_klap devices, they give a different discovery_result than the other IOT devices. They give a discovery_result that looks like the SMART devices, so there is no sysinfo. You need to give a base device type to get the sysinfo, then do a full discovery based on that because of the way that kasa identifies the devices with SMARTPLUGSWITCH or SMARTBULB and we break them all out into individual device classes which from the new discovery_result, you base the class off the family which does not work for all of the possible device types for IOT.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Maybe we need to update the dev_tool as well to handle the new discovery result more like the SMART devices for new_klap devices that are IOT?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

It's odd too, sometimes the device responds with new_klap, sometimes i doesn't...I need to see if there is a way I can force it to always use new_klap and if I can get a new fixture that looks correct.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Ok, I got a good fixture for the HS300 device, it has the following discovery result:

"discovery_result": {
"error_code": 0,
"result": {
"device_id": "00000000000000000000000000000000",
"device_model": "HS300(US)",
"device_type": "IOT.SMARTPLUGSWITCH",
"factory_default": false,
"hw_ver": "2.0",
"ip": "127.0.0.123",
"mac": "F0-A7-31-00-00-00",
"mgt_encrypt_schm": {
"ANS": false,
"encrypt_type": "KLAP",
"http_port": 80,
"is_support_https": false,
"lv": 2,
"new_klap": 1
},
"obd_src": "tplink",
"owner": "00000000000000000000000000000000",
"protocol_version": 1
}
},

This causes problems when it's classified as an IOT device but uses the new discovery process, but I've gotten everything I think squared away here on this one as well. Give it a once over if you want to include it in the next release as well.

@srtviperjr
Copy link
Copy Markdown

Any idea when this might make it to production? I had been using the patch in this post after each HomeAssistant update but after the latest 2026.2.3 the patch doesn't work anymore.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

IOT devices with KLAP encryption and login_version=2 use wrong transport (KlapTransport instead of KlapTransportV2)

6 participants