Skip to content

Support new_klap IoT devices#1580

Open
ZeliardM wants to merge 37 commits into
python-kasa:masterfrom
ZeliardM:feature/new-klap
Open

Support new_klap IoT devices#1580
ZeliardM wants to merge 37 commits into
python-kasa:masterfrom
ZeliardM:feature/new-klap

Conversation

@ZeliardM

@ZeliardM ZeliardM commented Sep 29, 2025

Copy link
Copy Markdown
Collaborator

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

codecov Bot commented Sep 29, 2025

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 97.33333% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 93.40%. Comparing base (88e1c27) to head (71a4147).

Files with missing lines Patch % Lines
kasa/cli/discover.py 66.66% 1 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #1580      +/-   ##
==========================================
+ Coverage   93.21%   93.40%   +0.18%     
==========================================
  Files         157      157              
  Lines        9819     9870      +51     
  Branches     1005     1013       +8     
==========================================
+ Hits         9153     9219      +66     
+ Misses        472      462      -10     
+ Partials      194      189       -5     

☔ View full report in Codecov by Harness.
📢 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
Collaborator 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
Collaborator 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

ZeliardM commented Oct 1, 2025

Copy link
Copy Markdown
Collaborator Author

@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

Copilot AI left a comment

Copy link
Copy Markdown

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

ZeliardM commented Oct 2, 2025

Copy link
Copy Markdown
Collaborator Author

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

@rytilahti rytilahti left a comment

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.

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

Comment thread kasa/device_factory.py Outdated
Comment thread kasa/deviceconfig.py Outdated
Comment thread kasa/discover.py Outdated
Comment thread tests/smart/modules/test_childsetup.py
Comment thread kasa/cli/hub.py
Comment thread tests/smart/modules/test_powerprotection.py
@ZeliardM ZeliardM changed the title Implement KlapTransportV3 for new_klap Implement KlapTransportV2 for new_klap Oct 7, 2025
@ZeliardM

ZeliardM commented Oct 7, 2025

Copy link
Copy Markdown
Collaborator Author

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

@rytilahti rytilahti left a comment

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.

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!

Comment thread tests/test_cli.py Outdated
Comment thread tests/test_discovery.py Outdated
Comment thread kasa/device_factory.py Outdated
Comment thread kasa/discover.py Outdated
Comment thread kasa/discover.py Outdated
@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!

@Allowencer

Allowencer commented Feb 19, 2026

Copy link
Copy Markdown

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 ==

Comment thread kasa/cli/main.py Outdated
Comment thread kasa/device_models.py Outdated
Comment thread kasa/discover.py Outdated
Comment thread tests/device_fixtures.py
Comment thread kasa/device_factory.py
@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.

@genzj

genzj commented Apr 27, 2026

Copy link
Copy Markdown

test log

I tested the PR and it's working with HS103 firmware 1.1.3.

Reminder: after upgrading the plug to firmware 1.1.3, even correct credentials can trigger an authentication error. The fix was to unregister the plug from the app and reinitialize it.

(.venv) user@host:~/kasa$ kasa -v -d --host REDACTED_IP sysinfo
Discovering device REDACTED_IP for 10 seconds
DEBUG:kasa.discover:[DISCOVERY] REDACTED_IP >> {'system': {'get_sysinfo': {}}}
DEBUG:kasa.discover:Waiting a total of 10 seconds for responses...
DEBUG:kasa.device_factory:Finding protocol for REDACTED_IP
DEBUG:kasa.device_factory:Finding protocol for DeviceFamily.IotSmartPlugSwitch
DEBUG:kasa.device_factory:Finding transport for IOT.KLAP.NEW_KLAP
DEBUG:kasa.transports.klaptransport:Created KLAP transport for REDACTED_IP
DEBUG:kasa.protocols.iotprotocol:REDACTED_IP >> {"system":{"get_sysinfo":{}}}
DEBUG:kasa.transports.klaptransport:Starting handshake with REDACTED_IP
DEBUG:kasa.httpclient:Posting to http://REDACTED_IP/app/handshake1
DEBUG:kasa.transports.klaptransport:Handshake1 posted at 2026-04-26 20:39:38.854634. Host is REDACTED_IP, Response status is 200, Request was REDACTED_REQUEST_ID
DEBUG:kasa.transports.klaptransport:Handshake1 success at 2026-04-26 20:39:38.854874. Host is REDACTED_IP, Server remote_seed is: REDACTED_REMOTE_SEED, server hash is: REDACTED_SERVER_HASH
DEBUG:kasa.transports.klaptransport:handshake1 hashes match with expected credentials
DEBUG:kasa.httpclient:Posting to http://REDACTED_IP/app/handshake2
DEBUG:kasa.transports.klaptransport:Handshake2 posted 2026-04-26 20:39:38.860822. Host is REDACTED_IP, Response status is 200, Request was REDACTED_REQUEST_ID_2
DEBUG:kasa.transports.klaptransport:Handshake with REDACTED_IP complete
DEBUG:kasa.httpclient:Posting to http://REDACTED_IP/app/request
DEBUG:kasa.transports.klaptransport:Device REDACTED_IP query posted Host is REDACTED_IP, Sequence is -1639787443, Response status is 200, Request was {"system":{"get_sysinfo":{}}}
DEBUG:kasa.transports.klaptransport:Device REDACTED_IP query response received
DEBUG:kasa.protocols.iotprotocol:REDACTED_IP << {'system': {'get_sysinfo': {'active_mode': 'none',
                            'alias': '#MASKED_NAME#',
                            'dev_name': 'Smart Wi-Fi Plug Mini',
                            'deviceId': 'REDACTED_DEVICE_ID',
                            'err_code': 0,
                            'feature': 'TIM',
                            'hwId': 'REDACTED_HW_ID',
                            'hw_ver': '5.0',
                            'icon_hash': '',
                            'latitude_i': 0,
                            'led_off': 0,
                            'lnk_on': 0,
                            'longitude_i': 0,
                            'mac': 'REDACTED_MAC',
                            'mic_type': 'IOT.SMARTPLUGSWITCH',
                            'model': 'HS103(US)',
                            'next_action': {'type': -1},
                            'obd_src': 'tplink',
                            'oemId': 'REDACTED_OEM_ID',
                            'on_time': 0,
                            'relay_state': 0,
                            'rssi': -26,
                            'status': 'new',
                            'sw_ver': '1.1.3 Build 250908 Rel.112508',
                            'updating': 0}}}
DEBUG:kasa.device:Initializing REDACTED_IP of type <class 'kasa.iot.iotplug.IotPlug'>
DEBUG:kasa.discover:[DISCOVERY] REDACTED_IP << {'error_code': 0,
 'result': {'device_id': 'REDACTED_DEVICE_ID',
            'device_model': 'HS103(US)',
            'device_type': 'IOT.SMARTPLUGSWITCH',
            'factory_default': False,
            'hw_ver': '5.0',
            'ip': 'REDACTED_IP',
            'mac': 'REDACTED_MAC',
            'mgt_encrypt_schm': {'ANS': False,
                                 'encrypt_type': 'KLAP',
                                 'http_port': 80,
                                 'is_support_https': False,
                                 'lv': 2,
                                 'new_klap': 1},
            'obd_src': 'tplink',
            'owner': 'REDACTED_OWNER',
            'protocol_version': 1}}
DEBUG:kasa.iot.iotdevice:Performing the initial update to obtain sysinfo
DEBUG:kasa.protocols.iotprotocol:REDACTED_IP >> {"system":{"get_sysinfo":{}}}
DEBUG:kasa.httpclient:Posting to http://REDACTED_IP/app/request
DEBUG:kasa.transports.klaptransport:Device REDACTED_IP query posted Host is REDACTED_IP, Sequence is -1639787442, Response status is 200, Request was {"system":{"get_sysinfo":{}}}
DEBUG:kasa.transports.klaptransport:Device REDACTED_IP query response received
DEBUG:kasa.protocols.iotprotocol:REDACTED_IP << {'system': {'get_sysinfo': {'active_mode': 'none',
                            'alias': '#MASKED_NAME#',
                            'dev_name': 'Smart Wi-Fi Plug Mini',
                            'deviceId': 'REDACTED_DEVICE_ID',
                            'err_code': 0,
                            'feature': 'TIM',
                            'hwId': 'REDACTED_HW_ID',
                            'hw_ver': '5.0',
                            'icon_hash': '',
                            'latitude_i': 0,
                            'led_off': 0,
                            'lnk_on': 0,
                            'longitude_i': 0,
                            'mac': 'REDACTED_MAC',
                            'mic_type': 'IOT.SMARTPLUGSWITCH',
                            'model': 'HS103(US)',
                            'next_action': {'type': -1},
                            'obd_src': 'tplink',
                            'oemId': 'REDACTED_OEM_ID',
                            'on_time': 0,
                            'relay_state': 0,
                            'rssi': -26,
                            'status': 'new',
                            'sw_ver': '1.1.3 Build 250908 Rel.112508',
                            'updating': 0}}}
DEBUG:kasa.iot.iotdevice:Adding module <Module HomeKit (smartlife.iot.homekit) for REDACTED_IP>
DEBUG:kasa.iot.iotdevice:Adding module <Module Schedule (schedule) for REDACTED_IP>
DEBUG:kasa.iot.iotdevice:Adding module <Module Usage (schedule) for REDACTED_IP>
DEBUG:kasa.iot.iotdevice:Adding module <Module Antitheft (anti_theft) for REDACTED_IP>
DEBUG:kasa.iot.iotdevice:Adding module <Module Time (time) for REDACTED_IP>
DEBUG:kasa.iot.iotdevice:Adding module <Module Cloud (cnCloud) for REDACTED_IP>
DEBUG:kasa.iot.iotdevice:Adding module <Module Led (system) for REDACTED_IP>
DEBUG:kasa.iot.iotmodule:Initial update, so consider supported: smartlife.iot.homekit
DEBUG:kasa.iot.iotdevice:Adding query for <Module HomeKit (smartlife.iot.homekit) for REDACTED_IP>: {'smartlife.iot.homekit': {'setup_info_get': {}}}
DEBUG:kasa.iot.iotmodule:Initial update, so consider supported: schedule
DEBUG:kasa.iot.iotdevice:Adding query for <Module Schedule (schedule) for REDACTED_IP>: {'schedule': {'get_rules': {}, 'get_next_action': {}}}
DEBUG:kasa.iot.iotmodule:Initial update, so consider supported: schedule
DEBUG:kasa.iot.iotdevice:Adding query for <Module Usage (schedule) for REDACTED_IP>: {'schedule': {'get_realtime': {}, 'get_daystat': {'year': 2026, 'month': 4}, 'get_monthstat': {'year': 2026}}}
DEBUG:kasa.iot.iotmodule:Initial update, so consider supported: anti_theft
DEBUG:kasa.iot.iotdevice:Adding query for <Module Antitheft (anti_theft) for REDACTED_IP>: {'anti_theft': {'get_rules': {}, 'get_next_action': {}}}
DEBUG:kasa.iot.iotmodule:Initial update, so consider supported: time
DEBUG:kasa.iot.iotdevice:Adding query for <Module Time (time) for REDACTED_IP>: {'time': {'get_time': {}, 'get_timezone': {}}}
DEBUG:kasa.iot.iotmodule:Initial update, so consider supported: cnCloud
DEBUG:kasa.iot.iotdevice:Adding query for <Module Cloud (cnCloud) for REDACTED_IP>: {'cnCloud': {'get_info': {}}}
DEBUG:kasa.iot.iotdevice:Adding query for <Module Led (system) for REDACTED_IP>: {}
DEBUG:kasa.protocols.iotprotocol:REDACTED_IP >> {"system":{"get_sysinfo":{}},"smartlife.iot.homekit":{"setup_info_get":{}},"schedule":{"get_rules":{},"get_next_action":{},"get_realtime":{},"get_daystat":{"year":2026,"month":4},"get_monthstat":{"year":2026}},"anti_theft":{"get_rules":{},"get_next_action":{}},"time":{"get_time":{},"get_timezone":{}},"cnCloud":{"get_info":{}}}
DEBUG:kasa.httpclient:Posting to http://REDACTED_IP/app/request
DEBUG:kasa.transports.klaptransport:Device REDACTED_IP query posted Host is REDACTED_IP, Sequence is -1639787441, Response status is 200, Request was {"system":{"get_sysinfo":{}},"smartlife.iot.homekit":{"setup_info_get":{}},"schedule":{"get_rules":{},"get_next_action":{},"get_realtime":{},"get_daystat":{"year":2026,"month":4},"get_monthstat":{"year":2026}},"anti_theft":{"get_rules":{},"get_next_action":{}},"time":{"get_time":{},"get_timezone":{}},"cnCloud":{"get_info":{}}}
DEBUG:kasa.transports.klaptransport:Device REDACTED_IP query response received
DEBUG:kasa.protocols.iotprotocol:REDACTED_IP << {'anti_theft': {'get_next_action': {'err_code': -2,
                                    'err_msg': 'member not support'},
                'get_rules': {'enable': 0,
                              'err_code': 0,
                              'rule_list': [],
                              'version': 2}},
 'cnCloud': {'get_info': {'binded': 1,
                          'cld_connection': 1,
                          'err_code': 0,
                          'fwDlPage': '',
                          'fwNotifyType': -1,
                          'illegalType': 0,
                          'server': 'n-devs.tplinkcloud.com',
                          'stopConnect': 0,
                          'tcspInfo': '',
                          'tcspStatus': 1,
                          'username': 'REDACTED_USERNAME'}},
 'schedule': {'get_daystat': {'day_list': [{'day': 26,
                                            'month': 4,
                                            'time': 68,
                                            'year': 2026}],
                              'err_code': 0},
              'get_monthstat': {'err_code': 0,
                                'month_list': [{'month': 4,
                                                'time': 68,
                                                'year': 2026}]},
              'get_next_action': {'err_code': 0, 'type': -1},
              'get_realtime': {'err_code': -2, 'err_msg': 'member not support'},
              'get_rules': {'enable': 1,
                            'err_code': 0,
                            'rule_list': [],
                            'version': 2}},
 'smartlife.iot.homekit': {'err_code': -1, 'err_msg': 'module not support'},
 'system': {'get_sysinfo': {'active_mode': 'none',
                            'alias': '#MASKED_NAME#',
                            'dev_name': 'Smart Wi-Fi Plug Mini',
                            'deviceId': 'REDACTED_DEVICE_ID',
                            'err_code': 0,
                            'feature': 'TIM',
                            'hwId': 'REDACTED_HW_ID',
                            'hw_ver': '5.0',
                            'icon_hash': '',
                            'latitude_i': 0,
                            'led_off': 0,
                            'lnk_on': 0,
                            'longitude_i': 0,
                            'mac': 'REDACTED_MAC',
                            'mic_type': 'IOT.SMARTPLUGSWITCH',
                            'model': 'HS103(US)',
                            'next_action': {'type': -1},
                            'obd_src': 'tplink',
                            'oemId': 'REDACTED_OEM_ID',
                            'on_time': 0,
                            'relay_state': 0,
                            'rssi': -26,
                            'status': 'new',
                            'sw_ver': '1.1.3 Build 250908 Rel.112508',
                            'updating': 0}},
 'time': {'get_time': {'err_code': 0,
                       'hour': 20,
                       'mday': 26,
                       'min': 39,
                       'month': 4,
                       'sec': 38,
                       'year': 2026},
          'get_timezone': {'err_code': 0, 'index': 6}}}
== System info ==
{'active_mode': 'none',
 'alias': '#MASKED_NAME#',
 'dev_name': 'Smart Wi-Fi Plug Mini',
 'deviceId': 'REDACTED_DEVICE_ID',
 'err_code': 0,
 'feature': 'TIM',
 'hwId': 'REDACTED_HW_ID',
 'hw_ver': '5.0',
 'icon_hash': '',
 'latitude_i': REDACTED_LATITUDE,
 'led_off': 0,
 'lnk_on': 0,
 'longitude_i': REDACTED_LONGITUDE,
 'mac': 'REDACTED_MAC',
 'mic_type': 'IOT.SMARTPLUGSWITCH',
 'model': 'HS103(US)',
 'next_action': {'type': -1},
 'obd_src': 'tplink',
 'oemId': 'REDACTED_OEM_ID',
 'on_time': 0,
 'relay_state': 0,
 'rssi': -26,
 'status': 'new',
 'sw_ver': '1.1.3 Build 250908 Rel.112508',
 'updating': 0}

@ZeliardM

Copy link
Copy Markdown
Collaborator Author

@genzj Thanks for the test and information. There are still some transient issues with Discover and how devices respond that can cause some issues but overall this fix works. I have several other PRs that I'm trying to get all worked on and merged before another release but I'm not sure when that will happen.

@Commod0re

Copy link
Copy Markdown

any update on the status of this PR? my two HS300s suddenly stopped working with home-assistant today and I think this is why...

@ZeliardM ZeliardM changed the title Implement KlapTransportV2 for new_klap Support new_klap IoT devices Jul 8, 2026
@ZeliardM

ZeliardM commented Jul 8, 2026

Copy link
Copy Markdown
Collaborator Author

Follow-up pass pushed in 71a4147.

Covered in this pass:

  • Resolved the remaining device factory review thread by keeping direct-connect IoT class selection based on the queried get_sysinfo response instead of the discovery response, with regression coverage in test_connect_iot_family_resolves_subclass_from_sysinfo.
  • Tightened tests/test_discovery.py discovery payload typing with TypedDict/structured annotations so the new KLAP fixture data no longer falls back to Any.
  • Matched the annotation direction from tests: add type annotations to top-level test files #1688 for the overlapping test files; tests: add type annotations to transport tests #1684 remains transport-test-only and does not overlap this PR's changed paths.
  • Fixed discover config output for new_klap=True devices so it prints a round-trippable --encrypt-type KLAPV2 value instead of the internal KLAP value.
  • Updated the PR title to Support new_klap IoT devices.

Local validation:

  • uv run pytest -q passed: 22547 passed, 852 skipped.
  • Targeted ruff check, ruff format --check, mypy, and git diff --check passed for the touched files.

After the push, GitHub lint and CodeQL were already green; the matrix CI/readthedocs jobs were still running when I checked.

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)

8 participants