From f1d86c6adec0e10bbef3cb6ae7005d9dff2df199 Mon Sep 17 00:00:00 2001 From: sdb9696 Date: Sat, 20 Jan 2024 13:08:11 +0000 Subject: [PATCH 1/2] Add protocol and transport documentation --- docs/source/design.rst | 67 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/docs/source/design.rst b/docs/source/design.rst index 6538c8b80..db5113512 100644 --- a/docs/source/design.rst +++ b/docs/source/design.rst @@ -61,6 +61,40 @@ You can get the list of supported modules for a given device instance using :att If you only need some module-specific information, you can call the wanted method on the module to avoid using :meth:`~kasa.SmartDevice.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. +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 encrpytion 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 is migrating from a single :class:`~TPLinkSmartHomeProtocol` +that support XOR encryption and the IOT protocol to seperate transports and protocols. +The classes providing this functionality are: + +- :class:`~kasa.BaseProtocol` +- :class:`~kasa.IotProtocol` +- :class:`~kasa.SmartProtocol` + +- :class:`~kasa.BaseTransport` +- :class:`~kasa.XorTransport` +- :class:`~kasa.AesTransport` +- :class:`~kasa.KlapTransport` +- :class:`~kasa.KlapTransportV2` + API documentation for modules ***************************** @@ -70,3 +104,36 @@ API documentation for modules :members: :inherited-members: :undoc-members: + +API documentation for protocols and transports +********************************************** + +.. automodule:: kasa.protocol + :noindex: + :members: + :inherited-members: + :undoc-members: + +.. automodule:: kasa.klaptransport + :noindex: + :members: + :inherited-members: + :undoc-members: + +.. automodule:: kasa.aestransport + :noindex: + :members: + :inherited-members: + :undoc-members: + +.. automodule:: kasa.iotprotocol + :noindex: + :members: + :inherited-members: + :undoc-members: + +.. automodule:: kasa.smartprotocol + :noindex: + :members: + :inherited-members: + :undoc-members: From 8dbeadf5f16cfd9c6e665a099bd49f57822b73f3 Mon Sep 17 00:00:00 2001 From: sdb9696 Date: Mon, 22 Jan 2024 12:14:49 +0000 Subject: [PATCH 2/2] Update post review --- docs/source/design.rst | 58 +++++++++++++++++++++++++++--------------- kasa/protocol.py | 2 +- 2 files changed, 38 insertions(+), 22 deletions(-) diff --git a/docs/source/design.rst b/docs/source/design.rst index db5113512..419c60569 100644 --- a/docs/source/design.rst +++ b/docs/source/design.rst @@ -1,5 +1,6 @@ .. py:module:: kasa.modules + .. _library_design: Library Design & Modules @@ -46,6 +47,7 @@ While the properties are designed to provide a nice API to use for common use ca you may sometimes want to access the raw, cached data as returned by the device. This can be done using the :attr:`~kasa.SmartDevice.internal_state` property. + .. _modules: Modules @@ -66,12 +68,14 @@ 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 encrpytion cipher. +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. @@ -81,19 +85,19 @@ The encryption cipher is the same as for Kasa KLAP but the handshake seeds are s 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 is migrating from a single :class:`~TPLinkSmartHomeProtocol` -that support XOR encryption and the IOT protocol to seperate transports and protocols. + +In order to support these different configurations the library migrated from a single :class:`TPLinkSmartHomeProtocol ` +to support pluggable transports and protocols. The classes providing this functionality are: -- :class:`~kasa.BaseProtocol` -- :class:`~kasa.IotProtocol` -- :class:`~kasa.SmartProtocol` +- :class:`BaseProtocol ` +- :class:`IotProtocol ` +- :class:`SmartProtocol ` -- :class:`~kasa.BaseTransport` -- :class:`~kasa.XorTransport` -- :class:`~kasa.AesTransport` -- :class:`~kasa.KlapTransport` -- :class:`~kasa.KlapTransportV2` +- :class:`BaseTransport ` +- :class:`AesTransport ` +- :class:`KlapTransport ` +- :class:`KlapTransportV2 ` API documentation for modules @@ -105,35 +109,47 @@ API documentation for modules :inherited-members: :undoc-members: + + API documentation for protocols and transports ********************************************** -.. automodule:: kasa.protocol - :noindex: +.. autoclass:: kasa.protocol.BaseProtocol :members: :inherited-members: :undoc-members: -.. automodule:: kasa.klaptransport - :noindex: +.. autoclass:: kasa.iotprotocol.IotProtocol :members: :inherited-members: :undoc-members: -.. automodule:: kasa.aestransport - :noindex: +.. autoclass:: kasa.smartprotocol.SmartProtocol :members: :inherited-members: :undoc-members: -.. automodule:: kasa.iotprotocol - :noindex: +.. autoclass:: kasa.protocol.BaseTransport :members: :inherited-members: :undoc-members: -.. automodule:: kasa.smartprotocol - :noindex: +.. autoclass:: kasa.klaptransport.KlapTransport + :members: + :inherited-members: + :undoc-members: + +.. autoclass:: kasa.klaptransport.KlapTransportV2 + :members: + :inherited-members: + :undoc-members: + +.. autoclass:: kasa.aestransport.AesTransport + :members: + :inherited-members: + :undoc-members: + +.. autoclass:: kasa.protocol.TPLinkSmartHomeProtocol :members: :inherited-members: :undoc-members: diff --git a/kasa/protocol.py b/kasa/protocol.py index a63250fac..bbdd81fdf 100755 --- a/kasa/protocol.py +++ b/kasa/protocol.py @@ -168,7 +168,7 @@ async def query(self, request: Union[str, Dict], retry_count: int = 3) -> Dict: :param str host: host name or ip address of the device :param request: command to send to the device (can be either dict or - json string) + json string) :param retry_count: how many retries to do in case of failure :return: response dict """