Library Design & Modules
This page aims to provide some details on the design and internals of this library. You might be interested in this if you want to improve this library, or if you are just looking to access some information that is not currently exposed.
Initialization
Use discover()
to perform udp-based broadcast discovery on the network.
This will return you a list of device instances based on the discovery replies.
If the device’s host is already known, you can use to construct a device instance with
connect()
.
The connect()
also enables support for connecting to new
KASA SMART protocol and TAPO devices directly using the parameter DeviceConfig
.
Simply serialize the config
property via to_dict()
and then deserialize it later with from_dict()
and then pass it into connect()
.
Update Cycle
When update()
is called,
the library constructs a query to send to the device based on supported modules.
Internally, each module defines query()
to describe what they want query during the update.
The returned data is cached internally to avoid I/O on property accesses. All properties defined both in the device class and in the module classes follow this principle.
While the properties are designed to provide a nice API to use for common use cases,
you may sometimes want to access the raw, cached data as returned by the device.
This can be done using the internal_state
property.
Modules
The functionality provided by all SmartDevice
instances is (mostly) done inside separate modules.
While the individual device-type specific classes provide an easy access for the most import features,
you can also access individual modules through kasa.SmartDevice.modules
.
You can get the list of supported modules for a given device instance using supported_modules
.
Note
If you only need some module-specific information,
you can call the wanted method on the module to avoid using update()
.
Protocols and Transports
The library supports two different TP-Link protocols, IOT
and SMART
.
IOT
is the original Kasa protocol and SMART
is the newer protocol supported by TAPO devices and newer KASA devices.
The original protocol has a target
, command
, args
interface whereas the new protocol uses a different set of
commands and has a method
, parameters
interface.
Confusingly TP-Link originally called the Kasa line “Kasa Smart” and hence this library used “Smart” in a lot of the
module and class names but actually they were built to work with the IOT
protocol.
In 2021 TP-Link started updating the underlying communication transport used by Kasa devices to make them more secure.
It switched from a TCP connection with static XOR type of encryption to a transport called KLAP
which communicates
over http and uses handshakes to negotiate a dynamic encryption cipher.
This automatic update was put on hold and only seemed to affect UK HS100 models.
In 2023 TP-Link started updating the underlying communication transport used by Tapo devices to make them more secure.
It switched from AES encryption via public key exchange to use KLAP
encryption and negotiation due to concerns
around impersonation with AES.
The encryption cipher is the same as for Kasa KLAP but the handshake seeds are slightly different.
Also in 2023 TP-Link started releasing newer Kasa branded devices using the SMART
protocol.
This appears to be driven by hardware version rather than firmware.
In order to support these different configurations the library migrated from a single protocol class TPLinkSmartHomeProtocol
to support pluggable transports and protocols.
The classes providing this functionality are:
Errors and Exceptions
The base exception for all library errors is KasaException
.
If the device returns an error the library raises a
DeviceError
which will usually contain anerror_code
with the detail.If the device fails to authenticate the library raises an
AuthenticationError
which is derived fromDeviceError
and could contain anerror_code
depending on the type of failure.If the library encounters and unsupported deviceit raises an
UnsupportedDeviceError
.If the device fails to respond within a timeout the library raises a
TimeoutError
.All other failures will raise the base
KasaException
class.
API documentation for modules
API documentation for protocols and transports
- class kasa.protocol.BaseProtocol(*, transport: BaseTransport)[source]
Base class for all TP-Link Smart Home communication.
- property config: DeviceConfig
Return the connection parameters the device is using.
- class kasa.iotprotocol.IotProtocol(*, transport: BaseTransport)[source]
Class for the legacy TPLink IOT KASA Protocol.
- BACKOFF_SECONDS_AFTER_TIMEOUT = 1
- property config: DeviceConfig
Return the connection parameters the device is using.
- class kasa.smartprotocol.SmartProtocol(*, transport: BaseTransport)[source]
Class for the new TPLink SMART protocol.
- BACKOFF_SECONDS_AFTER_TIMEOUT = 1
- DEFAULT_MULTI_REQUEST_BATCH_SIZE = 5
- property config: DeviceConfig
Return the connection parameters the device is using.
- class kasa.protocol.BaseTransport(*, config: DeviceConfig)[source]
Base class for all TP-Link protocol transports.
- DEFAULT_TIMEOUT = 5
- abstract property credentials_hash: str
The hashed credentials used by the transport.
- abstract property default_port: int
The default port for the transport.
- class kasa.xortransport.XorTransport(*, config: DeviceConfig)[source]
XorTransport class.
- BLOCK_SIZE = 4
- DEFAULT_PORT: int = 9999
- DEFAULT_TIMEOUT = 5
- close_without_wait() None [source]
Close the connection without waiting for the connection to close.
- property credentials_hash: str
The hashed credentials used by the transport.
- property default_port
Default port for the transport.
- class kasa.klaptransport.KlapTransport(*, config: DeviceConfig)[source]
Implementation of the KLAP encryption protocol.
KLAP is the name used in device discovery for TP-Link’s new encryption protocol, used by newer firmware versions.
- DEFAULT_PORT: int = 80
- DEFAULT_TIMEOUT = 5
- DISCOVERY_QUERY = {'system': {'get_sysinfo': None}}
- SESSION_COOKIE_NAME = 'TP_SESSIONID'
- TIMEOUT_COOKIE_NAME = 'TIMEOUT'
- property credentials_hash: str
The hashed credentials used by the transport.
- property default_port
Default port for the transport.
- static generate_auth_hash(creds: Credentials)[source]
Generate an md5 auth hash for the protocol on the supplied credentials.
- static generate_owner_hash(creds: Credentials)[source]
Return the MD5 hash of the username in this object.
- static handshake1_seed_auth_hash(local_seed: bytes, remote_seed: bytes, auth_hash: bytes)[source]
Generate an md5 auth hash for the protocol on the supplied credentials.
- static handshake2_seed_auth_hash(local_seed: bytes, remote_seed: bytes, auth_hash: bytes)[source]
Generate an md5 auth hash for the protocol on the supplied credentials.
- async perform_handshake() Any [source]
Perform handshake1 and handshake2.
Sets the encryption_session if successful.
- class kasa.klaptransport.KlapTransportV2(*, config: DeviceConfig)[source]
Implementation of the KLAP encryption protocol with v2 hanshake hashes.
- DEFAULT_PORT: int = 80
- DEFAULT_TIMEOUT = 5
- DISCOVERY_QUERY = {'system': {'get_sysinfo': None}}
- SESSION_COOKIE_NAME = 'TP_SESSIONID'
- TIMEOUT_COOKIE_NAME = 'TIMEOUT'
- async close() None
Close the http client and reset internal state.
- property credentials_hash: str
The hashed credentials used by the transport.
- property default_port
Default port for the transport.
- static generate_auth_hash(creds: Credentials)[source]
Generate an md5 auth hash for the protocol on the supplied credentials.
- static generate_owner_hash(creds: Credentials)
Return the MD5 hash of the username in this object.
- static handshake1_seed_auth_hash(local_seed: bytes, remote_seed: bytes, auth_hash: bytes)[source]
Generate an md5 auth hash for the protocol on the supplied credentials.
- static handshake2_seed_auth_hash(local_seed: bytes, remote_seed: bytes, auth_hash: bytes)[source]
Generate an md5 auth hash for the protocol on the supplied credentials.
- async perform_handshake() Any
Perform handshake1 and handshake2.
Sets the encryption_session if successful.
- async perform_handshake1() tuple[bytes, bytes, bytes]
Perform handshake1.
- async perform_handshake2(local_seed, remote_seed, auth_hash) KlapEncryptionSession
Perform handshake2.
- async reset() None
Reset internal handshake state.
- async send(request: str)
Send the request.
- class kasa.aestransport.AesTransport(*, config: DeviceConfig)[source]
Implementation of the AES encryption protocol.
AES is the name used in device discovery for TP-Link’s TAPO encryption protocol, sometimes used by newer firmware versions on kasa devices.
- BACKOFF_SECONDS_AFTER_LOGIN_ERROR = 1
- COMMON_HEADERS = {'Accept': 'application/json', 'Content-Type': 'application/json', 'requestByApp': 'true'}
- CONTENT_LENGTH = 'Content-Length'
- DEFAULT_PORT: int = 80
- DEFAULT_TIMEOUT = 5
- KEY_PAIR_CONTENT_LENGTH = 314
- SESSION_COOKIE_NAME = 'TP_SESSIONID'
- TIMEOUT_COOKIE_NAME = 'TIMEOUT'
- property credentials_hash: str
The hashed credentials used by the transport.
- property default_port: int
Default port for the transport.
- static hash_credentials(login_v2: bool, credentials: Credentials) tuple[str, str] [source]
Hash the credentials.
API documentation for errors and exceptions
- class kasa.exceptions.DeviceError(*args: Any, **kwargs: Any)[source]
Base exception for device errors.
- class kasa.exceptions.AuthenticationError(*args: Any, **kwargs: Any)[source]
Base exception for device authentication errors.