Skip to content

TPAP Implementation#1592

Open
ZeliardM wants to merge 68 commits intopython-kasa:masterfrom
ZeliardM:feature/tpap
Open

TPAP Implementation#1592
ZeliardM wants to merge 68 commits intopython-kasa:masterfrom
ZeliardM:feature/tpap

Conversation

@ZeliardM
Copy link
Copy Markdown
Contributor

Discovered with new firmware for devices, TP-Link is implementing a new Encryption Type, TPAP. This is an initial implementation to see if the coding works for the handshake. Testing of the code coverage still has to be worked on. The initial implementation includes the new transport, changes to the device_factory to allow devices to select the new transport, and a change to the project to include ecdsa as a new dependency along with cryptography for the new tpaptransport.py.

Copilot AI review requested due to automatic review settings October 18, 2025 19:48
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

Implements the new TPAP (TP-Link Adaptive Protocol) encryption type with SPAKE2+ HTTPS transport for TP-Link devices. This is an initial implementation to test handshake functionality with new firmware that uses TPAP encryption.

  • Added complete TPAP transport implementation using SPAKE2+ P-256 handshake and AEAD data channel
  • Updated device factory to support TPAP encryption type routing
  • Added ecdsa dependency for elliptic curve operations

Reviewed Changes

Copilot reviewed 5 out of 6 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
pyproject.toml Added ecdsa dependency and mypy overrides for the new package
kasa/transports/tpaptransport.py New TPAP transport implementation with SPAKE2+ handshake and secure channel
kasa/transports/init.py Added TpapTransport to module exports
kasa/deviceconfig.py Added Tpap enum value to DeviceEncryptionType
kasa/device_factory.py Added SMART.TPAP.HTTPS protocol mapping and fixed typo

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

Comment thread kasa/transports/tpaptransport.py Outdated
Comment thread kasa/transports/tpaptransport.py Outdated
Comment thread kasa/transports/tpaptransport.py Outdated
Comment thread kasa/transports/tpaptransport.py Fixed
Comment thread kasa/transports/tpaptransport.py Fixed
Comment thread kasa/transports/tpaptransport.py Fixed
Comment thread kasa/transports/tpaptransport.py Fixed
@codecov
Copy link
Copy Markdown

codecov Bot commented Oct 18, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 93.73%. Comparing base (76d9f68) to head (2640c28).

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #1592      +/-   ##
==========================================
+ Coverage   93.22%   93.73%   +0.50%     
==========================================
  Files         157      158       +1     
  Lines        9815    10608     +793     
  Branches     1003     1105     +102     
==========================================
+ Hits         9150     9943     +793     
  Misses        472      472              
  Partials      193      193              

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

Comment thread kasa/transports/tpaptransport.py Fixed
Comment thread kasa/transports/tpaptransport.py Fixed
Comment thread tests/transports/test_tpaptransport.py Fixed
Comment thread kasa/transports/tpaptransport.py Fixed
Comment thread kasa/transports/tpaptransport.py Fixed
Comment thread tests/transports/test_tpaptransport.py Fixed
@ZeliardM
Copy link
Copy Markdown
Contributor Author

@rytilahti Ok, I think this is a good first pass. I just need someone with a RV device to test it. The CodeQL Security flags, from my understanding, will always come up with md5 and sha1 hashing in the code, but it's required for the device communication, just like with the other transports.

@danieyal
Copy link
Copy Markdown

Sanitized discovery, logs, and TLS observations for the RV30 Max Plus(EU)-Firmware:1.3.0 Build 250909 Rel.135514 using TPAP. Personally identifying values are redacted. Hope this help.

  • Discovery advertises TPAP with tls=2 and PAKE suite [2]; HTTPS on 4433.
  • TLS1.3 fails immediately; TLS1.2 handshake succeeds with ECDHE-ECDSA-CHACHA20-POLY1305; no ALPN.
  • AES “/app” login on this device returns text/html “200 OK” (likely wrong endpoint for this family).
  • TPAP transport attempts hit TLS alert 40 initially; after constraining to TLS1.2, device still doesn’t accept our HTTP request format (suspect different login paths/headers/body or a pre-HTTP step).

uv run kasa --username '' --password '' --debug --host 192.168.68.63 discover config

DEBUG    Trying to connect with SmartProtocol                                                            discover.py:681
DEBUG    Using SmartDevice for SMART.TAPOROBOVAC                                                   device_factory.py:180
DEBUG    Initializing 192.168.68.63 of type <class 'kasa.smart.smartdevice.SmartDevice'>                   device.py:214
DEBUG    192.168.68.63 multi-request-batch-1-of-1 >>                                                smartprotocol.py:241
         '{"method":"multipleRequest","request_time_milis":1760838809450,"terminal_uuid":"qHsKLwgAV
         HlHIO3ZttV4Mw==","params":{"requests":[{"method":"component_nego"},{"method":"get_device_i
         nfo"},{"method":"get_connect_cloud_state"}]}}'
DEBUG    Posting to https://192.168.68.63:4433/                                                         httpclient.py:88
DEBUG    Device 192.168.68.63 received an os error, enabling sequential request delay: Cannot connect  httpclient.py:136
         to host 192.168.68.63:4433 ssl:<ssl.SSLContext object at 0x000001B6D6A4F7D0> [[SSL:
         SSLV3_ALERT_HANDSHAKE_FAILURE] sslv3 alert handshake failure (_ssl.c:1000)]
DEBUG    Device 192.168.68.63 got a connection error, will retry 3 times: ('Device connection       smartprotocol.py:145
         error: 192.168.68.63: Cannot connect to host 192.168.68.63:4433 ssl:<ssl.SSLContext object
         at 0x000001B6D6A4F7D0> [[SSL: SSLV3_ALERT_HANDSHAKE_FAILURE] sslv3 alert handshake failure
         (_ssl.c:1000)]', ClientConnectorSSLError(ConnectionKey(host='192.168.68.63', port=4433,
         is_ssl=True, ssl=<ssl.SSLContext object at 0x000001B6D6A4F7D0>, proxy=None,
         proxy_auth=None, proxy_headers_hash=None), SSLError(1, '[SSL:
         SSLV3_ALERT_HANDSHAKE_FAILURE] sslv3 alert handshake failure (_ssl.c:1000)')))
DEBUG    192.168.68.63 multi-request-batch-1-of-1 >>                                                smartprotocol.py:241
         '{"method":"multipleRequest","request_time_milis":1760838809471,"terminal_uuid":"qHsKLwgAV
         HlHIO3ZttV4Mw==","params":{"requests":[{"method":"component_nego"},{"method":"get_device_i
         nfo"},{"method":"get_connect_cloud_state"}]}}'
DEBUG    Device 192.168.68.63 waiting 0.25 seconds to send request                                      httpclient.py:81
DEBUG    Posting to https://192.168.68.63:4433/                                                         httpclient.py:88
DEBUG    192.168.68.63 multi-request-batch-1-of-1 >>                                                smartprotocol.py:241
         '{"method":"multipleRequest","request_time_milis":1760838809754,"terminal_uuid":"qHsKLwgAV
         HlHIO3ZttV4Mw==","params":{"requests":[{"method":"component_nego"},{"method":"get_device_i
         nfo"},{"method":"get_connect_cloud_state"}]}}'
DEBUG    Device 192.168.68.63 waiting 0.25 seconds to send request                                      httpclient.py:81
DEBUG    Posting to https://192.168.68.63:4433/                                                         httpclient.py:88
DEBUG    192.168.68.63 multi-request-batch-1-of-1 >>                                                smartprotocol.py:241
         '{"method":"multipleRequest","request_time_milis":1760838810228,"terminal_uuid":"qHsKLwgAV
         HlHIO3ZttV4Mw==","params":{"requests":[{"method":"component_nego"},{"method":"get_device_i
         nfo"},{"method":"get_connect_cloud_state"}]}}'
DEBUG    Device 192.168.68.63 waiting 0.25 seconds to send request                                      httpclient.py:81
DEBUG    Posting to https://192.168.68.63:4433/                                                         httpclient.py:88
DEBUG    Giving up on 192.168.68.63 after 3 retries                                                 smartprotocol.py:152
DEBUG    Unable to connect with SmartProtocol: ('Device connection error: 192.168.68.63: Cannot connect  discover.py:684
         to host 192.168.68.63:4433 ssl:<ssl.SSLContext object at 0x000001B6D6A4F7D0> [[SSL:
         SSLV3_ALERT_HANDSHAKE_FAILURE] sslv3 alert handshake failure (_ssl.c:1000)]',
         ClientConnectorSSLError(ConnectionKey(host='192.168.68.63', port=4433, is_ssl=True,
         ssl=<ssl.SSLContext object at 0x000001B6D6A4F7D0>, proxy=None, proxy_auth=None,
         proxy_headers_hash=None), SSLError(1, '[SSL: SSLV3_ALERT_HANDSHAKE_FAILURE] sslv3 alert
         handshake failure (_ssl.c:1000)')))
Attempt to connect to 192.168.68.63 with SmartProtocol + TpapTransport + SmartDevice + https failed
Unable to connect to 192.168.68.63

uv run kasa --username '' --password '' --debug --host 192.168.68.63 discover raw

Discovering device 192.168.68.63 for 10 seconds
DEBUG    [DISCOVERY] 192.168.68.63 >> {'system': {'get_sysinfo': {}}}                                    discover.py:326
DEBUG    Waiting a total of 10 seconds for responses...                                                  discover.py:587
{
  "discovery_response": {
    "result": {
      "device_id": "REDACTED_f47bb068b8aacda06dec54e",
      "owner": "REDACTED_96B05E0B002C122F61EC032",
      "device_type": "SMART.TAPOROBOVAC",
      "device_model": "RV30 Max Plus(EU)",
      "ip": "192.168.68.63",
      "mac": "BC-07-1D-00-00-00",
      "is_support_iot_cloud": true,
      "tpap": {
        "tls": 2,
        "dac": 1,
        "noc": 1,
        "pake": [
          2
        ],
        "port": 4433
      },
      "obd_src": "tplink",
      "protocol_version": 1,
      "factory_default": false,
      "mgt_encrypt_schm": {
        "is_support_https": true,
        "http_port": 4433,
        "encrypt_type": "TPAP",
        "lv": 2
      }
    },
    "error_code": 0
  },
  "meta": {
    "ip": "192.168.68.63",
    "port": 20002
  }
}
DEBUG    Using SmartDevice for SMART.TAPOROBOVAC                                                   device_factory.py:180
DEBUG    Finding protocol for 192.168.68.63                                                        device_factory.py:195
DEBUG    Finding protocol for DeviceFamily.SmartTapoRobovac                                        device_factory.py:198
DEBUG    Finding transport for SMART.TPAP.HTTPS                                                    device_factory.py:227
DEBUG    [DISCOVERY] 192.168.68.63 << {'error_code': 0,                                                  discover.py:924
          'result': {'device_id': 'REDACTED_f47bb068b8aacda06dec54e',
                     'device_model': 'RV30 Max Plus(EU)',
                     'device_type': 'SMART.TAPOROBOVAC',
                     'factory_default': False,
                     'ip': '192.168.68.63',
                     'is_support_iot_cloud': True,
                     'mac': 'BC-07-1D-00-00-00',
                     'mgt_encrypt_schm': {'encrypt_type': 'TPAP',
                                          'http_port': 4433,
                                          'is_support_https': True,
                                          'lv': 2},
                     'obd_src': 'tplink',
                     'owner': 'REDACTED_96B05E0B002C122F61EC032',
                     'protocol_version': 1,
                     'tpap': {'dac': 1, 'noc': 1, 'pake': [2], 'port': 4433, 'tls': 2}}}
DEBUG    Initializing 192.168.68.63 of type <class 'kasa.smart.smartdevice.SmartDevice'>                   device.py:214

SSL:

root@pve:~# openssl s_client -connect 192.168.68.63:4433 -tls1_3 -alpn h2
Connecting to 192.168.68.63
CONNECTED(00000003)
40D767A1D0750000:error:0A000410:SSL routines:ssl3_read_bytes:ssl/tls alert handshake failure:../ssl/record/rec_layer_s3.c:916:SSL alert number 40
---
no peer certificate available
---
No client certificate CA names sent
Negotiated TLS1.3 group: <NULL>
---
SSL handshake has read 7 bytes and written 1469 bytes
Verification: OK
---
New, (NONE), Cipher is (NONE)
Protocol: TLSv1.3
This TLS version forbids renegotiation.
Compression: NONE
Expansion: NONE
No ALPN negotiated
Early data was not sent
Verify return code: 0 (ok)
---
root@pve:~# openssl s_client -connect 192.168.68.63:4433 -tls1_2 -alpn h2
Connecting to 192.168.68.63
CONNECTED(00000003)
Can't use SSL_get_servername
depth=1 CN=SMART.TAPOROBOVAC CA, O=TP-LINK SYSTEMS INC., L=Irvine, ST=California, C=US
verify error:num=20:unable to get local issuer certificate
verify return:1
depth=0 CN=RV30 Max Plus(EU), OU=SMART.TAPOHUB
verify return:1
---
Certificate chain
 0 s:CN=RV30 Max Plus(EU), OU=SMART.TAPOHUB
   i:CN=SMART.TAPOROBOVAC CA, O=TP-LINK SYSTEMS INC., L=Irvine, ST=California, C=US
   a:PKEY: EC, (prime256v1); sigalg: ecdsa-with-SHA256
   v:NotBefore: Sep 19 20:43:33 2025 GMT; NotAfter: Sep 19 20:43:33 2030 GMT
 1 s:CN=SMART.TAPOROBOVAC CA, O=TP-LINK SYSTEMS INC., L=Irvine, ST=California, C=US
   i:CN=TP-LINK SYSTEMS DEVICE ROOT CA, O=TP-LINK SYSTEMS INC., L=Irvine, ST=California, C=US
   a:PKEY: EC, (prime256v1); sigalg: ecdsa-with-SHA256
   v:NotBefore: Nov 22 04:07:54 2024 GMT; NotAfter: Nov 20 04:07:54 2034 GMT
---
Server certificate
-----BEGIN CERTIFICATE-----
<REDACTED>
-----END CERTIFICATE-----
subject=CN=RV30 Max Plus(EU), OU=SMART.TAPOHUB
issuer=CN=SMART.TAPOROBOVAC CA, O=TP-LINK SYSTEMS INC., L=Irvine, ST=California, C=US
---
No client certificate CA names sent
Peer signing digest: SHA256
Peer signature type: ecdsa_secp256r1_sha256
Peer Temp Key: ECDH, secp384r1, 384 bits
---
SSL handshake has read 1476 bytes and written 350 bytes
Verification error: unable to get local issuer certificate
---
New, TLSv1.2, Cipher is ECDHE-ECDSA-CHACHA20-POLY1305
Protocol: TLSv1.2
Server public key is 256 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
    Protocol  : TLSv1.2
    Cipher    : ECDHE-ECDSA-CHACHA20-POLY1305
    Session-ID: <REDACTED>
    Session-ID-ctx:
    Master-Key: <REDACTED>
    PSK identity: None
    PSK identity hint: None
    SRP username: None
    Start Time: 1760847175
    Timeout   : 7200 (sec)
    Verify return code: 20 (unable to get local issuer certificate)
    Extended master secret: yes
---

Wireshark:

Frame 221: Packet, 234 bytes on wire (1872 bits), 234 bytes captured (1872 bits) on interface \Device\NPF_{5B7CFEBB-96D4-4EA5-A9EB-AEB90614BE7A}, id 0
    Section number: 1
    Interface id: 0 (\Device\NPF_{5B7CFEBB-96D4-4EA5-A9EB-AEB90614BE7A})
        Interface name: \Device\NPF_{5B7CFEBB-96D4-4EA5-A9EB-AEB90614BE7A}
        Interface description: Ethernet
    Encapsulation type: Ethernet (1)
    Arrival Time: Oct 19, 2025 11:35:25.271976000 Malay Peninsula Standard Time
    UTC Arrival Time: Oct 19, 2025 03:35:25.271976000 UTC
    Epoch Arrival Time: 1760844925.271976000
    [Time shift for this packet: 0.000000000 seconds]
    [Time delta from previous captured frame: 1.073000 milliseconds]
    [Time delta from previous displayed frame: 1.073000 milliseconds]
    [Time since reference or first frame: 3 minutes, 2.003639000 seconds]
    Frame Number: 221
    Frame Length: 234 bytes (1872 bits)
    Capture Length: 234 bytes (1872 bits)
    [Frame is marked: False]
    [Frame is ignored: False]
    [Protocols in frame: eth:ethertype:ip:tcp:tls]
    Character encoding: ASCII (0)
    [Coloring Rule Name: TCP]
    [Coloring Rule String: tcp]
Ethernet II, Src: CompalInform_02:ed:ec (38:a7:46:02:ed:ec), Dst: TPLink_77:0e:7d (bc:07:1d:77:0e:7d)
    Destination: TPLink_77:0e:7d (bc:07:1d:77:0e:7d)
        .... ..0. .... .... .... .... = LG bit: Globally unique address (factory default)
        .... ...0 .... .... .... .... = IG bit: Individual address (unicast)
    Source: CompalInform_02:ed:ec (38:a7:46:02:ed:ec)
        .... ..0. .... .... .... .... = LG bit: Globally unique address (factory default)
        .... ...0 .... .... .... .... = IG bit: Individual address (unicast)
    Type: IPv4 (0x0800)
    [Stream index: 0]
Internet Protocol Version 4, Src: 192.168.68.91, Dst: 192.168.68.63
    0100 .... = Version: 4
    .... 0101 = Header Length: 20 bytes (5)
    Differentiated Services Field: 0x00 (DSCP: CS0, ECN: Not-ECT)
        0000 00.. = Differentiated Services Codepoint: Default (0)
        .... ..00 = Explicit Congestion Notification: Not ECN-Capable Transport (0)
    Total Length: 220
    Identification: 0x2625 (9765)
    010. .... = Flags: 0x2, Don't fragment
        0... .... = Reserved bit: Not set
        .1.. .... = Don't fragment: Set
        ..0. .... = More fragments: Not set
    ...0 0000 0000 0000 = Fragment Offset: 0
    Time to Live: 128
    Protocol: TCP (6)
    Header Checksum: 0x0000 [validation disabled]
    [Header checksum status: Unverified]
    Source Address: 192.168.68.91
    Destination Address: 192.168.68.63
    [Stream index: 0]
Transmission Control Protocol, Src Port: 46387, Dst Port: 4433, Seq: 1, Ack: 1, Len: 180
    Source Port: 46387
    Destination Port: 4433
    [Stream index: 5]
    [Stream Packet Number: 4]
    [Conversation completeness: Incomplete, DATA (15)]
        ..0. .... = RST: Absent
        ...0 .... = FIN: Absent
        .... 1... = Data: Present
        .... .1.. = ACK: Present
        .... ..1. = SYN-ACK: Present
        .... ...1 = SYN: Present
        [Completeness Flags: ··DASS]
    [TCP Segment Len: 180]
    Sequence Number: 1    (relative sequence number)
    Sequence Number (raw): 2124410112
    [Next Sequence Number: 181    (relative sequence number)]
    Acknowledgment Number: 1    (relative ack number)
    Acknowledgment number (raw): 1100174539
    0101 .... = Header Length: 20 bytes (5)
    Flags: 0x018 (PSH, ACK)
        000. .... .... = Reserved: Not set
        ...0 .... .... = Accurate ECN: Not set
        .... 0... .... = Congestion Window Reduced: Not set
        .... .0.. .... = ECN-Echo: Not set
        .... ..0. .... = Urgent: Not set
        .... ...1 .... = Acknowledgment: Set
        .... .... 1... = Push: Set
        .... .... .0.. = Reset: Not set
        .... .... ..0. = Syn: Not set
        .... .... ...0 = Fin: Not set
        [TCP Flags: ·······AP···]
    Window: 255
    [Calculated window size: 65280]
    [Window size scaling factor: 256]
    Checksum: 0x0aba [unverified]
    [Checksum Status: Unverified]
    Urgent Pointer: 0
    [Timestamps]
        [Time since first frame in this TCP stream: 8.459000 milliseconds]
        [Time since previous frame in this TCP stream: 1.073000 milliseconds]
    [SEQ/ACK analysis]
        [iRTT: 7.386000 milliseconds]
        [Bytes in flight: 180]
        [Bytes sent since last PSH flag: 180]
    [Client Contiguous Streams: 1]
    [Server Contiguous Streams: 1]
    TCP payload (180 bytes)
Transport Layer Security
    [Stream index: 2]
    TLSv1.2 Record Layer: Handshake Protocol: Client Hello
        Content Type: Handshake (22)
        Version: TLS 1.0 (0x0301)
        Length: 175
        Handshake Protocol: Client Hello
            Handshake Type: Client Hello (1)
            Length: 171
            Version: TLS 1.2 (0x0303)
            Random: 3cbe0eae6e3be4e450edfdf4d611302985ecb513dc5d147633b7e16465777bf3
                GMT Unix Time: Apr 18, 2002 08:09:18.000000000 Malay Peninsula Standard Time
                Random Bytes: 6e3be4e450edfdf4d611302985ecb513dc5d147633b7e16465777bf3
            Session ID Length: 32
            Session ID: 1b04dc59c6d238c56aff3701dc937ef2e4a14eed2c195aa26d2a880c4b9c8af1
            Cipher Suites Length: 16
            Cipher Suites (8 suites)
                Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 (0xc02b)
                Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 (0xc02c)
                Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (0xc02f)
                Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (0xc030)
                Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA (0xc009)
                Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA (0xc00a)
                Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (0xc013)
                Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (0xc014)
            Compression Methods Length: 1
            Compression Methods (1 method)
                Compression Method: null (0)
            Extensions Length: 82
            Extension: renegotiation_info (len=1)
                Type: renegotiation_info (65281)
                Length: 1
                Renegotiation Info extension
                    Renegotiation info extension length: 0
            Extension: extended_master_secret (len=0)
                Type: extended_master_secret (23)
                Length: 0
            Extension: session_ticket (len=0)
                Type: session_ticket (35)
                Length: 0
                Session Ticket: <MISSING>
            Extension: signature_algorithms (len=20)
                Type: signature_algorithms (13)
                Length: 20
                Signature Hash Algorithms Length: 18
                Signature Hash Algorithms (9 algorithms)
                    Signature Algorithm: ecdsa_secp256r1_sha256 (0x0403)
                        Signature Hash Algorithm Hash: SHA256 (4)
                        Signature Hash Algorithm Signature: ECDSA (3)
                    Signature Algorithm: rsa_pss_rsae_sha256 (0x0804)
                        Signature Hash Algorithm Hash: Unknown (8)
                        Signature Hash Algorithm Signature: Unknown (4)
                    Signature Algorithm: rsa_pkcs1_sha256 (0x0401)
                        Signature Hash Algorithm Hash: SHA256 (4)
                        Signature Hash Algorithm Signature: RSA (1)
                    Signature Algorithm: ecdsa_secp384r1_sha384 (0x0503)
                        Signature Hash Algorithm Hash: SHA384 (5)
                        Signature Hash Algorithm Signature: ECDSA (3)
                    Signature Algorithm: rsa_pss_rsae_sha384 (0x0805)
                        Signature Hash Algorithm Hash: Unknown (8)
                        Signature Hash Algorithm Signature: Unknown (5)
                    Signature Algorithm: rsa_pkcs1_sha384 (0x0501)
                        Signature Hash Algorithm Hash: SHA384 (5)
                        Signature Hash Algorithm Signature: RSA (1)
                    Signature Algorithm: rsa_pss_rsae_sha512 (0x0806)
                        Signature Hash Algorithm Hash: Unknown (8)
                        Signature Hash Algorithm Signature: Unknown (6)
                    Signature Algorithm: rsa_pkcs1_sha512 (0x0601)
                        Signature Hash Algorithm Hash: SHA512 (6)
                        Signature Hash Algorithm Signature: RSA (1)
                    Signature Algorithm: rsa_pkcs1_sha1 (0x0201)
                        Signature Hash Algorithm Hash: SHA1 (2)
                        Signature Hash Algorithm Signature: RSA (1)
            Extension: status_request (len=5)
                Type: status_request (5)
                Length: 5
                Certificate Status Type: OCSP (1)
                Responder ID list Length: 0
                Request Extensions Length: 0
            Extension: application_layer_protocol_negotiation (len=14)
                Type: application_layer_protocol_negotiation (16)
                Length: 14
                ALPN Extension Length: 12
                ALPN Protocol
                    ALPN string length: 2
                    ALPN Next Protocol: h2
                    ALPN string length: 8
                    ALPN Next Protocol: http/1.1
            Extension: ec_point_formats (len=2)
                Type: ec_point_formats (11)
                Length: 2
                EC point formats Length: 1
                Elliptic curves point formats (1)
                    EC point format: uncompressed (0)
            Extension: supported_groups (len=8)
                Type: supported_groups (10)
                Length: 8
                Supported Groups List Length: 6
                Supported Groups (3 groups)
                    Supported Group: x25519 (0x001d)
                    Supported Group: secp256r1 (0x0017)
                    Supported Group: secp384r1 (0x0018)

Frame 224: Packet, 63 bytes on wire (504 bits), 63 bytes captured (504 bits) on interface \Device\NPF_{5B7CFEBB-96D4-4EA5-A9EB-AEB90614BE7A}, id 0
    Section number: 1
    Interface id: 0 (\Device\NPF_{5B7CFEBB-96D4-4EA5-A9EB-AEB90614BE7A})
        Interface name: \Device\NPF_{5B7CFEBB-96D4-4EA5-A9EB-AEB90614BE7A}
        Interface description: Ethernet
    Encapsulation type: Ethernet (1)
    Arrival Time: Oct 19, 2025 11:35:25.281849000 Malay Peninsula Standard Time
    UTC Arrival Time: Oct 19, 2025 03:35:25.281849000 UTC
    Epoch Arrival Time: 1760844925.281849000
    [Time shift for this packet: 0.000000000 seconds]
    [Time delta from previous captured frame: 4.004000 milliseconds]
    [Time delta from previous displayed frame: 4.004000 milliseconds]
    [Time since reference or first frame: 3 minutes, 2.013512000 seconds]
    Frame Number: 224
    Frame Length: 63 bytes (504 bits)
    Capture Length: 63 bytes (504 bits)
    [Frame is marked: False]
    [Frame is ignored: False]
    [Protocols in frame: eth:ethertype:ip:tcp:tls]
    Character encoding: ASCII (0)
    [Coloring Rule Name: TCP]
    [Coloring Rule String: tcp]
Ethernet II, Src: TPLink_77:0e:7d (bc:07:1d:77:0e:7d), Dst: CompalInform_02:ed:ec (38:a7:46:02:ed:ec)
    Destination: CompalInform_02:ed:ec (38:a7:46:02:ed:ec)
        .... ..0. .... .... .... .... = LG bit: Globally unique address (factory default)
        .... ...0 .... .... .... .... = IG bit: Individual address (unicast)
    Source: TPLink_77:0e:7d (bc:07:1d:77:0e:7d)
        .... ..0. .... .... .... .... = LG bit: Globally unique address (factory default)
        .... ...0 .... .... .... .... = IG bit: Individual address (unicast)
    Type: IPv4 (0x0800)
    [Stream index: 0]
Internet Protocol Version 4, Src: 192.168.68.63, Dst: 192.168.68.91
    0100 .... = Version: 4
    .... 0101 = Header Length: 20 bytes (5)
    Differentiated Services Field: 0x00 (DSCP: CS0, ECN: Not-ECT)
        0000 00.. = Differentiated Services Codepoint: Default (0)
        .... ..00 = Explicit Congestion Notification: Not ECN-Capable Transport (0)
    Total Length: 49
    Identification: 0x2213 (8723)
    010. .... = Flags: 0x2, Don't fragment
        0... .... = Reserved bit: Not set
        .1.. .... = Don't fragment: Set
        ..0. .... = More fragments: Not set
    ...0 0000 0000 0000 = Fragment Offset: 0
    Time to Live: 64
    Protocol: TCP (6)
    Header Checksum: 0x0ec9 [validation disabled]
    [Header checksum status: Unverified]
    Source Address: 192.168.68.63
    Destination Address: 192.168.68.91
    [Stream index: 0]
Transmission Control Protocol, Src Port: 4433, Dst Port: 46386, Seq: 1426, Ack: 181, Len: 9
    Source Port: 4433
    Destination Port: 46386
    [Stream index: 4]
    [Stream Packet Number: 12]
    [Conversation completeness: Incomplete, DATA (15)]
        ..0. .... = RST: Absent
        ...0 .... = FIN: Absent
        .... 1... = Data: Present
        .... .1.. = ACK: Present
        .... ..1. = SYN-ACK: Present
        .... ...1 = SYN: Present
        [Completeness Flags: ··DASS]
    [TCP Segment Len: 9]
    Sequence Number: 1426    (relative sequence number)
    Sequence Number (raw): 1085180748
    [Next Sequence Number: 1435    (relative sequence number)]
    Acknowledgment Number: 181    (relative ack number)
    Acknowledgment number (raw): 241256951
    0101 .... = Header Length: 20 bytes (5)
    Flags: 0x018 (PSH, ACK)
        000. .... .... = Reserved: Not set
        ...0 .... .... = Accurate ECN: Not set
        .... 0... .... = Congestion Window Reduced: Not set
        .... .0.. .... = ECN-Echo: Not set
        .... ..0. .... = Urgent: Not set
        .... ...1 .... = Acknowledgment: Set
        .... .... 1... = Push: Set
        .... .... .0.. = Reset: Not set
        .... .... ..0. = Syn: Not set
        .... .... ...0 = Fin: Not set
        [TCP Flags: ·······AP···]
    Window: 1892
    [Calculated window size: 30272]
    [Window size scaling factor: 16]
    Checksum: 0x968c [unverified]
    [Checksum Status: Unverified]
    Urgent Pointer: 0
    [Timestamps]
        [Time since first frame in this TCP stream: 216.772000 milliseconds]
        [Time since previous frame in this TCP stream: 4.204000 milliseconds]
    [SEQ/ACK analysis]
        [iRTT: 11.499000 milliseconds]
        [Bytes in flight: 9]
        [Bytes sent since last PSH flag: 9]
    [Client Contiguous Streams: 1]
    [Server Contiguous Streams: 1]
    TCP payload (9 bytes)
Transport Layer Security
    [Stream index: 1]
    TLSv1.2 Record Layer: Handshake Protocol: Server Hello Done
        Content Type: Handshake (22)
        Version: TLS 1.2 (0x0303)
        Length: 4
        Handshake Protocol: Server Hello Done
            Handshake Type: Server Hello Done (14)
            Length: 0
Frame 225: Packet, 212 bytes on wire (1696 bits), 212 bytes captured (1696 bits) on interface \Device\NPF_{5B7CFEBB-96D4-4EA5-A9EB-AEB90614BE7A}, id 0
    Section number: 1
    Interface id: 0 (\Device\NPF_{5B7CFEBB-96D4-4EA5-A9EB-AEB90614BE7A})
        Interface name: \Device\NPF_{5B7CFEBB-96D4-4EA5-A9EB-AEB90614BE7A}
        Interface description: Ethernet
    Encapsulation type: Ethernet (1)
    Arrival Time: Oct 19, 2025 11:35:25.284112000 Malay Peninsula Standard Time
    UTC Arrival Time: Oct 19, 2025 03:35:25.284112000 UTC
    Epoch Arrival Time: 1760844925.284112000
    [Time shift for this packet: 0.000000000 seconds]
    [Time delta from previous captured frame: 2.263000 milliseconds]
    [Time delta from previous displayed frame: 2.263000 milliseconds]
    [Time since reference or first frame: 3 minutes, 2.015775000 seconds]
    Frame Number: 225
    Frame Length: 212 bytes (1696 bits)
    Capture Length: 212 bytes (1696 bits)
    [Frame is marked: False]
    [Frame is ignored: False]
    [Protocols in frame: eth:ethertype:ip:tcp:tls]
    Character encoding: ASCII (0)
    [Coloring Rule Name: TCP]
    [Coloring Rule String: tcp]
Ethernet II, Src: CompalInform_02:ed:ec (38:a7:46:02:ed:ec), Dst: TPLink_77:0e:7d (bc:07:1d:77:0e:7d)
    Destination: TPLink_77:0e:7d (bc:07:1d:77:0e:7d)
        .... ..0. .... .... .... .... = LG bit: Globally unique address (factory default)
        .... ...0 .... .... .... .... = IG bit: Individual address (unicast)
    Source: CompalInform_02:ed:ec (38:a7:46:02:ed:ec)
        .... ..0. .... .... .... .... = LG bit: Globally unique address (factory default)
        .... ...0 .... .... .... .... = IG bit: Individual address (unicast)
    Type: IPv4 (0x0800)
    [Stream index: 0]
Internet Protocol Version 4, Src: 192.168.68.91, Dst: 192.168.68.63
    0100 .... = Version: 4
    .... 0101 = Header Length: 20 bytes (5)
    Differentiated Services Field: 0x00 (DSCP: CS0, ECN: Not-ECT)
        0000 00.. = Differentiated Services Codepoint: Default (0)
        .... ..00 = Explicit Congestion Notification: Not ECN-Capable Transport (0)
    Total Length: 198
    Identification: 0x2627 (9767)
    010. .... = Flags: 0x2, Don't fragment
        0... .... = Reserved bit: Not set
        .1.. .... = Don't fragment: Set
        ..0. .... = More fragments: Not set
    ...0 0000 0000 0000 = Fragment Offset: 0
    Time to Live: 128
    Protocol: TCP (6)
    Header Checksum: 0x0000 [validation disabled]
    [Header checksum status: Unverified]
    Source Address: 192.168.68.91
    Destination Address: 192.168.68.63
    [Stream index: 0]
Transmission Control Protocol, Src Port: 46386, Dst Port: 4433, Seq: 181, Ack: 1435, Len: 158
    Source Port: 46386
    Destination Port: 4433
    [Stream index: 4]
    [Stream Packet Number: 13]
    [Conversation completeness: Incomplete, DATA (15)]
        ..0. .... = RST: Absent
        ...0 .... = FIN: Absent
        .... 1... = Data: Present
        .... .1.. = ACK: Present
        .... ..1. = SYN-ACK: Present
        .... ...1 = SYN: Present
        [Completeness Flags: ··DASS]
    [TCP Segment Len: 158]
    Sequence Number: 181    (relative sequence number)
    Sequence Number (raw): 241256951
    [Next Sequence Number: 339    (relative sequence number)]
    Acknowledgment Number: 1435    (relative ack number)
    Acknowledgment number (raw): 1085180757
    0101 .... = Header Length: 20 bytes (5)
    Flags: 0x018 (PSH, ACK)
        000. .... .... = Reserved: Not set
        ...0 .... .... = Accurate ECN: Not set
        .... 0... .... = Congestion Window Reduced: Not set
        .... .0.. .... = ECN-Echo: Not set
        .... ..0. .... = Urgent: Not set
        .... ...1 .... = Acknowledgment: Set
        .... .... 1... = Push: Set
        .... .... .0.. = Reset: Not set
        .... .... ..0. = Syn: Not set
        .... .... ...0 = Fin: Not set
        [TCP Flags: ·······AP···]
    Window: 250
    [Calculated window size: 64000]
    [Window size scaling factor: 256]
    Checksum: 0x0aa4 [unverified]
    [Checksum Status: Unverified]
    Urgent Pointer: 0
    [Timestamps]
        [Time since first frame in this TCP stream: 219.035000 milliseconds]
        [Time since previous frame in this TCP stream: 2.263000 milliseconds]
    [SEQ/ACK analysis]
        [This is an ACK to the segment in frame: 224]
        [The RTT to ACK the segment was: 2.263000 milliseconds]
        [iRTT: 11.499000 milliseconds]
        [Bytes in flight: 158]
        [Bytes sent since last PSH flag: 158]
    [Client Contiguous Streams: 1]
    [Server Contiguous Streams: 1]
    TCP payload (158 bytes)
Transport Layer Security
    [Stream index: 1]
    TLSv1.2 Record Layer: Handshake Protocol: Client Key Exchange
        Content Type: Handshake (22)
        Version: TLS 1.2 (0x0303)
        Length: 102
        Handshake Protocol: Client Key Exchange
            Handshake Type: Client Key Exchange (16)
            Length: 98
            EC Diffie-Hellman Client Params
                Pubkey Length: 97
                Pubkey: 0495574c7aa82261d993d4498805cc1090590eb703e0f85f77a68b4ca4f6dc148b8d401ff25e0359f99a06473e8fa771956ecbcf6512de82961734bc2584546b0ffc4ebcd2d787aa39402881fb51297e8dab3dc0f887e863494fa8b8fba336c0c6
    TLSv1.2 Record Layer: Change Cipher Spec Protocol: Change Cipher Spec
        Content Type: Change Cipher Spec (20)
        Version: TLS 1.2 (0x0303)
        Length: 1
        Change Cipher Spec Message
    TLSv1.2 Record Layer: Handshake Protocol: Encrypted Handshake Message
        Content Type: Handshake (22)
        Version: TLS 1.2 (0x0303)
        Length: 40
        Handshake Protocol: Encrypted Handshake Message

@ZeliardM
Copy link
Copy Markdown
Contributor Author

@danieyal Pull the latest commit and try giving it a shot again.

@danieyal
Copy link
Copy Markdown

unfortunately, still the same error.

DEBUG    Trying to connect with SmartProtocol                                                             discover.py:681
DEBUG    Using SmartDevice for SMART.TAPOROBOVAC                                                    device_factory.py:180
DEBUG    Initializing 192.168.68.63 of type <class 'kasa.smart.smartdevice.SmartDevice'>                    device.py:214
DEBUG    192.168.68.63 multi-request-batch-1-of-1 >>                                                 smartprotocol.py:241
         '{"method":"multipleRequest","request_time_milis":1760887822371,"terminal_uuid":"mRY0IrNONh
         G5kZRhIPcYrg==","params":{"requests":[{"method":"component_nego"},{"method":"get_device_inf
         o"},{"method":"get_connect_cloud_state"}]}}'
DEBUG    Posting to https://192.168.68.63:4433/                                                          httpclient.py:88
DEBUG    Device 192.168.68.63 received an os error, enabling sequential request delay: Cannot connect   httpclient.py:157
         to host 192.168.68.63:4433 ssl:<ssl.SSLContext object at 0x0000025A3D7D7550> [[SSL:
         SSLV3_ALERT_HANDSHAKE_FAILURE] sslv3 alert handshake failure (_ssl.c:1000)]
DEBUG    Device 192.168.68.63 got a connection error, will retry 3 times: ('Device connection error: smartprotocol.py:145
         192.168.68.63: Cannot connect to host 192.168.68.63:4433 ssl:<ssl.SSLContext object at
         0x0000025A3D7D7550> [[SSL: SSLV3_ALERT_HANDSHAKE_FAILURE] sslv3 alert handshake failure
         (_ssl.c:1000)]', ClientConnectorSSLError(ConnectionKey(host='192.168.68.63', port=4433,
         is_ssl=True, ssl=<ssl.SSLContext object at 0x0000025A3D7D7550>, proxy=None,
         proxy_auth=None, proxy_headers_hash=None), SSLError(1, '[SSL:
         SSLV3_ALERT_HANDSHAKE_FAILURE] sslv3 alert handshake failure (_ssl.c:1000)')))
DEBUG    192.168.68.63 multi-request-batch-1-of-1 >>                                                 smartprotocol.py:241
         '{"method":"multipleRequest","request_time_milis":1760887822496,"terminal_uuid":"mRY0IrNONh
         G5kZRhIPcYrg==","params":{"requests":[{"method":"component_nego"},{"method":"get_device_inf
         o"},{"method":"get_connect_cloud_state"}]}}'
DEBUG    Device 192.168.68.63 waiting 0.25 seconds to send request                                       httpclient.py:81
DEBUG    Posting to https://192.168.68.63:4433/                                                          httpclient.py:88
DEBUG    192.168.68.63 multi-request-batch-1-of-1 >>                                                 smartprotocol.py:241
         '{"method":"multipleRequest","request_time_milis":1760887823014,"terminal_uuid":"mRY0IrNONh
         G5kZRhIPcYrg==","params":{"requests":[{"method":"component_nego"},{"method":"get_device_inf
         o"},{"method":"get_connect_cloud_state"}]}}'
DEBUG    Device 192.168.68.63 waiting 0.25 seconds to send request                                       httpclient.py:81
DEBUG    Posting to https://192.168.68.63:4433/                                                          httpclient.py:88
DEBUG    192.168.68.63 multi-request-batch-1-of-1 >>                                                 smartprotocol.py:241
         '{"method":"multipleRequest","request_time_milis":1760887823298,"terminal_uuid":"mRY0IrNONh
         G5kZRhIPcYrg==","params":{"requests":[{"method":"component_nego"},{"method":"get_device_inf
         o"},{"method":"get_connect_cloud_state"}]}}'
DEBUG    Device 192.168.68.63 waiting 0.25 seconds to send request                                       httpclient.py:81
DEBUG    Posting to https://192.168.68.63:4433/                                                          httpclient.py:88
DEBUG    Giving up on 192.168.68.63 after 3 retries                                                  smartprotocol.py:152
DEBUG    Unable to connect with SmartProtocol: ('Device connection error: 192.168.68.63: Cannot connect   discover.py:684
         to host 192.168.68.63:4433 ssl:<ssl.SSLContext object at 0x0000025A3D7D7550> [[SSL:
         SSLV3_ALERT_HANDSHAKE_FAILURE] sslv3 alert handshake failure (_ssl.c:1000)]',
         ClientConnectorSSLError(ConnectionKey(host='192.168.68.63', port=4433, is_ssl=True,
         ssl=<ssl.SSLContext object at 0x0000025A3D7D7550>, proxy=None, proxy_auth=None,
         proxy_headers_hash=None), SSLError(1, '[SSL: SSLV3_ALERT_HANDSHAKE_FAILURE] sslv3 alert
         handshake failure (_ssl.c:1000)')))
Attempt to connect to 192.168.68.63 with SmartProtocol + TpapTransport + SmartDevice + https failed
Unable to connect to 192.168.68.63

@danieyal
Copy link
Copy Markdown

I think i have got the TLS working now but stuck on the authentication now.

  • TLS 1.2, cipher ECDHE-ECDSA-AES-256-GCM-SHA384
  • No SNI (IP direct)
  • ALPN offered: h2, http/1.1
  • Server certificate chain: TP-LINK SYSTEMS DEVICE ROOT CA → SMART.TAPOROBOVAC CA → device leaf (CN RV30 Max Plus(EU), OU SMART.TAPOHUB)
  • OCSP AIA: http://ocsp-tss.tplinkcloud.com
  • No CertificateRequest observed → not mTLS
CIPHERS = ":".join(
        [
            "ECDHE-ECDSA-AES256-GCM-SHA384",
            "ECDHE-ECDSA-CHACHA20-POLY1305",
            "ECDHE-ECDSA-AES128-GCM-SHA256",
            "AES256-GCM-SHA384",
            "AES256-SHA256",
            "AES128-GCM-SHA256",
            "AES128-SHA256",
            "AES256-SHA",
        ]
    )

The device is returning a JSON response with 'error_code': -2402 along with authentication failure details like failedAttempts and remainAttempts. The device is rejecting the authentication attempt at the pake_register stage returning error code -2402. My theory is the device is actively rejecting our credentials/authentication attempt before we even get to the SPAKE2+ cryptographic exchange. This suggests the device needs something we're not providing, most likely DAC support.

DEBUG    TPAP register(empty) response: status=200, data_type=dict, data_len=3,
         data={'error_info': {'lockedMinute': 0, 'failedAttempts': 4, 'remainAttempts': 11},
         'result': {'sub_method': 'pake_register'}, 'error_code': -2402}

@ZeliardM
Copy link
Copy Markdown
Contributor Author

I have been working on this today without much movement, still trying to figure out the authentication pieces. Looks like I will have to implement NOC but having issues getting the information and URLs for the certificate registration with the Tapo cloud. There is an API rate limit which causes problems as well. So, I'm still working on this, but nothing yet.

@ZeliardM
Copy link
Copy Markdown
Contributor Author

@danieyal Are you able to use the Tapo app on your computer with Wireshark? I'm trying to reverse engineer the url for the certificates and the requests are not working. I am looking for something to do with:
nbu.cvm-server-v2

This is what points to where to apply for the certificates, but I can't get the communication to work correctly on my end. I'm trying to get the signature correct with the app to the cloud so I can pull the url, but I can't get that either. Until I have the URL to work with the serviceId: nbu.cvm-server-v2, then I can't get the library to handle the noc certificates.

@ZeliardM
Copy link
Copy Markdown
Contributor Author

@danieyal try pulling again and let me know. I updated the ciphers like you found and I also corrected the last error you posted, it went to the stok field in the register parameters, it needed to be sessionId instead. Let me know what you get with this.

@danieyal
Copy link
Copy Markdown

danieyal commented Oct 22, 2025

@ZeliardM Thanks for the updates, and to clarify my side:

  • I can’t use Wireshark alone due to TLS/Cert pinning; I’m using Frida. I’ve posted sanitized findings (TLS, DS wrapper, discovery, logs) in my report and can share more privately if needed.
  • RV30 appears to commission via cloud and only then uses local DS:
    • Local DS: POST https://<ip>:4433/stok=<REDACTED>/ds with headers Accept: application/octet-stream, Connection: keep-alive, body wrapper:
      {"inputParams":{"requestData":{<SMART JSON>}},"serviceId":"passthrough"}
    • Plain JSON to /ds returns {"error_code": -2402} on this firmware, implying DS expects the SPAKE-protected binary frames tied to the cloud-issued session.
  • TLS (local): TLS 1.2 only, ECDHE‑ECDSA (AES‑256‑GCM/CHACHA20), no SNI, ALPN offered h2/http/1.1, device ECDSA leaf via SMART.TAPOROBOVAC CA.

Re: NOC/nbu.cvm-server-v2:

  • I haven’t seen any local pake_register at all; the app drives commissioning over cloud (…/v1/things/<thing-id>/services-sync) and then hits local DS.
  • I’ll keep trying to capture the exact services-sync request/response for serviceId: nbu.cvm-server-v2 with Frida (and sanitize), but so far, I have not seen it at all. If someone already has the signed payload/URL shape, that would unblock wiring NOC into the library much faster.
  • I cannot directly see DAC/NOC (Matter) details locally since those are invoked against the cloud endpoints.

I also pulled the latest branch:

  • Cipher updates look good.
  • Current failure is still -2402 at register.

Frida Log for device commissioning, I reset my device to see if pake_register appear at all, but it seems like nope, it just communicates over cloud regardless, other Tapo devices (plug, bulb, hub, camera) that I own still communicates locally (so probably not local network issue), I can 'see' the local endpoint for other devices but only vacuum just straight to cloud endpoint. Sorry, if it takes too long, setting up Frida took longer than expected.

frida -U -f com.tplink.iot -l .\unpin.js -l .\okhttp_log.js -l .\mac_sniff.js -l .\json_watch.js -l .\native_sock_hook.js -l .\hook_socket_write.js -l .\hook_socket_java.js -l .\okhttp_resp_tap.js
     ____
    / _  |   Frida 17.4.0 - A world-class dynamic instrumentation toolkit
   | (_| |
    > _  |   Commands:
   /_/ |_|       help      -> Displays the help system
   . . . .       object?   -> Display information about 'object'
   . . . .       exit/quit -> Exit
   . . . .
   . . . .   More info at https://frida.re/docs/home/
Waiting for USB device to appear...
   . . . .
   . . . .   Connected to Redmi Note 5 (id=adb-21f3ca07-4K2z0L._adb-tls-connect._tcp)
Spawned `com.tplink.iot`. Resuming main thread!

---- OKHTTP REQUEST ----
URL: https://n-aps1-wap.i.tplinkcloud.com/api/v2/account/checkPassword
Method: POST
Headers:
signature-required: true
token-required: false

Body:
{"appType":"TP-Link_Tapo_Android","cloudPassword":"<REDACTED>","cloudUserName":"<REDACTED>"}
------------------------
[KeySpec] algo=HmacSHA1 key=54,101,100,55,100,57,55,102,51,101,55,51,52,54,55,......
[Mac] getInstance: HmacSHA1
---- OKHTTP REQUEST ----
URL: https://nbu.iot-app-server.app-v2/v1/families/thing-onboarding
Method: POST
Headers:

Body:
{"familyId":"default","roomId":"2sVeb2pm","thingNames":["<REDACTED>"]}
------------------------
[Socket.connect] addr=aps1-app-server.iot.i.tplinkcloud.com/54.254.71.245:443 timeout=30000
---- OKHTTP REQUEST ----
URL: https://192.168.68.63:4433/stok=<REDACTED>/ds
Method: POST
Headers:
Connection: keep-alive
Accept: application/octet-stream

Body:
  fDɣ   S5*:  3  @ 2 ԧ  k JٗhC W x~  I   p 
------------------------
[Socket.connect] addr=/192.168.68.63:4433 timeout=30000
---- OKHTTP REQUEST ----
URL: https://n-aps1-wap.i.tplinkcloud.com/api/v2/common/getDeviceListByPage
Method: POST
Headers:
signature-required: true

Body:
{"deviceTypeList":["SMART.TAPOPLUG","SMART.TAPOBULB","SMART.IPCAMERA","SMART.TAPOHUB","SMART.TAPOSENSOR","SMART.TAPOSWITCH","SMART.TAPOROBOVAC","SMART.TAPODOORBELL","SMART.TAPOLOCK","SMART.TAPOREMOTE","SMART.TAPOCHIME","SMART.KASAPLUG","SMART.KASASWITCH","SMART.KASAHUB","SMART.KASAENERGY","IOT.IPCAMERA"],"index":0,"limit":20}
------------------------
[KeySpec] algo=HmacSHA1 key=54,101,100,55,100,57,55,102,51,101,55,51,52,54,55,......
[Mac] getInstance: HmacSHA1
[Socket.connect] addr=n-aps1-wap.i.tplinkcloud.com/47.130.43.98:443 timeout=30000
---- OKHTTP REQUEST ----
URL: https://nbu.iot-app-server.app-v2/v2/things?page=0&pageSize=100&deviceTypes=SMART.TAPOPLUG%2CSMART.TAPOBULB%2CSMART.IPCAMERA%2CSMART.TAPOHUB%2CSMART.TAPOSENSOR%2CSMART.TAPOSWITCH%2CSMART.TAPOROBOVAC%2CSMART.TAPODOORBELL%2CSMART.TAPOLOCK%2CSMART.TAPOREMOTE%2CSMART.TAPOCHIME%2CIOT.SMARTPLUGSWITCH%2CIOT.SMARTBULB%2CIOT.IPCAMERA%2CIOT.HUB%2CIOT.RANGEEXTENDER%2CIOT.RANGEEXTENDER.SMARTPLUG%2CIOT.ROUTER%2CSMART.KASAPLUG%2CSMART.KASASWITCH%2CSMART.KASAHUB%2CSMART.KASAENERGY%2CSMART.MATTERPLUG%2CSMART.MATTERBULB&includePcDevice=false&includeKasaShareDevices=true&includeMatterDevice=false
Method: GET
Headers:

logReq err: TypeError: not a function
---- OKHTTP REQUEST ----
URL: https://aps1-app-server.iot.i.tplinkcloud.com/v1/things/<REDACTED>/rt-info
Method: GET
Headers:

logReq err: TypeError: not a function
---- OKHTTP REQUEST ----
URL: https://192.168.68.63:4433/stok=<REDACTED>/ds
Method: POST
Headers:
Connection: keep-alive
Accept: application/octet-stream

Body:
  g  6B
  Y >   Q!Tf ^  FsD  NHL
------------------------
[Socket.connect] addr=/192.168.68.63:4433 timeout=30000
---- OKHTTP REQUEST ----
URL: https://aps1-app-server.iot.i.tplinkcloud.com/v1/things/<REDACTED>/details
Method: GET
Headers:

logReq err: TypeError: not a function
---- OKHTTP REQUEST ----
URL: https://aps1-app-server.iot.i.tplinkcloud.com/v1/things/<REDACTED>/settings
Method: GET
Headers:

logReq err: TypeError: not a function
[Socket.connect] addr=aps1-app-server.iot.i.tplinkcloud.com/54.254.71.245:443 timeout=30000
---- OKHTTP REQUEST ----
URL: https://aps1-app-server.iot.i.tplinkcloud.com/v1/things/<REDACTED>/components
Method: GET
Headers:

logReq err: TypeError: not a function
---- OKHTTP REQUEST ----
URL: https://aps1-app-server.iot.i.tplinkcloud.com/v1/things/shadows?thingNames=<REDACTED>
Method: GET
Headers:
isEdgeRequest: false

logReq err: TypeError: not a function
[Socket.connect] addr=aps1-app-server.iot.i.tplinkcloud.com/54.254.71.245:443 timeout=30000
[Socket.connect] addr=aps1-app-server.iot.i.tplinkcloud.com/54.254.71.245:443 timeout=30000
[Socket.connect] addr=aps1-app-server.iot.i.tplinkcloud.com/54.254.71.245:443 timeout=30000
---- OKHTTP REQUEST ----
URL: https://n-aps1-wap.i.tplinkcloud.com/api/v2/common/getIntlFwList
Method: POST
Headers:
signature-required: true

Body:
{"devFwCurrentVer":"1.3.0","deviceId":"<REDACTED>","fwId":"00000000000000000000000000000000","hwId":"FE727A169352FE69<REDACTED>","locale":"en_US","oemId":"E24B0568952B79<REDACTED>"}
------------------------
---- OKHTTP REQUEST ----
URL: https://aps1-app-server.iot.i.tplinkcloud.com/v1/things/<REDACTED>/services-sync
Method: POST
Headers:
isEdgeRequest: false

Body:
{"inputParams":{"requestData":{"method":"multipleRequest","params":{"requests":[{"method":"setQuickSetupExtraInfo","params":{"nickname":"Um9ib3QgVmFjdXVt"}}]}}},"serviceId":"passthrough"}
------------------------
[KeySpec] algo=HmacSHA1 key=54,101,100,55,100,57,55,102,51,101,55,51,52,54,55,......
---- OKHTTP REQUEST ----
URL: https://aps1-app-server.iot.i.tplinkcloud.com/v1/things/<REDACTED>/services-sync
Method: POST
Headers:
isEdgeRequest: false

Body:
{"inputParams":{"requestData":{"method":"multipleRequest","params":{"requests":[{"method":"account_sync","params":{"cloud_account":{"password":"<REDACTED>","username":"<REDACTED>,"serviceId":"passthrough"}
------------------------
[Mac] getInstance: HmacSHA1
[Socket.connect] addr=n-aps1-wap.i.tplinkcloud.com/47.130.43.98:443 timeout=30000
---- OKHTTP REQUEST ----
URL: https://aps1-app-server.iot.i.tplinkcloud.com/v1/things/<REDACTED>/components
Method: GET
Headers:

logReq err: TypeError: not a function
---- OKHTTP REQUEST ----
URL: https://aps1-app-server.iot.i.tplinkcloud.com/v1/voice-packages?deviceModel=RV30%20Max%20Plus
Method: GET
Headers:

logReq err: TypeError: not a function
---- OKHTTP REQUEST ----
URL: https://192.168.68.63:4433/stok=<REDACTED>/ds
Method: POST
Headers:
Connection: keep-alive
Accept: application/octet-stream

Body:
      _Tt3 v LB Q[iw LaG    @ T 24 ؏ 
------------------------
[Socket.connect] addr=/192.168.68.63:4433 timeout=30000
---- OKHTTP REQUEST ----
URL: https://aps1-app-server.iot.i.tplinkcloud.com/v1/things/<REDACTED>/components
Method: GET
Headers:

logReq err: TypeError: not a function
---- OKHTTP REQUEST ----
URL: https://aps1-app-server.iot.i.tplinkcloud.com/v1/things/<REDACTED>/features/autoUpdateMode
Method: PATCH
Headers:

Body:
{"enable":true,"random_range":120,"time":180}
------------------------
---- OKHTTP REQUEST ----
URL: https://aps1-app-server.iot.i.tplinkcloud.com/v1/things/<REDACTED>/services-sync
Method: POST
Headers:
isEdgeRequest: false

Body:
{"inputParams":{"requestData":{"method":"multipleRequest","params":{"requests":[{"method":"getCurrentVoiceLanguage"}]}}},"serviceId":"passthrough"}
------------------------
---- OKHTTP REQUEST ----
URL: https://aps1-app-server.iot.i.tplinkcloud.com/v1/voice-packages?deviceModel=RV30
Method: GET
Headers:

logReq err: TypeError: not a function
---- OKHTTP REQUEST ----
URL: https://192.168.68.63:4433/stok=<REDACTED>/ds
Method: POST
Headers:
Connection: keep-alive
Accept: application/octet-stream

Body:
  Ô{ F ZR  =F    |ZK0K  @   A  8    v;|Z  e 
------------------------
[Socket.connect] addr=/192.168.68.63:4433 timeout=30000
---- OKHTTP REQUEST ----
URL: https://aps1-app-server.iot.i.tplinkcloud.com/v1/things/<REDACTED>/components
Method: GET
Headers:

logReq err: TypeError: not a function
---- OKHTTP REQUEST ----
URL: https://aps1-app-server.iot.i.tplinkcloud.com/v1/voice-packages/signed-url?voicePackageId=2
Method: GET
Headers:

logReq err: TypeError: not a function
[Socket.connect] addr=aps1-app-server.iot.i.tplinkcloud.com/54.254.71.245:443 timeout=30000
---- OKHTTP REQUEST ----
URL: https://aps1-app-server.iot.i.tplinkcloud.com/v1/things/<REDACTED>/services-sync
Method: POST
Headers:
isEdgeRequest: false

Body:
{"inputParams":{"requestData":{"method":"multipleRequest","params":{"requests":[{"method":"setVoiceLanguage","params":{"md5":"055ba03d9973ac5dd","name":"bb053ca2c56f3902b","url":"https://prd-iot-as-aps1.s3.ap-southeast-1.amazonaws.com/%2FvoicePackages/voicePackages2/2_English_Female_American.tar.gz?X-Amz-Security-Token=IQoJb3JpZ2luX2VjEHYaDmFwLXNvdXRoZWFzdC0xIkgwRgIhAM3vt3Fd2jRBA8aYB71rzzu1Woohe1O%2BvnvOlH4wLz3CAiEAzvdnJc4HuMUxH%2Fdq0hUmUUXVrYvkG3jP%2Ba%2FB6Vj3jI8qnQUILxADGgw3NDYxNjY3NTYyNjUiDFr71TsbnRtbNUX4ACr6BPGn9lOCsTm5n34KJtuhT33sBzsxQes0I2AamY%2B73JvPJMc08a%2FQ%2FqNM%2BtdxjDcxILd%2F%2BGgSeAJVl5WpSuyeG1gs3cpOkcQY6yvsm8PoCHlb5EyugCp2oDmm6HgMj%2Bkuf4IXODgZmohgtRNculKigHe2c9i7A5w4V2psD4YYdjBQBZFApSaKd%2BhloX3ctD7m0KGaeKxJeJzjD1zN5wBzmGh8UAY1a6iLSont%2BHnljSQsZu9U7iDe99%2FSxcbWZL2nEjvjyVENN%2B94m1a3yLeWg8WpaLpcPj%2FUeBHA&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Date=20251022T132901Z&X-Amz-SignedHeaders=host&X-Amz-Expires=3599&X-Amz-Credential=ASIA23OYBEOUZHYDRAAJ%2F20251022%2Fap-southeast-1%2Fs3%2Faws4_request&X-Amz-Signature=b165c66043b59fac66d120144f8e51f","version":2}}]}}},"serviceId":"passthrough"}
------------------------
---- OKHTTP REQUEST ----
URL: https://aps1-app-server.iot.i.tplinkcloud.com/v1/things/shadows?thingNames=<REDACTED>
Method: GET
Headers:
isEdgeRequest: false

logReq err: TypeError: not a function
---- OKHTTP REQUEST ----
URL: https://aps1-app-server.iot.i.tplinkcloud.com/v1/things/<REDACTED>/services-sync
Method: POST
Headers:
isEdgeRequest: false

Body:
{"inputParams":{"requestData":{"method":"multipleRequest","params":{"requests":[{"method":"getCleanAttr","params":{"type":"global"}}]}}},"serviceId":"passthrough"}
------------------------
---- OKHTTP REQUEST ----
URL: https://aps1-app-server.iot.i.tplinkcloud.com/v1/things/<REDACTED>/services-sync
Method: POST
Headers:
isEdgeRequest: false

Body:
{"inputParams":{"requestData":{"method":"multipleRequest","params":{"requests":[{"method":"getMapInfo"}]}}},"serviceId":"passthrough"}
------------------------
---- OKHTTP REQUEST ----
URL: https://aps1-app-server.iot.i.tplinkcloud.com/v1/things/<REDACTED>/details
Method: GET
Headers:

logReq err: TypeError: not a function
---- OKHTTP REQUEST ----
URL: https://aps1-app-server.iot.i.tplinkcloud.com/v1/things/<REDACTED>/settings
Method: GET
Headers:

logReq err: TypeError: not a function
---- OKHTTP REQUEST ----
URL: https://aps1-app-server.iot.i.tplinkcloud.com/v1/things/shadows?thingNames=<REDACTED>
Method: GET
Headers:
isEdgeRequest: false

logReq err: TypeError: not a function
[Socket.connect] addr=aps1-app-server.iot.i.tplinkcloud.com/54.254.71.245:443 timeout=30000
[Socket.connect] addr=aps1-app-server.iot.i.tplinkcloud.com/54.254.71.245:443 timeout=30000
---- OKHTTP REQUEST ----
URL: https://aps1-app-server.iot.i.tplinkcloud.com/v1/things/<REDACTED>/services-sync
Method: POST
Headers:
isEdgeRequest: false

Body:
{"inputParams":{"requestData":{"method":"multipleRequest","params":{"requests":[{"method":"getCleanAttr","params":{"type":"running"}},{"method":"getAreaUnit"},{"method":"getCleanRecords"},{"method":"getDoNotDisturb"},{"method":"getConsumablesInfo"},{"method":"getMopState"},{"method":"getDeviceTime"},{"method":"getCurrentVoiceLanguage"},{"method":"getCustomizationRulesInfo"}]}}},"serviceId":"passthrough"}
------------------------
[Socket.connect] addr=aps1-app-server.iot.i.tplinkcloud.com/54.254.71.245:443 timeout=30000
---- OKHTTP REQUEST ----
URL: https://aps1-app-server.iot.i.tplinkcloud.com/v1/voice-packages?deviceModel=RV30%20Max%20Plus
Method: GET
Headers:

logReq err: TypeError: not a function
[Socket.connect] addr=aps1-app-server.iot.i.tplinkcloud.com/54.254.71.245:443 timeout=30000
---- OKHTTP REQUEST ----
URL: https://aps1-app-server.iot.i.tplinkcloud.com/v1/things/<REDACTED>/services-sync
Method: POST
Headers:
isEdgeRequest: false

Body:
{"inputParams":{"requestData":{"method":"multipleRequest","params":{"requests":[{"method":"getMapData","params":{}},{"method":"getPathData","params":{"start_pos":0}}]}}},"serviceId":"passthrough"}
------------------------
---- OKHTTP REQUEST ----
URL: https://aps1-app-server.iot.i.tplinkcloud.com/v1/things/<REDACTED>/rt-info
Method: GET
Headers:

logReq err: TypeError: not a function
---- OKHTTP REQUEST ----
URL: https://aps1-app-server.iot.i.tplinkcloud.com/v1/things/<REDACTED>/services-sync
Method: POST
Headers:
isEdgeRequest: false

Body:
{"inputParams":{"requestData":{"method":"multipleRequest","params":{"requests":[{"method":"getCleanAttr","params":{"type":"global"}}]}}},"serviceId":"passthrough"}
------------------------
---- OKHTTP REQUEST ----
URL: https://aps1-app-server.iot.i.tplinkcloud.com/v1/things/<REDACTED>/firmwares/latest
Method: GET
Headers:

logReq err: TypeError: not a function
---- OKHTTP REQUEST ----
URL: https://aps1-app-server.iot.i.tplinkcloud.com/v1/things/<REDACTED>/services-sync
Method: POST
Headers:
isEdgeRequest: false

Body:
{"inputParams":{"requestData":{"method":"multipleRequest","params":{"requests":[{"method":"startUpdateMapData","params":{"map_upload_start":true}}]}}},"serviceId":"passthrough"}
------------------------
---- OKHTTP REQUEST ----
URL: https://aps1-app-server.iot.i.tplinkcloud.com/v1/things/<REDACTED>/services-sync
Method: POST
Headers:
isEdgeRequest: false

Body:
{"inputParams":{"requestData":{"method":"multipleRequest","params":{"requests":[{"method":"getMapData","params":{}},{"method":"getPathData","params":{"start_pos":0}}]}}},"serviceId":"passthrough"}
------------------------
---- OKHTTP REQUEST ----
URL: https://aps1-app-server.iot.i.tplinkcloud.com/v1/things/<REDACTED>/services-sync
Method: POST
Headers:
isEdgeRequest: false

Body:
{"inputParams":{"requestData":{"method":"multipleRequest","params":{"requests":[{"method":"startUpdateMapData","params":{"map_upload_start":true}}]}}},"serviceId":"passthrough"}
------------------------
---- OKHTTP REQUEST ----
URL: https://aps1-app-server.iot.i.tplinkcloud.com/v1/things/<REDACTED>/services-sync
Method: POST
Headers:
isEdgeRequest: false

Body:
{"inputParams":{"requestData":{"method":"multipleRequest","params":{"requests":[{"method":"getMapInfo"}]}}},"serviceId":"passthrough"}
------------------------
---- OKHTTP REQUEST ----
URL: https://aps1-app-server.iot.i.tplinkcloud.com/v1/things/<REDACTED>/services-sync
Method: POST
Headers:
isEdgeRequest: false

Body:
{"inputParams":{"requestData":{"method":"multipleRequest","params":{"requests":[{"method":"getMapData","params":{"map_id":0}},{"method":"getPathData","params":{"start_pos":0}}]}}},"serviceId":"passthrough"}
------------------------
---- OKHTTP REQUEST ----
URL: https://aps1-app-server.iot.i.tplinkcloud.com/v1/things/<REDACTED>/services-sync
Method: POST
Headers:
isEdgeRequest: false

Body:
{"inputParams":{"requestData":{"method":"multipleRequest","params":{"requests":[{"method":"getPathData","params":{"start_pos":0}}]}}},"serviceId":"passthrough"}
------------------------
---- OKHTTP REQUEST ----
URL: https://aps1-app-server.iot.i.tplinkcloud.com/v1/things/<REDACTED>/services-sync
Method: POST
Headers:
isEdgeRequest: false

Body:
{"inputParams":{"requestData":{"method":"multipleRequest","params":{"requests":[{"method":"getPathData","params":{"start_pos":0}}]}}},"serviceId":"passthrough"}
------------------------
---- OKHTTP REQUEST ----
URL: https://aps1-app-server.iot.i.tplinkcloud.com/v1/things/<REDACTED>/services-sync
Method: POST
Headers:
isEdgeRequest: false

Body:
{"inputParams":{"requestData":{"method":"multipleRequest","params":{"requests":[{"method":"getCleanRecords"}]}}},"serviceId":"passthrough"}
------------------------
---- OKHTTP REQUEST ----
URL: https://aps1-app-server.iot.i.tplinkcloud.com/v1/things/<REDACTED>/services-sync
Method: POST
Headers:
isEdgeRequest: false

Body:
{"inputParams":{"requestData":{"method":"multipleRequest","params":{"requests":[{"method":"getCleanRecords"}]}}},"serviceId":"passthrough"}
------------------------
---- OKHTTP REQUEST ----
URL: https://aps1-app-server.iot.i.tplinkcloud.com/v1/things/<REDACTED>/services-sync
Method: POST
Headers:
isEdgeRequest: false

Body:
{"inputParams":{"requestData":{"method":"multipleRequest","params":{"requests":[{"method":"getPathData","params":{"start_pos":0}}]}}},"serviceId":"passthrough"}
------------------------
---- OKHTTP REQUEST ----
URL: https://aps1-app-server.iot.i.tplinkcloud.com/v1/things/<REDACTED>/services-sync
Method: POST
Headers:
isEdgeRequest: false

Body:
{"inputParams":{"requestData":{"method":"multipleRequest","params":{"requests":[{"method":"getMapData","params":{}},{"method":"getPathData","params":{"start_pos":0}}]}}},"serviceId":"passthrough"}
------------------------
---- OKHTTP REQUEST ----
URL: https://aps1-app-server.iot.i.tplinkcloud.com/v1/things/shadows?thingNames=<REDACTED>
Method: GET
Headers:
isEdgeRequest: false

logReq err: TypeError: not a function
---- OKHTTP REQUEST ----
URL: https://aps1-app-server.iot.i.tplinkcloud.com/v1/things/<REDACTED>/services-sync
Method: POST
Headers:
isEdgeRequest: false

Body:
{"inputParams":{"requestData":{"method":"multipleRequest","params":{"requests":[{"method":"getPathData","params":{"start_pos":0}}]}}},"serviceId":"passthrough"}
------------------------
---- OKHTTP REQUEST ----
URL: https://aps1-app-server.iot.i.tplinkcloud.com/v1/things/<REDACTED>/rules?ruleType=schedule&startIndex=0
Method: GET
Headers:

logReq err: TypeError: not a function
---- OKHTTP REQUEST ----
URL: https://aps1-app-server.iot.i.tplinkcloud.com/v1/things/<REDACTED>/services-sync
Method: POST
Headers:
isEdgeRequest: false

Body:
{"inputParams":{"requestData":{"method":"multipleRequest","params":{"requests":[{"method":"getPathData","params":{"start_pos":0}}]}}},"serviceId":"passthrough"}
------------------------
---- OKHTTP REQUEST ----
URL: https://aps1-app-server.iot.i.tplinkcloud.com/v1/things/<REDACTED>/services-sync
Method: POST
Headers:
isEdgeRequest: false

Body:
{"inputParams":{"requestData":{"method":"multipleRequest","params":{"requests":[{"method":"getPathData","params":{"start_pos":0}}]}}},"serviceId":"passthrough"}
------------------------
---- OKHTTP REQUEST ----
URL: https://aps1-app-server.iot.i.tplinkcloud.com/v1/things/<REDACTED>/services-sync
Method: POST
Headers:
isEdgeRequest: false

Body:
{"inputParams":{"requestData":{"method":"multipleRequest","params":{"requests":[{"method":"getMapData","params":{}},{"method":"getPathData","params":{"start_pos":0}}]}}},"serviceId":"passthrough"}
------------------------
---- OKHTTP REQUEST ----
URL: https://aps1-app-server.iot.i.tplinkcloud.com/v1/things/<REDACTED>/firmwares/latest
Method: GET
Headers:

logReq err: TypeError: not a function
---- OKHTTP REQUEST ----
URL: https://aps1-app-server.iot.i.tplinkcloud.com/v1/things/<REDACTED>/services-sync
Method: POST
Headers:
isEdgeRequest: false

Body:
{"inputParams":{"requestData":{"method":"multipleRequest","params":{"requests":[{"method":"getDeviceTime"}]}}},"serviceId":"passthrough"}
------------------------
---- OKHTTP REQUEST ----
URL: https://aps1-app-server.iot.i.tplinkcloud.com/v1/things/shadows?thingNames=<REDACTED>
Method: GET
Headers:
isEdgeRequest: false

logReq err: TypeError: not a function
---- OKHTTP REQUEST ----
URL: https://aps1-app-server.iot.i.tplinkcloud.com/v1/things/<REDACTED>/settings
Method: GET
Headers:

logReq err: TypeError: not a function
---- OKHTTP REQUEST ----
URL: https://aps1-app-server.iot.i.tplinkcloud.com/v1/things/<REDACTED>/details
Method: GET
Headers:

logReq err: TypeError: not a function
---- OKHTTP REQUEST ----
URL: https://aps1-app-server.iot.i.tplinkcloud.com/v1/things/<REDACTED>/services-sync
Method: POST
Headers:
isEdgeRequest: false

Body:
{"inputParams":{"requestData":{"method":"multipleRequest","params":{"requests":[{"method":"getCarpetClean"},{"method":"getChildLockInfo"},{"method":"getDoNotDisturb"},{"method":"getCleanAttr","params":{"type":"pose"}},{"method":"getConsumablesInfo"},{"method":"getDustCollectionInfo"}]}}},"serviceId":"passthrough"}
------------------------
---- OKHTTP REQUEST ----
URL: https://aps1-app-server.iot.i.tplinkcloud.com/v1/things/<REDACTED>/services-sync
Method: POST
Headers:
isEdgeRequest: false

Body:
{"inputParams":{"requestData":{"method":"multipleRequest","params":{"requests":[{"method":"getMapInfo"}]}}},"serviceId":"passthrough"}
------------------------
---- OKHTTP REQUEST ----
URL: https://aps1-app-server.iot.i.tplinkcloud.com/v1/things/<REDACTED>/rt-info
Method: GET
Headers:

logReq err: TypeError: not a function
---- OKHTTP REQUEST ----
URL: https://aps1-app-server.iot.i.tplinkcloud.com/v1/things/<REDACTED>/services-sync
Method: POST
Headers:
isEdgeRequest: false

Body:
{"inputParams":{"requestData":{"method":"multipleRequest","params":{"requests":[{"method":"getMapData","params":{"map_id":0}},{"method":"getPathData","params":{"start_pos":0}}]}}},"serviceId":"passthrough"}
------------------------
---- OKHTTP REQUEST ----
URL: https://aps1-app-server.iot.i.tplinkcloud.com/v1/things/<REDACTED>/services-sync
Method: POST
Headers:
isEdgeRequest: false

Body:
{"inputParams":{"requestData":{"method":"multipleRequest","params":{"requests":[{"method":"getPathData","params":{"start_pos":0}}]}}},"serviceId":"passthrough"}
------------------------
---- OKHTTP REQUEST ----
URL: https://aps1-app-server.iot.i.tplinkcloud.com/v1/things/shadows?thingNames=<REDACTED>
Method: GET
Headers:
isEdgeRequest: false

logReq err: TypeError: not a function
---- OKHTTP REQUEST ----
URL: https://aps1-app-server.iot.i.tplinkcloud.com/v1/things/<REDACTED>/services-sync
Method: POST
Headers:
isEdgeRequest: false

Body:
{"inputParams":{"requestData":{"method":"multipleRequest","params":{"requests":[{"method":"getMapInfo"}]}}},"serviceId":"passthrough"}
------------------------
---- OKHTTP REQUEST ----
URL: https://aps1-app-server.iot.i.tplinkcloud.com/v1/things/<REDACTED>/details
Method: GET
Headers:

logReq err: TypeError: not a function
---- OKHTTP REQUEST ----
URL: https://aps1-app-server.iot.i.tplinkcloud.com/v1/things/shadows?thingNames=<REDACTED>
Method: GET
Headers:
isEdgeRequest: false

logReq err: TypeError: not a function
---- OKHTTP REQUEST ----
URL: https://aps1-app-server.iot.i.tplinkcloud.com/v1/things/<REDACTED>/settings
Method: GET
Headers:

logReq err: TypeError: not a function
---- OKHTTP REQUEST ----
URL: https://aps1-app-server.iot.i.tplinkcloud.com/v1/voice-packages?deviceModel=RV30%20Max%20Plus
Method: GET
Headers:

logReq err: TypeError: not a function
---- OKHTTP REQUEST ----
URL: https://aps1-app-server.iot.i.tplinkcloud.com/v1/things/<REDACTED>/services-sync
Method: POST
Headers:
isEdgeRequest: false

Body:
{"inputParams":{"requestData":{"method":"multipleRequest","params":{"requests":[{"method":"getMapData","params":{"map_id":0}},{"method":"getPathData","params":{"start_pos":0}}]}}},"serviceId":"passthrough"}
------------------------
---- OKHTTP REQUEST ----
URL: https://aps1-app-server.iot.i.tplinkcloud.com/v1/things/<REDACTED>/services-sync
Method: POST
Headers:
isEdgeRequest: false

Body:
{"inputParams":{"requestData":{"method":"multipleRequest","params":{"requests":[{"method":"getCleanAttr","params":{"type":"running"}},{"method":"getAreaUnit"},{"method":"getCleanRecords"},{"method":"getDoNotDisturb"},{"method":"getConsumablesInfo"},{"method":"getMopState"},{"method":"getDeviceTime"},{"method":"getCurrentVoiceLanguage"},{"method":"getCustomizationRulesInfo"}]}}},"serviceId":"passthrough"}
------------------------
---- OKHTTP REQUEST ----
URL: https://aps1-app-server.iot.i.tplinkcloud.com/v1/things/<REDACTED>/rt-info
Method: GET
Headers

@ZeliardM
Copy link
Copy Markdown
Contributor Author

@danieyal That's great, I do see something in your logs about nbu, that may help point me where I need to go.

Yea, Frida is a pain. I've used it in the past but lost my devices to do so, so it's been rough lately.

I appreciate your work so far. I am going through the encryption pieces again. Yea, the pake_register phase is essentially handshake1 and I still need to see what is going on.

@ZeliardM
Copy link
Copy Markdown
Contributor Author

@danieyal Ok, I've spent most of the day going over things, and I think I'm at an impasse. I can't get the URLs to communicate with the cloud for the NOC certificates. I've gotten close, but what happens is that the APK uses a call, gets a cloud token, then pulls the URLs from the cloud. I can get the cloud token, but the I cannot get the signature matches for the calls out that have 'signature-required' set to true. I need to see if there is a way to reverse engineer these signatures so we can get them to match from my code based on how everything is supposed to be. I have some scripts and code that I've got for testing if you would be able to take it along with some of the Frida work you've done and possibly see if you can get the URL? I can send them via Discord if that works?

@danieyal
Copy link
Copy Markdown

@ZeliardM yeah sure, I will try but since I am working during the day, I might not have enough time to dedicate to it, but I'll try. Discord works for me.

@ZeliardM
Copy link
Copy Markdown
Contributor Author

@danieyal All good, give it a shot and let me know and we will go from there. Thanks!

@ZeliardM
Copy link
Copy Markdown
Contributor Author

@danieyal What I have been able to pull apart today is that the checkpassword call that is used in the frida logs you posted earlier, this has the same signature requirements that I am looking for. If you can get me some wireshark pulls of this actual communication so I can see the actual headers and packet information, then I might be able to reverse engineer this from there. If you want, we can keep going on Discord, my username is the same there.

@ZeliardM
Copy link
Copy Markdown
Contributor Author

@danieyal nevermind, I finally got the matching signature and figured out how to get the right url for getting the certificates!

@ZeliardM
Copy link
Copy Markdown
Contributor Author

ZeliardM commented Oct 24, 2025

Ok, now that I have all of this, my plan is as follows:

  1. Add certificate handling and a certificate store to the python-kasa API and CLI. This will be both as callable functions and storage. python-kasa itself is stateless and does not hold information, so these will be configured to store data in predefined areas based on Operating Systems.

  2. Update the TPAP Transport to handle NOC Authentication with SPAKE2+ and DAC Authentication. This will use the NOC data from the new modules to handle everything hopefully seamlessly, at least that's how I'm going to try to get it configured.

It's going to take quite some time for me to get through all of this, I want to put it together cleanly.

I'm headed out of town with my family for the weekend so I may not work on it much right now, but will keep everyone updated as I keep working on it.

@ZeliardM
Copy link
Copy Markdown
Contributor Author

I am still slowly working on this. I have the NOC capabilities set up, now I'm working on testing the code. Having issues with the CSR formatting so I'll keep plugging away at it and keep you in the loop.

@epg-pers
Copy link
Copy Markdown

@ZeliardM Thanks for the steer. I've put together the room cleaning changes here: #1660 — happy to adjust anything based on your feedback.

Comment thread kasa/transports/tpaptransport.py Fixed
Comment thread kasa/transports/tpaptransport.py Fixed
Comment thread kasa/transports/tpaptransport.py Fixed
Comment thread kasa/transports/tpaptransport.py Fixed
@ZeliardM
Copy link
Copy Markdown
Contributor Author

I am making some major changes to the TPAP Implementation. I would like anyone's help testing it. I need to make sure that it functions and works with all of the device types that currently support TPAP, plugs, vacuums, and cameras. I am finalizing the changes now and should be able to get something out later today, but I will need people to test and get me debug plain discover logs from the CLI of kasa to be specific in the handling. If you have any questions, let me know.


@staticmethod
def _md5_hex(value: str) -> str:
return hashlib.md5(value.encode()).hexdigest() # noqa: S324

Check failure

Code scanning / CodeQL

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

Sensitive data (id)
is used in a hashing algorithm (MD5) that is insecure.
Sensitive data (id)
is used in a hashing algorithm (MD5) that is insecure.
Sensitive data (id)
is used in a hashing algorithm (MD5) that is insecure.
Sensitive data (id)
is used in a hashing algorithm (MD5) that is insecure.
Sensitive data (id)
is used in a hashing algorithm (MD5) that is insecure.
Sensitive data (id)
is used in a hashing algorithm (MD5) that is insecure.
Sensitive data (id) is used in a hashing algorithm (MD5) that is insecure.
Sensitive data (password) is used in a hashing algorithm (MD5) that is insecure for password hashing, since it is not a computationally expensive hash function.
Sensitive data (password) is used in a hashing algorithm (MD5) that is insecure for password hashing, since it is not a computationally expensive hash function.
Comment thread kasa/transports/tpaptransport.py Fixed

@staticmethod
def _sha1_hex(value: str) -> str:
return hashlib.sha1(value.encode()).hexdigest() # noqa: S324

Check failure

Code scanning / CodeQL

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

Sensitive data (secret)
is used in a hashing algorithm (SHA1) that is insecure.
Sensitive data (password)
is used in a hashing algorithm (SHA1) that is insecure for password hashing, since it is not a computationally expensive hash function.
Sensitive data (password)
is used in a hashing algorithm (SHA1) that is insecure for password hashing, since it is not a computationally expensive hash function.
Sensitive data (password)
is used in a hashing algorithm (SHA1) that is insecure for password hashing, since it is not a computationally expensive hash function.
)
return passcode
return hashlib.sha256(
(username_hint + decoded_salt + passcode).encode()

Check failure

Code scanning / CodeQL

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

Sensitive data (password)
is used in a hashing algorithm (SHA256) that is insecure for password hashing, since it is not a computationally expensive hash function.
Sensitive data (password)
is used in a hashing algorithm (SHA256) that is insecure for password hashing, since it is not a computationally expensive hash function.
Sensitive data (password)
is used in a hashing algorithm (SHA256) that is insecure for password hashing, since it is not a computationally expensive hash function.
@ZeliardM
Copy link
Copy Markdown
Contributor Author

Ok, I have pushed all my changes. I still have some clean up, but we should be pretty close now.

I made a lot of changes and the first thing to do is see if the device connections for tpap still work at all. There are two paths:

  1. Remove-Item Env:KASA_TEST_DISABLE_TPAP_TLS2_VERIFY -ErrorAction SilentlyContinue
  • This command is in Powershell and you can change it to whatever environment you're working in. This will remove any test flags and force the code to use a hardcoded Root CA Certificate for TLS Cert Verify if TLS = 2. This certificate in the old code was retrieved via the NOC/Cloud dependency and since we have removed that, I pulled it and hardcoded it in. Test here to see if the TPAP Transport now works with this hardcoded and SPAKE2+ only communication.
  1. $env:KASA_TEST_DISABLE_TPAP_TLS2_VERIFY="1"
  • This command is in Powershell and you can change it to whatever environment you're working in. This will set the test flag and force the code to skip a hardcoded Root CA Certificate for TLS Cert Verify if TLS = 2 and instead use CERT_NONE. This certificate in the old code was retrieved via the NOC/Cloud dependency and since we have removed that, I want to simulate the code running without that for SPAKE2+ Test here to see if the TPAP Transport now works without Cert Verify and SPAKE2+ only communication.

If you have any questions about this, let me know. And thanks for testing.

@Slaymish
Copy link
Copy Markdown

Slaymish commented Apr 1, 2026

Device: L535E(EU) — SMART.TAPOBULB
Firmware: 1.4.1 Build 251016 Rel.204554
TPAP config: tls=0, http_port=80, is_support_https=False, dac=1, noc=1, pake=[2]

SPAKE2+ handshake is being attempted over plain HTTP (no TLS, port 80). Device responds to pake_register with error code -2203 (mapped to INTERNAL_UNKNOWN_ERROR). Two POSTs to http://192.168.1.111/ are made before failing.

This is a tls=0 device unlike the RV30 Max which uses tls=2/HTTPS — may need separate handling for the no-TLS path.

DEBUG    TPAP: starting SPAKE2+ handshake with 192.168.1.111
DEBUG    Posting to http://192.168.1.111/
DEBUG    Posting to http://192.168.1.111/
WARNING  Device 192.168.1.111 received unknown error code: -2203

@ZeliardM
Copy link
Copy Markdown
Contributor Author

ZeliardM commented Apr 1, 2026

@Slaymish I appreciate this, one of the first bulbs I've seen with this now. I'm still working on additional changes here, so please be patient and I'll let you know when you can try and pull the code and try again.

@danieyal
Copy link
Copy Markdown

danieyal commented Apr 1, 2026

Ok, I have pushed all my changes. I still have some clean up, but we should be pretty close now.

I made a lot of changes and the first thing to do is see if the device connections for tpap still work at all. There are two paths:

  1. Remove-Item Env:KASA_TEST_DISABLE_TPAP_TLS2_VERIFY -ErrorAction SilentlyContinue
  • This command is in Powershell and you can change it to whatever environment you're working in. This will remove any test flags and force the code to use a hardcoded Root CA Certificate for TLS Cert Verify if TLS = 2. This certificate in the old code was retrieved via the NOC/Cloud dependency and since we have removed that, I pulled it and hardcoded it in. Test here to see if the TPAP Transport now works with this hardcoded and SPAKE2+ only communication.
  1. $env:KASA_TEST_DISABLE_TPAP_TLS2_VERIFY="1"
  • This command is in Powershell and you can change it to whatever environment you're working in. This will set the test flag and force the code to skip a hardcoded Root CA Certificate for TLS Cert Verify if TLS = 2 and instead use CERT_NONE. This certificate in the old code was retrieved via the NOC/Cloud dependency and since we have removed that, I want to simulate the code running without that for SPAKE2+ Test here to see if the TPAP Transport now works without Cert Verify and SPAKE2+ only communication.

If you have any questions about this, let me know. And thanks for testing.

@ZeliardM

// Remove-Item Env:KASA_TEST_DISABLE_TPAP_TLS2_VERIFY -ErrorAction SilentlyContinue

DEBUG    Trying to connect with SmartProtocol                                                            discover.py:684
DEBUG    Using SmartDevice for SMART.TAPOROBOVAC                                                   device_factory.py:181
DEBUG    Initializing 192.168.68.63 of type <class 'kasa.smart.smartdevice.SmartDevice'>                   device.py:217
DEBUG    192.168.68.63 multi-request-batch-1-of-1 >>                                                smartprotocol.py:242
         '{"method":"multipleRequest","request_time_milis":1775055520537,"terminal_uuid":"y4VYNjYdj
         a+nq66kiAffUA==","params":{"requests":[{"method":"component_nego"},{"method":"get_device_i
         nfo"},{"method":"get_connect_cloud_state"}]}}'
DEBUG    TPAP: starting SPAKE2+ handshake with 192.168.68.63                                        tpaptransport.py:194
DEBUG    Posting to https://192.168.68.63:4433/                                                         httpclient.py:88
DEBUG    Posting to https://192.168.68.63:4433/                                                         httpclient.py:88
DEBUG    Device 192.168.68.63 received an os error, enabling sequential request delay: Cannot connect  httpclient.py:136
         to host 192.168.68.63:4433 ssl:True [SSLCertVerificationError: (1, '[SSL:
         CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate
         (_ssl.c:1032)')]
DEBUG    Device 192.168.68.63 got a connection error, will retry 3 times: ("Device connection       smartprotocol.py:146
         error: 192.168.68.63: Cannot connect to host 192.168.68.63:4433 ssl:True
         [SSLCertVerificationError: (1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify
         failed: unable to get local issuer certificate (_ssl.c:1032)')]",
         ClientConnectorCertificateError(ConnectionKey(host='192.168.68.63', port=4433,
         is_ssl=True, ssl=<ssl.SSLContext object at 0x000001D85EE56F30>, proxy=None,
         proxy_auth=None, proxy_headers_hash=None), SSLCertVerificationError(1, '[SSL:
         CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer
         certificate (_ssl.c:1032)')))
DEBUG    192.168.68.63 multi-request-batch-1-of-1 >>                                                smartprotocol.py:242
         '{"method":"multipleRequest","request_time_milis":1775055521132,"terminal_uuid":"y4VYNjYdj
         a+nq66kiAffUA==","params":{"requests":[{"method":"component_nego"},{"method":"get_device_i
         nfo"},{"method":"get_connect_cloud_state"}]}}'
DEBUG    TPAP: starting SPAKE2+ handshake with 192.168.68.63                                        tpaptransport.py:194
DEBUG    Device 192.168.68.63 waiting 0.24655039998469874 seconds to send request                       httpclient.py:81
DEBUG    Posting to https://192.168.68.63:4433/                                                         httpclient.py:88
DEBUG    192.168.68.63 multi-request-batch-1-of-1 >>                                                smartprotocol.py:242
         '{"method":"multipleRequest","request_time_milis":1775055521483,"terminal_uuid":"y4VYNjYdj
         a+nq66kiAffUA==","params":{"requests":[{"method":"component_nego"},{"method":"get_device_i
         nfo"},{"method":"get_connect_cloud_state"}]}}'
DEBUG    TPAP: starting SPAKE2+ handshake with 192.168.68.63                                        tpaptransport.py:194
DEBUG    Device 192.168.68.63 waiting 0.2471263000043109 seconds to send request                        httpclient.py:81
DEBUG    Posting to https://192.168.68.63:4433/                                                         httpclient.py:88
DEBUG    192.168.68.63 multi-request-batch-1-of-1 >>                                                smartprotocol.py:242
         '{"method":"multipleRequest","request_time_milis":1775055521811,"terminal_uuid":"y4VYNjYdj
         a+nq66kiAffUA==","params":{"requests":[{"method":"component_nego"},{"method":"get_device_i
         nfo"},{"method":"get_connect_cloud_state"}]}}'
DEBUG    TPAP: starting SPAKE2+ handshake with 192.168.68.63                                        tpaptransport.py:194
DEBUG    Device 192.168.68.63 waiting 0.24718599999323487 seconds to send request                       httpclient.py:81
DEBUG    Posting to https://192.168.68.63:4433/                                                         httpclient.py:88
DEBUG    Giving up on 192.168.68.63 after 3 retries                                                 smartprotocol.py:153
DEBUG    Unable to connect with SmartProtocol: ("Device connection error: 192.168.68.63: Cannot connect  discover.py:687
         to host 192.168.68.63:4433 ssl:True [SSLCertVerificationError: (1, '[SSL:
         CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate
         (_ssl.c:1032)')]", ClientConnectorCertificateError(ConnectionKey(host='192.168.68.63',
         port=4433, is_ssl=True, ssl=<ssl.SSLContext object at 0x000001D85EE574D0>, proxy=None,
         proxy_auth=None, proxy_headers_hash=None), SSLCertVerificationError(1, '[SSL:
         CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate
         (_ssl.c:1032)')))
Attempt to connect to 192.168.68.63 with SmartProtocol + TpapTransport + SmartDevice + https failed
DEBUG    Trying to connect with SmartProtocol                                                            discover.py:684
DEBUG    Using SmartDevice for SMART.TAPOPLUG                                                      device_factory.py:181
DEBUG    Initializing 192.168.68.63 of type <class 'kasa.smart.smartdevice.SmartDevice'>                   device.py:217
DEBUG    192.168.68.63 multi-request-batch-1-of-1 >>                                                smartprotocol.py:242
         '{"method":"multipleRequest","request_time_milis":1775055523242,"terminal_uuid":"TD11vwRNY
         RllfSld5EQtNw==","params":{"requests":[{"method":"component_nego"},{"method":"get_device_i
         nfo"},{"method":"get_connect_cloud_state"}]}}'
DEBUG    TPAP: starting SPAKE2+ handshake with 192.168.68.63                                        tpaptransport.py:194
DEBUG    Posting to http://192.168.68.63/                                                               httpclient.py:88
DEBUG    Device 192.168.68.63 received an os error, enabling sequential request delay: Cannot connect  httpclient.py:136
         to host 192.168.68.63:80 ssl:<ssl.SSLContext object at 0x000001D85EE571B0> [The remote
         computer refused the network connection]
DEBUG    Device 192.168.68.63 got a connection error, will retry 3 times: ('Device connection       smartprotocol.py:146
         error: 192.168.68.63: Cannot connect to host 192.168.68.63:80 ssl:<ssl.SSLContext object
         at 0x000001D85EE571B0> [The remote computer refused the network connection]',
         ClientConnectorError(ConnectionKey(host='192.168.68.63', port=80, is_ssl=False,
         ssl=<ssl.SSLContext object at 0x000001D85EE571B0>, proxy=None, proxy_auth=None,
         proxy_headers_hash=None), ConnectionRefusedError(22, 'The remote computer refused the
         network connection', None, 1225, None)))
DEBUG    192.168.68.63 multi-request-batch-1-of-1 >>                                                smartprotocol.py:242
         '{"method":"multipleRequest","request_time_milis":1775055525331,"terminal_uuid":"TD11vwRNY
         RllfSld5EQtNw==","params":{"requests":[{"method":"component_nego"},{"method":"get_device_i
         nfo"},{"method":"get_connect_cloud_state"}]}}'
DEBUG    TPAP: starting SPAKE2+ handshake with 192.168.68.63                                        tpaptransport.py:194
DEBUG    Device 192.168.68.63 waiting 0.24634950002655387 seconds to send request                       httpclient.py:81
DEBUG    Posting to http://192.168.68.63/                                                               httpclient.py:88
DEBUG    192.168.68.63 multi-request-batch-1-of-1 >>                                                smartprotocol.py:242
         '{"method":"multipleRequest","request_time_milis":1775055527637,"terminal_uuid":"TD11vwRNY
         RllfSld5EQtNw==","params":{"requests":[{"method":"component_nego"},{"method":"get_device_i
         nfo"},{"method":"get_connect_cloud_state"}]}}'
DEBUG    TPAP: starting SPAKE2+ handshake with 192.168.68.63                                        tpaptransport.py:194
DEBUG    Device 192.168.68.63 waiting 0.24730260000796989 seconds to send request                       httpclient.py:81
DEBUG    Posting to http://192.168.68.63/                                                               httpclient.py:88
DEBUG    192.168.68.63 multi-request-batch-1-of-1 >>                                                smartprotocol.py:242
         '{"method":"multipleRequest","request_time_milis":1775055529947,"terminal_uuid":"TD11vwRNY
         RllfSld5EQtNw==","params":{"requests":[{"method":"component_nego"},{"method":"get_device_i
         nfo"},{"method":"get_connect_cloud_state"}]}}'
DEBUG    TPAP: starting SPAKE2+ handshake with 192.168.68.63                                        tpaptransport.py:194
DEBUG    Device 192.168.68.63 waiting 0.24771519997739233 seconds to send request                       httpclient.py:81
DEBUG    Posting to http://192.168.68.63/                                                               httpclient.py:88
DEBUG    Giving up on 192.168.68.63 after 3 retries                                                 smartprotocol.py:153
DEBUG    Unable to connect with SmartProtocol: ('Device connection error: 192.168.68.63: Cannot connect  discover.py:687
         to host 192.168.68.63:80 ssl:<ssl.SSLContext object at 0x000001D85EE577F0> [The remote computer
         refused the network connection]', ClientConnectorError(ConnectionKey(host='192.168.68.63',
         port=80, is_ssl=False, ssl=<ssl.SSLContext object at 0x000001D85EE577F0>, proxy=None,
         proxy_auth=None, proxy_headers_hash=None), ConnectionRefusedError(22, 'The remote computer
         refused the network connection', None, 1225, None)))
Attempt to connect to 192.168.68.63 with SmartProtocol + TpapTransport + SmartDevice + http failed
DEBUG    Trying to connect with SmartCamProtocol                                                         discover.py:684
DEBUG    Using SmartCamDevice for SMART.IPCAMERA                                                   device_factory.py:181
DEBUG    Initializing 192.168.68.63 of type <class 'kasa.smartcam.smartcamdevice.SmartCamDevice'>          device.py:217
DEBUG    192.168.68.63 multi-request-batch-1-of-1 >>                                                smartprotocol.py:242
         '{"method":"multipleRequest","request_time_milis":1775055532261,"terminal_uuid":"+YKGGogix
         Irt3M03hhDg4w==","params":{"requests":[{"method":"getDeviceInfo","params":{"device_info":{
         "name":["basic_info","info"]}}},{"method":"getAppComponentList","params":{"app_component":
         {"name":"app_component_list"}}},{"method":"getConnectionType","params":{"network":{"get_co
         nnection_type":{}}}}]}}'
DEBUG    TPAP: starting SPAKE2+ handshake with 192.168.68.63                                        tpaptransport.py:194
DEBUG    Posting to https://192.168.68.63:4433/                                                         httpclient.py:88
DEBUG    Posting to https://192.168.68.63:4433/                                                         httpclient.py:88
DEBUG    Device 192.168.68.63 received an os error, enabling sequential request delay: Cannot connect  httpclient.py:136
         to host 192.168.68.63:4433 ssl:True [SSLCertVerificationError: (1, '[SSL:
         CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate
         (_ssl.c:1032)')]
DEBUG    Device 192.168.68.63 got a connection error, will retry 3 times: ("Device connection       smartprotocol.py:146
         error: 192.168.68.63: Cannot connect to host 192.168.68.63:4433 ssl:True
         [SSLCertVerificationError: (1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify
         failed: unable to get local issuer certificate (_ssl.c:1032)')]",
         ClientConnectorCertificateError(ConnectionKey(host='192.168.68.63', port=4433,
         is_ssl=True, ssl=<ssl.SSLContext object at 0x000001D85EE576B0>, proxy=None,
         proxy_auth=None, proxy_headers_hash=None), SSLCertVerificationError(1, '[SSL:
         CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer
         certificate (_ssl.c:1032)')))
DEBUG    192.168.68.63 multi-request-batch-1-of-1 >>                                                smartprotocol.py:242
         '{"method":"multipleRequest","request_time_milis":1775055532866,"terminal_uuid":"+YKGGogix
         Irt3M03hhDg4w==","params":{"requests":[{"method":"getDeviceInfo","params":{"device_info":{
         "name":["basic_info","info"]}}},{"method":"getAppComponentList","params":{"app_component":
         {"name":"app_component_list"}}},{"method":"getConnectionType","params":{"network":{"get_co
         nnection_type":{}}}}]}}'
DEBUG    TPAP: starting SPAKE2+ handshake with 192.168.68.63                                        tpaptransport.py:194
DEBUG    Device 192.168.68.63 waiting 0.24599140000646003 seconds to send request                       httpclient.py:81
DEBUG    Posting to https://192.168.68.63:4433/                                                         httpclient.py:88
DEBUG    192.168.68.63 multi-request-batch-1-of-1 >>                                                smartprotocol.py:242
         '{"method":"multipleRequest","request_time_milis":1775055533222,"terminal_uuid":"+YKGGogix
         Irt3M03hhDg4w==","params":{"requests":[{"method":"getDeviceInfo","params":{"device_info":{
         "name":["basic_info","info"]}}},{"method":"getAppComponentList","params":{"app_component":
         {"name":"app_component_list"}}},{"method":"getConnectionType","params":{"network":{"get_co
         nnection_type":{}}}}]}}'
DEBUG    TPAP: starting SPAKE2+ handshake with 192.168.68.63                                        tpaptransport.py:194
DEBUG    Device 192.168.68.63 waiting 0.2475067999912426 seconds to send request                        httpclient.py:81
DEBUG    Posting to https://192.168.68.63:4433/                                                         httpclient.py:88
DEBUG    192.168.68.63 multi-request-batch-1-of-1 >>                                                smartprotocol.py:242
         '{"method":"multipleRequest","request_time_milis":1775055533566,"terminal_uuid":"+YKGGogix
         Irt3M03hhDg4w==","params":{"requests":[{"method":"getDeviceInfo","params":{"device_info":{
         "name":["basic_info","info"]}}},{"method":"getAppComponentList","params":{"app_component":
         {"name":"app_component_list"}}},{"method":"getConnectionType","params":{"network":{"get_co
         nnection_type":{}}}}]}}'
DEBUG    TPAP: starting SPAKE2+ handshake with 192.168.68.63                                        tpaptransport.py:194
DEBUG    Device 192.168.68.63 waiting 0.24726170001667924 seconds to send request                       httpclient.py:81
DEBUG    Posting to https://192.168.68.63:4433/                                                         httpclient.py:88
DEBUG    Giving up on 192.168.68.63 after 3 retries                                                 smartprotocol.py:153
DEBUG    Unable to connect with SmartCamProtocol: ("Device connection error: 192.168.68.63: Cannot       discover.py:687
         connect to host 192.168.68.63:4433 ssl:True [SSLCertVerificationError: (1, '[SSL:
         CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate
         (_ssl.c:1032)')]", ClientConnectorCertificateError(ConnectionKey(host='192.168.68.63',
         port=4433, is_ssl=True, ssl=<ssl.SSLContext object at 0x000001D85EE57BB0>, proxy=None,
         proxy_auth=None, proxy_headers_hash=None), SSLCertVerificationError(1, '[SSL:
         CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate
         (_ssl.c:1032)')))
Attempt to connect to 192.168.68.63 with SmartCamProtocol + TpapSmartCamTransport + SmartCamDevice + https failed
Unable to connect to 192.168.68.63

// $env:KASA_TEST_DISABLE_TPAP_TLS2_VERIFY="1"

DEBUG    Trying to connect with SmartProtocol                                                            discover.py:684
DEBUG    Using SmartDevice for SMART.TAPOPLUG                                                      device_factory.py:181
DEBUG    Initializing 192.168.68.63 of type <class 'kasa.smart.smartdevice.SmartDevice'>                   device.py:217
DEBUG    192.168.68.63 multi-request-batch-1-of-1 >>                                                smartprotocol.py:242
         '{"method":"multipleRequest","request_time_milis":1775055705781,"terminal_uuid":"igrsJU7Ue
         VMwW4NPxaJOPw==","params":{"requests":[{"method":"component_nego"},{"method":"get_device_i
         nfo"},{"method":"get_connect_cloud_state"}]}}'
DEBUG    TPAP: starting SPAKE2+ handshake with 192.168.68.63                                        tpaptransport.py:194
DEBUG    Posting to http://192.168.68.63/                                                               httpclient.py:88
DEBUG    Device 192.168.68.63 received an os error, enabling sequential request delay: Cannot connect  httpclient.py:136
         to host 192.168.68.63:80 ssl:<ssl.SSLContext object at 0x00000279A68777F0> [The remote
         computer refused the network connection]
DEBUG    Device 192.168.68.63 got a connection error, will retry 3 times: ('Device connection       smartprotocol.py:146
         error: 192.168.68.63: Cannot connect to host 192.168.68.63:80 ssl:<ssl.SSLContext object
         at 0x00000279A68777F0> [The remote computer refused the network connection]',
         ClientConnectorError(ConnectionKey(host='192.168.68.63', port=80, is_ssl=False,
         ssl=<ssl.SSLContext object at 0x00000279A68777F0>, proxy=None, proxy_auth=None,
         proxy_headers_hash=None), ConnectionRefusedError(22, 'The remote computer refused the
         network connection', None, 1225, None)))
DEBUG    192.168.68.63 multi-request-batch-1-of-1 >>                                                smartprotocol.py:242
         '{"method":"multipleRequest","request_time_milis":1775055707840,"terminal_uuid":"igrsJU7Ue
         VMwW4NPxaJOPw==","params":{"requests":[{"method":"component_nego"},{"method":"get_device_i
         nfo"},{"method":"get_connect_cloud_state"}]}}'
DEBUG    TPAP: starting SPAKE2+ handshake with 192.168.68.63                                        tpaptransport.py:194
DEBUG    Device 192.168.68.63 waiting 0.24704990000464022 seconds to send request                       httpclient.py:81
DEBUG    Posting to http://192.168.68.63/                                                               httpclient.py:88
DEBUG    192.168.68.63 multi-request-batch-1-of-1 >>                                                smartprotocol.py:242
         '{"method":"multipleRequest","request_time_milis":1775055710147,"terminal_uuid":"igrsJU7Ue
         VMwW4NPxaJOPw==","params":{"requests":[{"method":"component_nego"},{"method":"get_device_i
         nfo"},{"method":"get_connect_cloud_state"}]}}'
DEBUG    TPAP: starting SPAKE2+ handshake with 192.168.68.63                                        tpaptransport.py:194
DEBUG    Device 192.168.68.63 waiting 0.24718130001565441 seconds to send request                       httpclient.py:81
DEBUG    Posting to http://192.168.68.63/                                                               httpclient.py:88
DEBUG    192.168.68.63 multi-request-batch-1-of-1 >>                                                smartprotocol.py:242
         '{"method":"multipleRequest","request_time_milis":1775055712473,"terminal_uuid":"igrsJU7Ue
         VMwW4NPxaJOPw==","params":{"requests":[{"method":"component_nego"},{"method":"get_device_i
         nfo"},{"method":"get_connect_cloud_state"}]}}'
DEBUG    TPAP: starting SPAKE2+ handshake with 192.168.68.63                                        tpaptransport.py:194
DEBUG    Device 192.168.68.63 waiting 0.24733119999291375 seconds to send request                       httpclient.py:81
DEBUG    Posting to http://192.168.68.63/                                                               httpclient.py:88
DEBUG    Giving up on 192.168.68.63 after 3 retries                                                 smartprotocol.py:153
DEBUG    Unable to connect with SmartProtocol: ('Device connection error: 192.168.68.63: Cannot connect  discover.py:687
         to host 192.168.68.63:80 ssl:<ssl.SSLContext object at 0x00000279A68D3070> [The remote computer
         refused the network connection]', ClientConnectorError(ConnectionKey(host='192.168.68.63',
         port=80, is_ssl=False, ssl=<ssl.SSLContext object at 0x00000279A68D3070>, proxy=None,
         proxy_auth=None, proxy_headers_hash=None), ConnectionRefusedError(22, 'The remote computer
         refused the network connection', None, 1225, None)))
Attempt to connect to 192.168.68.63 with SmartProtocol + TpapTransport + SmartDevice + http failed
DEBUG    Trying to connect with SmartCamProtocol                                                         discover.py:684
DEBUG    Using SmartCamDevice for SMART.IPCAMERA                                                   device_factory.py:181
DEBUG    Initializing 192.168.68.63 of type <class 'kasa.smartcam.smartcamdevice.SmartCamDevice'>          device.py:217
DEBUG    192.168.68.63 multi-request-batch-1-of-1 >>                                                smartprotocol.py:242
         '{"method":"multipleRequest","request_time_milis":1775055714786,"terminal_uuid":"OrBsXIYGW
         7SdLpP5pOmylQ==","params":{"requests":[{"method":"getDeviceInfo","params":{"device_info":{
         "name":["basic_info","info"]}}},{"method":"getAppComponentList","params":{"app_component":
         {"name":"app_component_list"}}},{"method":"getConnectionType","params":{"network":{"get_co
         nnection_type":{}}}}]}}'
DEBUG    TPAP: starting SPAKE2+ handshake with 192.168.68.63                                        tpaptransport.py:194
DEBUG    Posting to https://192.168.68.63:4433/                                                         httpclient.py:88
WARNING  TPAP TLS2 certificate verification disabled for 192.168.68.63 via                         tpaptransport.py:1378
         KASA_TEST_DISABLE_TPAP_TLS2_VERIFY
DEBUG    Posting to https://192.168.68.63:4433/                                                         httpclient.py:88
DEBUG    Posting to https://192.168.68.63:4433/                                                         httpclient.py:88
WARNING  Device 192.168.68.63 received unknown error code: -2203                                    tpaptransport.py:294
DEBUG    TPAP: SPAKE2+ candidate 1/2 failed for 192.168.68.63: TPAP pake_share failed:              tpaptransport.py:357
         192.168.68.63: INTERNAL_UNKNOWN_ERROR(-100000) (error_code=INTERNAL_UNKNOWN_ERROR)
DEBUG    Posting to https://192.168.68.63:4433/                                                         httpclient.py:88
DEBUG    Posting to https://192.168.68.63:4433/                                                         httpclient.py:88
WARNING  Device 192.168.68.63 received unknown error code: -2203                                    tpaptransport.py:294
DEBUG    TPAP: all password-based SPAKE2+ smartcam candidates failed for 192.168.68.63              tpaptransport.py:367
DEBUG    Unable to query the device: 192.168.68.63, not retrying: TPAP pake_share failed:           smartprotocol.py:192
         192.168.68.63: INTERNAL_UNKNOWN_ERROR(-100000) (error_code=INTERNAL_UNKNOWN_ERROR)
DEBUG    Unable to connect with SmartCamProtocol: TPAP pake_share failed: 192.168.68.63:                 discover.py:687
         INTERNAL_UNKNOWN_ERROR(-100000) (error_code=INTERNAL_UNKNOWN_ERROR)
Attempt to connect to 192.168.68.63 with SmartCamProtocol + TpapSmartCamTransport + SmartCamDevice + https failed
DEBUG    Trying to connect with SmartProtocol                                                            discover.py:684
DEBUG    Using SmartDevice for SMART.TAPOROBOVAC                                                   device_factory.py:181
DEBUG    Initializing 192.168.68.63 of type <class 'kasa.smart.smartdevice.SmartDevice'>                   device.py:217
DEBUG    192.168.68.63 multi-request-batch-1-of-1 >>                                                smartprotocol.py:242
         '{"method":"multipleRequest","request_time_milis":1775055716091,"terminal_uuid":"kbSG89GYS
         c2qkCjr55cwWg==","params":{"requests":[{"method":"component_nego"},{"method":"get_device_i
         nfo"},{"method":"get_connect_cloud_state"}]}}'
DEBUG    TPAP: starting SPAKE2+ handshake with 192.168.68.63                                        tpaptransport.py:194
DEBUG    Posting to https://192.168.68.63:4433/                                                         httpclient.py:88
WARNING  TPAP TLS2 certificate verification disabled for 192.168.68.63 via                         tpaptransport.py:1378
         KASA_TEST_DISABLE_TPAP_TLS2_VERIFY
DEBUG    Posting to https://192.168.68.63:4433/                                                         httpclient.py:88
WARNING  Device 192.168.68.63 received unknown error code: -2203                                    tpaptransport.py:294
DEBUG    Unable to query the device: 192.168.68.63, not retrying: TPAP pake_register failed:        smartprotocol.py:192
         192.168.68.63: INTERNAL_UNKNOWN_ERROR(-100000) (error_code=INTERNAL_UNKNOWN_ERROR)
DEBUG    Unable to connect with SmartProtocol: TPAP pake_register failed: 192.168.68.63:                 discover.py:687
         INTERNAL_UNKNOWN_ERROR(-100000) (error_code=INTERNAL_UNKNOWN_ERROR)
Attempt to connect to 192.168.68.63 with SmartProtocol + TpapTransport + SmartDevice + https failed
Unable to connect to 192.168.68.63

@TA2k
Copy link
Copy Markdown

TA2k commented Apr 1, 2026

Hi @ZeliardM, great work on the TPAP/SPAKE2+ implementation!

I've been working on a Node.js (ioBroker) adapter and successfully connected to a P100 (FW 1.4.3, HW 2.0, tls=0, pake:[2], HTTP port 80) using your code as reference. A few findings that might help:

1. Credential hashing for passwd_id=2 is double-hashed (tls=0 devices)

For smartcam auth with pake:[2], _iter_spake_candidate_secrets() returns md5(password) and sha256(password) as candidates. Then _resolve_spake_credentials()_build_credentials() with passwd_id=2 applies sha1() on top, producing sha1(md5(password)).

The device expects sha1(raw_password). Fix: include the raw password in the candidate list:

# In _iter_spake_candidate_secrets, for pake:[2]:
candidates = [password, self._md5_hex(password), self._sha256_hex_upper(password)]

2. Username "admin" works for all plugs

P100/P110 plugs with pake:[2] expect md5("admin") as the pake_register username, regardless of whether smartcam auth is detected. Using md5(email) returns error -2203. The SmartCam path already handles this correctly.

3. Missing extra_crypt type: password_sha_with_salt

The Tapo APK (3.17.803) defines a third extra_crypt.type besides password_shadow and password_authkey:

  • password_sha_with_salt: SHA256( name + base64decode(sha_salt) + password ) hex-encoded
    • name is "admin" when sha_name == 0, otherwise "user"
    • sha_salt is a base64-encoded salt from extra_crypt.params

This type is not handled in the current implementation and would fall through silently.

4. passcode_type should vary by pake version

The APK sets passcode_type based on the pake list from discovery:

  • pake contains 0 → "default_userpw"
  • pake contains 2 or 5 → "userpw"
  • pake contains 3 → "shared_token"

The current implementation always sends "default_userpw".


Verified fixes 1+2 against a real P100 device — handshake completes and device_info is returned. Likely also fixes @Slaymish's L535E (tls=0, pake:[2]) which shows the same -2203 error.

@ZeliardM
Copy link
Copy Markdown
Contributor Author

ZeliardM commented Apr 1, 2026

Thanks! I'll look through all of this. I've got a bigger PR that I'm working on right now for improving the discovery handling and implementing a lot of missing device types and transports. It's taking a lot right now so I'm not sure when all of this will actually make it out.


@staticmethod
def _sha256_hex_upper(value: str) -> str:
return hashlib.sha256(value.encode()).hexdigest().upper() # noqa: S324

Check failure

Code scanning / CodeQL

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

Sensitive data (password)
is used in a hashing algorithm (SHA256) that is insecure for password hashing, since it is not a computationally expensive hash function.
Sensitive data (password)
is used in a hashing algorithm (SHA256) that is insecure for password hashing, since it is not a computationally expensive hash function.
@ZeliardM
Copy link
Copy Markdown
Contributor Author

ZeliardM commented Apr 9, 2026

@danieyal @TA2k @Slaymish Ok everyone, I have pushed some updates to the transport. Pull down the latest commits and let me know. Thanks!

@danieyal
Copy link
Copy Markdown

@ZeliardM working fine here

DEBUG Trying to connect with SmartProtocol discover.py:684
DEBUG Using SmartDevice for SMART.TAPOROBOVAC device_factory.py:180
DEBUG Initializing 192.168.68.63 of type <class 'kasa.smart.smartdevice.SmartDevice'> device.py:217
DEBUG 192.168.68.63 multi-request-batch-1-of-1 >> smartprotocol.py:242
'{"method":"multipleRequest","request_time_milis":1775828146006,"terminal_uuid":"7JLhp3UB0
qxwRifq4FDxlQ==","params":{"requests":[{"method":"component_nego"},{"method":"get_device_i
nfo"},{"method":"get_connect_cloud_state"}]}}'
DEBUG TPAP: starting handshake with 192.168.68.63 tpaptransport.py:181
DEBUG Posting to https://192.168.68.63:4433/ httpclient.py:88
DEBUG Posting to https://192.168.68.63:4433/ httpclient.py:88
DEBUG Posting to https://192.168.68.63:4433/ httpclient.py:88
DEBUG TPAP: handshake complete with 192.168.68.63 tpaptransport.py:189
DEBUG Posting to https://192.168.68.63:4433/stok=08yblnTd7GD0D47fctKulQ9AQEcvz8/ds

..................

DEBUG Device 192.168.68.63 with connection params True took 1.45 seconds to update device_factory.py:96
Attempt to connect to 192.168.68.63 with SmartProtocol + TpapTransport + SmartDevice + https succeeded
DEBUG Found working protocol SmartProtocol discover.py:699
Managed to connect, cli options to connect are:
--device-family SMART.TAPOROBOVAC --encrypt-type TPAP --https

@ZeliardM
Copy link
Copy Markdown
Contributor Author

@danieyal That's great! Glad to hear it.

@tuck-ski
Copy link
Copy Markdown

I have a Tapo H110C(JP), a Smart IR & IoT Hub that I was hoping to add support for myself. I was able to discover the device with kasa discover normally, but in order to test the IR capabilities through the app I needed to upgrade the firmware. After upgrading to 1.4.4 it started using the TPAP protocol, and I needed to include code from this PR in order to authenticate. However, after updating to the latest changes I am getting an error:

> uv run kasa -d --target 192.168.0.26
warning: The `tool.uv.dev-dependencies` field (used in `pyproject.toml`) is deprecated and will be removed in a future release; use `dependency-groups.dev` instead
No host name given, trying discovery..
Discovering devices on 192.168.0.26 for 10 seconds
DEBUG    [DISCOVERY] 192.168.0.26 >> {'system': {'get_sysinfo': {}}}                                                                                                                                                          discover.py:327
DEBUG    Waiting 10 seconds for responses...                                                                                                                                                                                 discover.py:503
DEBUG    Using SmartDevice for SMART.TAPOHUB                                                                                                                                                                           device_factory.py:180
DEBUG    Finding protocol for 192.168.0.26                                                                                                                                                                              device_factory.py:195
DEBUG    Finding protocol for DeviceFamily.SmartTapoHub                                                                                                                                                                device_factory.py:198
DEBUG    Finding transport for SMART.TPAP                                                                                                                                                                              device_factory.py:237
DEBUG    [DISCOVERY] 192.168.0.26 << {'error_code': 0,                                                                                                                                                                        discover.py:927
          'result': {'device_id': 'REDACTED_13f94a2bc0c8f7287817554',                                                                                                                                                                       
                     'device_model': 'H110C(JP)',                                                                                                                                                                                           
                     'device_type': 'SMART.TAPOHUB',                                                                                                                                                                                        
                     'factory_default': False,                                                                                                                                                                                              
                     'ip': '192.168.0.26',                                                                                                                                                                                                   
                     'is_support_iot_cloud': True,                                                                                                                                                                                          
                     'mac': 'CC-BA-BD-00-00-00',                                                                                                                                                                                            
                     'mgt_encrypt_schm': {'encrypt_type': 'TPAP',                                                                                                                                                                           
                                          'http_port': 80,                                                                                                                                                                                  
                                          'is_support_https': False,                                                                                                                                                                        
                                          'lv': 2},                                                                                                                                                                                         
                     'obd_src': 'tplink',                                                                                                                                                                                                   
                     'owner': 'REDACTED_19D0B628697D38CB874CD17',                                                                                                                                                                           
                     'protocol_version': 1,                                                                                                                                                                                                 
                     'tpap': {'dac': 1, 'noc': 1, 'pake': [2], 'port': 80, 'tls': 0},                                                                                                                                                       
                     'tpap_preferred': True}}                                                                                                                                                                                               
DEBUG    Initializing 192.168.0.26 of type <class 'kasa.smart.smartdevice.SmartDevice'>                                                                                                                                         device.py:217
DEBUG    192.168.0.26 multi-request-batch-1-of-1 >>                                                                                                                                                                      smartprotocol.py:242
         '{"method":"multipleRequest","request_time_milis":1776385213155,"terminal_uuid":"Iu5GgXzgH3F9unhhVs7U9Q==","params":{"requests":[{"method":"component_nego"},{"method":"get_device_info"},{"method":"get_conne                     
         ct_cloud_state"}]}}'                                                                                                                                                                                                               
DEBUG    TPAP: starting handshake with 192.168.0.26                                                                                                                                                                      tpaptransport.py:181
DEBUG    Posting to http://192.168.0.26/                                                                                                                                                                                     httpclient.py:88
DEBUG    Posting to http://192.168.0.26/                                                                                                                                                                                     httpclient.py:88
DEBUG    Posting to http://192.168.0.26/                                                                                                                                                                                     httpclient.py:88
WARNING  Device 192.168.0.26 received unknown error code: -2203                                                                                                                                                          tpaptransport.py:261
DEBUG    TPAP: credential candidate 1/2 failed for 192.168.0.26: TPAP pake_share failed for 192.168.0.26: INTERNAL_UNKNOWN_ERROR(-100000) (error_code=INTERNAL_UNKNOWN_ERROR)                                             tpaptransport.py:339
DEBUG    Posting to http://192.168.0.26/                                                                                                                                                                                     httpclient.py:88
DEBUG    Posting to http://192.168.0.26/                                                                                                                                                                                     httpclient.py:88
WARNING  Device 192.168.0.26 received unknown error code: -2203                                                                                                                                                          tpaptransport.py:261
DEBUG    TPAP: all password-based camera candidates failed for 192.168.0.26                                                                                                                                              tpaptransport.py:349
DEBUG    Unable to query the device: 192.168.0.26, not retrying: TPAP pake_share failed for 192.168.0.26: INTERNAL_UNKNOWN_ERROR(-100000) (error_code=INTERNAL_UNKNOWN_ERROR)                                             smartprotocol.py:192
Raised error: TPAP pake_share failed for 192.168.0.26: INTERNAL_UNKNOWN_ERROR(-100000) (error_code=INTERNAL_UNKNOWN_ERROR)
Traceback (most recent call last):
  File "python-kasa/.venv/bin/kasa", line 10, in <module>
    sys.exit(cli())
             ~~~^^
  File "python-kasa/kasa/cli/common.py", line 282, in __call__
    asyncio.run(self.main(*args, **kwargs))
    ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/user/.local/share/uv/python/cpython-3.13.5-linux-x86_64-gnu/lib/python3.13/asyncio/runners.py", line 195, in run
    return runner.run(main)
           ~~~~~~~~~~^^^^^^
  File "/home/user/.local/share/uv/python/cpython-3.13.5-linux-x86_64-gnu/lib/python3.13/asyncio/runners.py", line 118, in run
    return self._loop.run_until_complete(task)
           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^
  File "/home/user/.local/share/uv/python/cpython-3.13.5-linux-x86_64-gnu/lib/python3.13/asyncio/base_events.py", line 725, in run_until_complete
    return future.result()
           ~~~~~~~~~~~~~^^
  File "python-kasa/.venv/lib/python3.13/site-packages/asyncclick/core.py", line 1126, in main
    rv = await self.invoke(ctx)
         ^^^^^^^^^^^^^^^^^^^^^^
  File "python-kasa/kasa/cli/common.py", line 270, in invoke
    _handle_exception(self._debug, exc)
    ~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^
  File "python-kasa/kasa/cli/common.py", line 268, in invoke
    return await super().invoke(ctx)
           ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "python-kasa/.venv/lib/python3.13/site-packages/asyncclick/core.py", line 1728, in invoke
    rv = await super().invoke(ctx)
         ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "python-kasa/.venv/lib/python3.13/site-packages/asyncclick/core.py", line 1496, in invoke
    return await ctx.invoke(self.callback, **ctx.params)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "python-kasa/.venv/lib/python3.13/site-packages/asyncclick/core.py", line 829, in invoke
    rv = await rv
         ^^^^^^^^
  File "python-kasa/kasa/cli/main.py", line 301, in cli
    return await invoke_subcommand(discover, ctx)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "python-kasa/kasa/cli/common.py", line 114, in invoke_subcommand
    return await command.invoke(sub_ctx)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "python-kasa/.venv/lib/python3.13/site-packages/asyncclick/core.py", line 1728, in invoke
    rv = await super().invoke(ctx)
         ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "python-kasa/.venv/lib/python3.13/site-packages/asyncclick/core.py", line 1496, in invoke
    return await ctx.invoke(self.callback, **ctx.params)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "python-kasa/.venv/lib/python3.13/site-packages/asyncclick/core.py", line 829, in invoke
    rv = await rv
         ^^^^^^^^
  File "python-kasa/kasa/cli/discover.py", line 41, in discover
    return await ctx.invoke(detail)
           ^^^^^^^^^^^^^^^^^^^^^^^^
  File "python-kasa/.venv/lib/python3.13/site-packages/asyncclick/core.py", line 829, in invoke
    rv = await rv
         ^^^^^^^^
  File "python-kasa/kasa/cli/discover.py", line 102, in detail
    discovered = await _discover(
                 ^^^^^^^^^^^^^^^^
    ...<3 lines>...
    )
    ^
  File "python-kasa/kasa/cli/discover.py", line 227, in _discover
    discovered_devices = await Discover.discover(
                         ^^^^^^^^^^^^^^^^^^^^^^^^
    ...<8 lines>...
    )
    ^
  File "python-kasa/kasa/discover.py", line 508, in discover
    raise ex
  File "python-kasa/kasa/discover.py", line 504, in discover
    await protocol.wait_for_discovery_to_complete()
  File "python-kasa/kasa/discover.py", line 302, in wait_for_discovery_to_complete
    await asyncio.gather(*self.callback_tasks)
  File "python-kasa/kasa/cli/discover.py", line 89, in print_discovered
    await dev.update()
  File "python-kasa/kasa/smart/smartdevice.py", line 271, in update
    await self._negotiate()
  File "python-kasa/kasa/smart/smartdevice.py", line 218, in _negotiate
    resp = await self.protocol.query(initial_query)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "python-kasa/kasa/protocols/smartprotocol.py", line 136, in query
    return await self._query(request, retry_count)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "python-kasa/kasa/protocols/smartprotocol.py", line 197, in _query
    raise ex
  File "python-kasa/kasa/protocols/smartprotocol.py", line 141, in _query
    return await self._execute_query(
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
        request, retry_count=retry, iterate_list_pages=True
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    )
    ^
  File "python-kasa/kasa/protocols/smartprotocol.py", line 329, in _execute_query
    return await self._execute_multiple_query(
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        request, retry_count, iterate_list_pages
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    )
    ^
  File "python-kasa/kasa/protocols/smartprotocol.py", line 248, in _execute_multiple_query
    response_step = await self._transport.send(smart_request)
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "python-kasa/kasa/transports/tpaptransport.py", line 1334, in send
    return await self._send_once(request)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "python-kasa/kasa/transports/tpaptransport.py", line 1349, in _send_once
    await self._encryption_session.perform_handshake()
  File "python-kasa/kasa/transports/tpaptransport.py", line 187, in perform_handshake
    await self._perform_auth_handshake()
  File "python-kasa/kasa/transports/tpaptransport.py", line 353, in _perform_auth_handshake
    raise last_error
  File "python-kasa/kasa/transports/tpaptransport.py", line 331, in _perform_auth_handshake
    share_result = await self._login(share_params, step_name="pake_share")
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "python-kasa/kasa/transports/tpaptransport.py", line 244, in _login
    self._handle_response_error_code(data, step_name)
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^
  File "python-kasa/kasa/transports/tpaptransport.py", line 280, in _handle_response_error_code
    raise DeviceError(full, error_code=error_code)
kasa.exceptions.DeviceError: TPAP pake_share failed for 192.168.0.26: INTERNAL_UNKNOWN_ERROR(-100000) (error_code=INTERNAL_UNKNOWN_ERROR)


Reverting to the code that worked before (directly before the Complete re-write, using commit 18736c2) seems to authenticate correctly. (Ignoring the unknown child device, which is currently not supported)

warning: The `tool.uv.dev-dependencies` field (used in `pyproject.toml`) is deprecated and will be removed in a future release; use `dependency-groups.dev` instead
No host name given, trying discovery..
Discovering devices on 192.168.0.26 for 10 seconds
DEBUG    [DISCOVERY] 192.168.0.26 >> {'system': {'get_sysinfo': {}}}                                                                                                                                                          discover.py:327
DEBUG    Waiting 10 seconds for responses...                                                                                                                                                                                 discover.py:503
DEBUG    Using SmartDevice for SMART.TAPOHUB                                                                                                                                                                           device_factory.py:180
DEBUG    Finding protocol for 192.168.0.26                                                                                                                                                                              device_factory.py:195
DEBUG    Finding protocol for DeviceFamily.SmartTapoHub                                                                                                                                                                device_factory.py:198
DEBUG    Finding transport for SMART.TPAP                                                                                                                                                                              device_factory.py:227
DEBUG    [DISCOVERY] 192.168.0.26 << {'error_code': 0,                                                                                                                                                                        discover.py:927
          'result': {'device_id': 'REDACTED_13f94a2bc0c8f7287817554',                                                                                                                                                                       
                     'device_model': 'H110C(JP)',                                                                                                                                                                                           
                     'device_type': 'SMART.TAPOHUB',                                                                                                                                                                                        
                     'factory_default': False,                                                                                                                                                                                              
                     'ip': '192.168.0.26',                                                                                                                                                                                                   
                     'is_support_iot_cloud': True,                                                                                                                                                                                          
                     'mac': 'CC-BA-BD-00-00-00',                                                                                                                                                                                            
                     'mgt_encrypt_schm': {'encrypt_type': 'TPAP',                                                                                                                                                                           
                                          'http_port': 80,                                                                                                                                                                                  
                                          'is_support_https': False,                                                                                                                                                                        
                                          'lv': 2},                                                                                                                                                                                         
                     'obd_src': 'tplink',                                                                                                                                                                                                   
                     'owner': 'REDACTED_19D0B628697D38CB874CD17',                                                                                                                                                                           
                     'protocol_version': 1,                                                                                                                                                                                                 
                     'tpap': {'dac': 1, 'noc': 1, 'pake': [2], 'port': 80, 'tls': 0},                                                                                                                                                       
                     'tpap_preferred': True}}                                                                                                                                                                                               
DEBUG    Initializing 192.168.0.26 of type <class 'kasa.smart.smartdevice.SmartDevice'>                                                                                                                                         device.py:217
DEBUG    192.168.0.26 multi-request-batch-1-of-1 >>                                                                                                                                                                      smartprotocol.py:242
         '{"method":"multipleRequest","request_time_milis":1776385320775,"terminal_uuid":"E7J4hhHMTk+cInnY9oXxkw==","params":{"requests":[{"method":"component_nego"},{"method":"get_device_info"},{"method":"get_conne                     
         ct_cloud_state"}]}}'                                                                                                                                                                                                               
DEBUG    Posting to http://192.168.0.26/                                                                                                                                                                                     httpclient.py:88
DEBUG    Starting new HTTPS connection (1): n-wap.i.tplinkcloud.com:443                                                                                                                                               connectionpool.py:1049
DEBUG    https://n-wap.i.tplinkcloud.com:443 "POST / HTTP/1.1" 200 230                                                                                                                                                 connectionpool.py:544
DEBUG    Starting new HTTPS connection (1): n-aps1-wap.i.tplinkcloud.com:443                                                                                                                                          connectionpool.py:1049
DEBUG    https://n-aps1-wap.i.tplinkcloud.com:443 "POST /api/v2/common/getAppServiceUrlById HTTP/1.1" 200 179                                                                                                          connectionpool.py:544
DEBUG    Starting new HTTPS connection (1): use1-cvm-api.i.tplinkcloud.com:443                                                                                                                                        connectionpool.py:1049
DEBUG    https://use1-cvm-api.i.tplinkcloud.com:443 "POST /v1/certificate/noc/app/apply HTTP/1.1" 200 None                                                                                                             connectionpool.py:544
DEBUG    Posting to http://192.168.0.26/                                                                                                                                                                                     httpclient.py:88
DEBUG    Posting to http://192.168.0.26/                                                                                                                                                                                     httpclient.py:88
DEBUG    Authenticator: established session via NOC                                                                                                                                                                    tpaptransport.py:1193
DEBUG    Posting to http://192.168.0.26/stok=tiWTCI0tEL27drb37Ojx3VtEL27drb/ds                                                                                                                                               httpclient.py:88
DEBUG    192.168.0.26 multi-request-batch-1-of-1 << {'error_code': 0,                                                                                                                                                    smartprotocol.py:254
          'result': {'responses': [{'error_code': 0,                                                                                                                                                                                        
                                    'method': 'component_nego',                                                                                                                                                                             
                                    'result': {'component_list': [{'id': 'device',                                                                                                                                                          
                                                                   'ver_code': 2},                                                                                                                                                          
                                                                  {'id': 'firmware',                                                                                                                                                        
                                                                   'ver_code': 2},                                                                                                                                                          
                                                                  {'id': 'quick_setup',                                                                                                                                                     
                                                                   'ver_code': 3},                                                                                                                                                          
                                                                  {'id': 'inherit',                                                                                                                                                         
                                                                   'ver_code': 1},                                                                                                                                                          
                                                                  {'id': 'time',                                                                                                                                                            
                                                                   'ver_code': 1},                                                                                                                                                          
                                                                  {'id': 'wireless',                                                                                                                                                        
                                                                   'ver_code': 1},                                                                                                                                                          
                                                                  {'id': 'account',                                                                                                                                                         
                                                                   'ver_code': 1},                                                                                                                                                          
                                                                  {'id': 'synchronize',                                                                                                                                                     
                                                                   'ver_code': 1},                                                                                                                                                          
                                                                  {'id': 'sunrise_sunset',                                                                                                                                                  
                                                                   'ver_code': 1},                                                                                                                                                          
                                                                  {'id': 'led',                                                                                                                                                             
                                                                   'ver_code': 1},                                                                                                                                                          
                                                                  {'id': 'cloud_connect',                                                                                                                                                   
                                                                   'ver_code': 1},                                                                                                                                                          
                                                                  {'id': 'iot_cloud',                                                                                                                                                       
                                                                   'ver_code': 1},                                                                                                                                                          
                                                                  {'id': 'child_device',                                                                                                                                                    
                                                                   'ver_code': 1},                                                                                                                                                          
                                                                  {'id': 'child_quick_setup',                                                                                                                                               
                                                                   'ver_code': 1},                                                                                                                                                          
                                                                  {'id': 'child_inherit',                                                                                                                                                   
                                                                   'ver_code': 1},                                                                                                                                                          
                                                                  {'id': 'control_child',                                                                                                                                                   
                                                                   'ver_code': 1},                                                                                                                                                          
                                                                  {'id': 'alarm',                                                                                                                                                           
                                                                   'ver_code': 1},                                                                                                                                                          
                                                                  {'id': 'device_load',                                                                                                                                                     
                                                                   'ver_code': 1},                                                                                                                                                          
                                                                  {'id': 'device_local_time',                                                                                                                                               
                                                                   'ver_code': 1},                                                                                                                                                          
                                                                  {'id': 'alarm_logs',                                                                                                                                                      
                                                                   'ver_code': 1},                                                                                                                                                          
                                                                  {'id': 'localSmart',                                                                                                                                                      
                                                                   'ver_code': 2},                                                                                                                                                          
                                                                  {'id': 'matter',                                                                                                                                                          
                                                                   'ver_code': 3},                                                                                                                                                          
                                                                  {'id': 'chime',                                                                                                                                                           
                                                                   'ver_code': 1},                                                                                                                                                          
                                                                  {'id': 'ir_remote',                                                                                                                                                       
                                                                   'ver_code': 1},                                                                                                                                                          
                                                                  {'id': 'ir_customise_icon',                                                                                                                                               
                                                                   'ver_code': 1},                                                                                                                                                          
                                                                  {'id': 'tpap',                                                                                                                                                            
                                                                   'ver_code': 1},                                                                                                                                                          
                                                                  {'id': 'noc',                                                                                                                                                             
                                                                   'ver_code': 1}]}},                                                                                                                                                       
                                   {'error_code': 0,                                                                                                                                                                                        
                                    'method': 'get_device_info',                                                                                                                                                                            
                                    'result': {'avatar': 'hub_h110',                                                                                                                                                                        
                                               'device_id': 'REDACTED_97AD1150C866F8142E2DD9B24A2A536',                                                                                                                                     
                                               'fw_id': 'REDACTED_00000000000000000000000',                                                                                                                                                 
                                               'fw_ver': '1.4.4 Build 251031 Rel.111523',                                                                                                                                                   
                                               'has_set_location_info': False,                                                                                                                                                              
                                               'hw_id': 'REDACTED_03FE3ADF33AA282DA816E6E',                                                                                                                                                 
                                               'hw_ver': '1.0',                                                                                                                                                                             
                                               'in_alarm': False,                                                                                                                                                                           
                                               'in_alarm_source': '',                                                                                                                                                                       
                                               'ip': '192.168.0.26',                                                                                                                                                                         
                                               'lang': '',                                                                                                                                                                                  
                                               'latitude': 0,                                                                                                                                                                               
                                               'longitude': 0,                                                                                                                                                                              
                                               'mac': 'CC-BA-BD-00-00-00',                                                                                                                                                                  
                                               'model': 'H110',                                                                                                                                                                             
                                               'nickname': 'I01BU0tFRF9OQU1FIw==',                                                                                                                                                          
                                               'oem_id': 'REDACTED_B8FC58E23638A20035B7CC7',                                                                                                                                                
                                               'overheated': False,                                                                                                                                                                         
                                               'region': 'Asia/Tokyo',                                                                                                                                                                      
                                               'rssi': -31,                                                                                                                                                                                 
                                               'signal_level': 3,                                                                                                                                                                           
                                               'specs': 'JP',                                                                                                                                                                               
                                               'ssid': 'I01BU0tFRF9TU0lEIw==',                                                                                                                                                              
                                               'subg_phyid': 'f920p9',                                                                                                                                                                      
                                               'time_diff': 540,                                                                                                                                                                            
                                               'type': 'SMART.TAPOHUB'}},                                                                                                                                                                   
                                   {'error_code': 0,                                                                                                                                                                                        
                                    'method': 'get_connect_cloud_state',                                                                                                                                                                    
                                    'result': {'status': 0}}]}}                                                                                                                                                                             
DEBUG    192.168.0.26 multi-request-batch-1-of-1 >>                                                                                                                                                                      smartprotocol.py:242
         '{"method":"multipleRequest","request_time_milis":1776385324396,"terminal_uuid":"E7J4hhHMTk+cInnY9oXxkw==","params":{"requests":[{"method":"get_child_device_component_list"},{"method":"get_child_device_list                     
         "}]}}'                                                                                                                                                                                                                             
DEBUG    Posting to http://192.168.0.26/stok=tiWTCI0tEL27drb37Ojx3VtEL27drb/ds                                                                                                                                               httpclient.py:88
DEBUG    192.168.0.26 multi-request-batch-1-of-1 << {'error_code': 0,                                                                                                                                                    smartprotocol.py:254
          'result': {'responses': [{'error_code': 0,                                                                                                                                                                                        
                                    'method': 'get_child_device_component_list',                                                                                                                                                            
                                    'result': {'child_component_list': [{'component_list': [{'id': 'device',                                                                                                                                
                                                                                             'ver_code': 2},                                                                                                                                
                                                                                            {'id': 'localSmart',                                                                                                                            
                                                                                             'ver_code': 1},                                                                                                                                
                                                                                            {'id': 'iot_cloud',                                                                                                                             
                                                                                             'ver_code': 1}],                                                                                                                               
                                                                         'device_id': 'REDACTED_97AD1150C866F8142E2DD9B24A2A536030B0002'}],                                                                                                 
                                               'start_index': 0,                                                                                                                                                                            
                                               'sum': 1}},                                                                                                                                                                                  
                                   {'error_code': 0,                                                                                                                                                                                        
                                    'method': 'get_child_device_list',                                                                                                                                                                      
                                    'result': {'child_device_list': [{'avatar': '',                                                                                                                                                         
                                                                      'bind_count': 0,                                                                                                                                                      
                                                                      'category': 'ir.remote',                                                                                                                                              
                                                                      'copy_device_id': '',                                                                                                                                                 
                                                                      'customize_key_sum': 1,                                                                                                                                               
                                                                      'device_id': 'REDACTED_97AD1150C866F8142E2DD9B24A2A536030B0002',                                                                                                      
                                                                      'downloaded_key_sum': 2,                                                                                                                                              
                                                                      'fw_ver': '',                                                                                                                                                         
                                                                      'hw_id': '',                                                                                                                                                          
                                                                      'hw_ver': '',                                                                                                                                                         
                                                                      'isThirdPartySub': True,                                                                                                                                              
                                                                      'key_list': [{'ac_status': 'P0_M0_T26_S0_D0',                                                                                                                         
                                                                                    'display_name': '44Kq44Oz',                                                                                                                             
                                                                                    'id': 5907,                                                                                                                                             
                                                                                    'name': '2X2GRTPG',                                                                                                                                     
                                                                                    'pwm': 24},                                                                                                                                             
                                                                                   {'ac_status': 'P0_M0_T26_S0_D0',                                                                                                                         
                                                                                    'display_name': '44Kq44OV',                                                                                                                             
                                                                                    'id': 5912,                                                                                                                                             
                                                                                    'name': 'k66777kO',                                                                                                                                     
                                                                                    'pwm': 24},                                                                                                                                             
                                                                                   {'ac_status': 'P0_M0_T26_S0_D0',                                                                                                                         
                                                                                    'display_name': 'bWF4',                                                                                                                                 
                                                                                    'icon': 'Brightness',                                                                                                                                   
                                                                                    'id': -1,                                                                                                                                               
                                                                                    'name': 'xt6GQ976',                                                                                                                                     
                                                                                    'order': 1,                                                                                                                                             
                                                                                    'pwm': 24,                                                                                                                                              
                                                                                    'type': ''}],                                                                                                                                           
                                                                      'key_sum': 3,                                                                                                                                                         
                                                                      'lastOnboardingTimestamp': 1773929940,                                                                                                                                
                                                                      'mac': 'A53603000000',                                                                                                                                                
                                                                      'model': 'Light',                                                                                                                                                     
                                                                      'nickname': 'I01BU0tFRF9OQU1FIw==',                                                                                                                                   
                                                                      'oemId': '',                                                                                                                                                          
                                                                      'on': 0,                                                                                                                                                              
                                                                      'parent_device_id': 'REDACTED_97AD1150C866F8142E2DD9B24A2A536',                                                                                                       
                                                                      'remote_id': 0,                                                                                                                                                       
                                                                      'remote_type': 1,                                                                                                                                                     
                                                                      'type': 'SMART.TAPOREMOTE'}],                                                                                                                                         
                                               'start_index': 0,                                                                                                                                                                            
                                               'sum': 1}}]}}                                                                                                                                                                                
DEBUG    Device 192.168.0.26, found required alarm, adding Alarm to modules.                                                                                                                                               smartdevice.py:429
DEBUG    Device 192.168.0.26, found required child_device, adding ChildDevice to modules.                                                                                                                                  smartdevice.py:429
DEBUG    Device 192.168.0.26, found required child_quick_setup, adding ChildSetup to modules.                                                                                                                              smartdevice.py:429
DEBUG    Device 192.168.0.26, found required cloud_connect, adding Cloud to modules.                                                                                                                                       smartdevice.py:429
DEBUG    Device 192.168.0.26, found required device, adding DeviceModule to modules.                                                                                                                                       smartdevice.py:429
DEBUG    Device 192.168.0.26, found required firmware, adding Firmware to modules.                                                                                                                                         smartdevice.py:429
DEBUG    Device 192.168.0.26, found required led, adding Led to modules.                                                                                                                                                   smartdevice.py:429
DEBUG    Device 192.168.0.26, found required matter, adding Matter to modules.                                                                                                                                             smartdevice.py:429
DEBUG    Device 192.168.0.26, found required None, adding OverheatProtection to modules.                                                                                                                                   smartdevice.py:429
DEBUG    Device 192.168.0.26, found required time, adding Time to modules.                                                                                                                                                 smartdevice.py:429
DEBUG    Querying 192.168.0.26 for modules: Time, Alarm, ChildSetup, Firmware, Led, Matter                                                                                                                                 smartdevice.py:342
DEBUG    192.168.0.26 multi-request-batch-1-of-2 >>                                                                                                                                                                      smartprotocol.py:242
         '{"method":"multipleRequest","request_time_milis":1776385324443,"terminal_uuid":"E7J4hhHMTk+cInnY9oXxkw==","params":{"requests":[{"method":"get_device_time"},{"method":"get_alarm_configure"},{"method":"get_                     
         support_alarm_type_list"},{"method":"get_support_child_device_category"},{"method":"get_auto_update_info"}]}}'                                                                                                                     
DEBUG    Posting to http://192.168.0.26/stok=tiWTCI0tEL27drb37Ojx3VtEL27drb/ds                                                                                                                                               httpclient.py:88
DEBUG    192.168.0.26 multi-request-batch-1-of-2 << {'error_code': 0,                                                                                                                                                    smartprotocol.py:254
          'result': {'responses': [{'error_code': 0,                                                                                                                                                                                        
                                    'method': 'get_device_time',                                                                                                                                                                            
                                    'result': {'region': 'Asia/Tokyo',                                                                                                                                                                      
                                               'time_diff': 540,                                                                                                                                                                            
                                               'timestamp': 1776385323}},                                                                                                                                                                   
                                   {'error_code': 0,                                                                                                                                                                                        
                                    'method': 'get_alarm_configure',                                                                                                                                                                        
                                    'result': {'duration': 300,                                                                                                                                                                             
                                               'type': 'Doorbell Ring 1',                                                                                                                                                                   
                                               'volume': 'high'}},                                                                                                                                                                          
                                   {'error_code': 0,                                                                                                                                                                                        
                                    'method': 'get_support_alarm_type_list',                                                                                                                                                                
                                    'result': {'alarm_type_list': ['Doorbell Ring 1',                                                                                                                                                       
                                                                   'Doorbell Ring 2',                                                                                                                                                       
                                                                   'Doorbell Ring 3',                                                                                                                                                       
                                                                   'Doorbell Ring 4',                                                                                                                                                       
                                                                   'Doorbell Ring 5',                                                                                                                                                       
                                                                   'Doorbell Ring 6',                                                                                                                                                       
                                                                   'Doorbell Ring 7',                                                                                                                                                       
                                                                   'Doorbell Ring 8',                                                                                                                                                       
                                                                   'Doorbell Ring 9',                                                                                                                                                       
                                                                   'Doorbell Ring 10',                                                                                                                                                      
                                                                   'Phone Ring',                                                                                                                                                            
                                                                   'Alarm 1',                                                                                                                                                               
                                                                   'Alarm 2',                                                                                                                                                               
                                                                   'Alarm 3',                                                                                                                                                               
                                                                   'Alarm 4',                                                                                                                                                               
                                                                   'Dripping Tap',                                                                                                                                                          
                                                                   'Alarm 5',                                                                                                                                                               
                                                                   'Connection 1']}},                                                                                                                                                       
                                   {'error_code': 0,                                                                                                                                                                                        
                                    'method': 'get_support_child_device_category',                                                                                                                                                          
                                    'result': {'device_category_list': [{'category': 'subg.trv'},                                                                                                                                           
                                                                        {'category': 'subg.trigger'},                                                                                                                                       
                                                                        {'category': 'subg.plugswitch'},                                                                                                                                    
                                                                        {'category': 'ir.remote'}]}},                                                                                                                                       
                                   {'error_code': 0,                                                                                                                                                                                        
                                    'method': 'get_auto_update_info',                                                                                                                                                                       
                                    'result': {'enable': True,                                                                                                                                                                              
                                               'random_range': 120,                                                                                                                                                                         
                                               'time': 180}}]}}                                                                                                                                                                             
DEBUG    192.168.0.26 multi-request-batch-2-of-2 >>                                                                                                                                                                      smartprotocol.py:242
         '{"method":"multipleRequest","request_time_milis":1776385324479,"terminal_uuid":"E7J4hhHMTk+cInnY9oXxkw==","params":{"requests":[{"method":"get_led_info"},{"method":"get_matter_setup_info"}]}}'                                  
DEBUG    Posting to http://192.168.0.26/stok=tiWTCI0tEL27drb37Ojx3VtEL27drb/ds                                                                                                                                               httpclient.py:88
DEBUG    192.168.0.26 multi-request-batch-2-of-2 << {'error_code': 0,                                                                                                                                                    smartprotocol.py:254
          'result': {'responses': [{'error_code': 0,                                                                                                                                                                                        
                                    'method': 'get_led_info',                                                                                                                                                                               
                                    'result': {'led_rule': 'always',                                                                                                                                                                        
                                               'led_status': True,                                                                                                                                                                          
                                               'night_mode': {'end_time': 420,                                                                                                                                                              
                                                              'night_mode_type': 'custom',                                                                                                                                                  
                                                              'start_time': 1320}}},                                                                                                                                                        
                                   {'error_code': 0,                                                                                                                                                                                        
                                    'method': 'get_matter_setup_info',                                                                                                                                                                      
                                    'result': {'setup_code': '00000000000',                                                                                                                                                                 
                                               'setup_payload': '00:-0-0000000000000000'}}]}}                                                                                                                                               
DEBUG    Initializing 192.168.0.26 of type <class 'kasa.smart.smartchilddevice.SmartChildDevice'>                                                                                                                               device.py:217
DEBUG    Device 192.168.0.26, found required device, adding DeviceModule to modules.                                                                                                                                       smartdevice.py:429
DEBUG    Created child device <DeviceType.Unknown ライト リモコン (None) of <DeviceType.Hub at 192.168.0.26 - Tapo H110 (H110)>> for 192.168.0.26                                                                           smartdevice.py:131
DEBUG    Update completed 192.168.0.26: ['component_nego', 'get_device_info', 'get_connect_cloud_state', 'get_child_device_component_list', 'get_child_device_list', 'get_device_time', 'get_alarm_configure',             smartdevice.py:298
         'get_support_alarm_type_list', 'get_support_child_device_category', 'get_auto_update_info', 'get_led_info', 'get_matter_setup_info']                                                                                               
== Tapo H110 - H110 ==
Host: 192.168.0.26
Port: 80
Device state: False
Time:         2026-04-17 09:22:03+09:00 (tz: Asia/Tokyo)
Hardware:     1.0 (JP)
Firmware:     1.4.4 Build 251031 Rel.111523
MAC (rssi):   CC:BA:BD:45:96:A4 (-31)

== Primary features ==

== Information ==
Signal Level (signal_level): 3
Alarm (alarm): False
Alarm source (alarm_source): None
Cloud connection (cloud_connection): True
Update available (update_available): None
Check latest firmware (check_latest_firmware): <Action>
Overheated (overheated): False

== Configuration ==
Alarm sound (alarm_sound): *Doorbell Ring 1* Doorbell Ring 2 Doorbell Ring 3 Doorbell Ring 4 Doorbell Ring 5 Doorbell Ring 6 Doorbell Ring 7 Doorbell Ring 8 Doorbell Ring 9 Doorbell Ring 10 Phone Ring Alarm 1 Alarm 2 Alarm 3 Alarm 4 
Dripping Tap Alarm 5 Connection 1
Alarm volume (alarm_volume): mute low normal *high*
Alarm volume (alarm_volume_level): 3 (range: 0-3)
Alarm duration (alarm_duration): 300 (range: 1-600)
Test alarm (test_alarm): <Action>
Stop alarm (stop_alarm): <Action>
Pair (pair): <Action>
Auto update enabled (auto_update_enabled): True
LED (led): True

== Debug ==
Device ID (device_id): 802D5252397AD1150C866F8142E2DD9B24A2A536
RSSI (rssi): -31 dBm
SSID (ssid): IoT_SSID
Reboot (reboot): <Action>
Device time (device_time): 2026-04-17 09:22:03+09:00
Current firmware version (current_firmware_version): 1.4.4 Build 251031 Rel.111523
Available firmware version (available_firmware_version): None
Matter setup code (matter_setup_code): 22821532237
Matter setup payload (matter_setup_payload): MT:-2-0100I147GAZ6F410

== Children ==

        == ライト リモコン (None) ==

        == Primary features ==

        == Information ==

        == Configuration ==

        == Debug ==
        Device ID (device_id): 802D5252397AD1150C866F8142E2DD9B24A2A536030B0002
        Reboot (reboot): <Action>
        Unpair device (unpair): <Action>


DEBUG    Discovered 1 devices                                                                                                                                                                                                discover.py:512
Found 1 devices

I would still like to work on adding support for the ir.remote device type, so if there's anything I can do to assist the TPAP implementation please let me know.

@ZeliardM
Copy link
Copy Markdown
Contributor Author

@tuck-ski Thaks for this feedback. I haven't had anyone test this path yet so it's good to see. I'll take this information and see if I can work on getting the issues resolved and let you know. Thanks!

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.