GeezerVison is showing github.com — Update post review and rename TPLinkProtocol to BaseProtocol · python-kasa/python-kasa@809c54f
File treeExpand file treeCollapse file tree Open diff view settings Expand file treeCollapse file tree Open diff view settings Collapse file Copy file name to clipboardExpand all lines: docs/source/design.rst +37-21Lines changed: 37 additions & 21 deletions - Display the source diff
- Display the rich diff
| Original file line number | Diff line number | Diff line change |
|---|
| 1 | 1 | .. py:module:: kasa.modules | 2 | 2 |
| | 3 | +
| 3 | 4 | .. _library_design: | 4 | 5 |
| 5 | 6 | Library Design & Modules | @@ -46,6 +47,7 @@ While the properties are designed to provide a nice API to use for common use ca | 46 | 47 | you may sometimes want to access the raw, cached data as returned by the device. | 47 | 48 | This can be done using the :attr:`~kasa.SmartDevice.internal_state` property. | 48 | 49 |
| | 50 | + | 49 | 51 | .. _modules: | 50 | 52 |
| 51 | 53 | Modules | @@ -66,12 +68,14 @@ Protocols and Transports | 66 | 68 |
| 67 | 69 | The library supports two different TP-Link protocols, ``IOT`` and ``SMART``. | 68 | 70 | ``IOT`` is the original Kasa protocol and ``SMART`` is the newer protocol supported by TAPO devices and newer KASA devices. | | 71 | +The original protocol has a ``target``, ``command``, ``args`` interface whereas the new protocol uses a different set of | | 72 | +commands and has a ``method``, ``parameters`` interface. | 69 | 73 | Confusingly TP-Link originally called the Kasa line "Kasa Smart" and hence this library used "Smart" in a lot of the | 70 | 74 | module and class names but actually they were built to work with the ``IOT`` protocol. | 71 | 75 |
| 72 | 76 | In 2021 TP-Link started updating the underlying communication transport used by Kasa devices to make them more secure. | 73 | 77 | It switched from a TCP connection with static XOR type of encryption to a transport called ``KLAP`` which communicates | 74 | | -over http and uses handshakes to negotiate a dynamic encrpytion cipher. | | 78 | +over http and uses handshakes to negotiate a dynamic encryption cipher. | 75 | 79 | This automatic update was put on hold and only seemed to affect UK HS100 models. | 76 | 80 |
| 77 | 81 | 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 | 81 | 85 | Also in 2023 TP-Link started releasing newer Kasa branded devices using the ``SMART`` protocol. | 82 | 86 | This appears to be driven by hardware version rather than firmware. | 83 | 87 |
| 84 | | -In order to support these different configurations the library is migrating from a single :class:`~TPLinkSmartHomeProtocol` | 85 | | -that support XOR encryption and the IOT protocol to seperate transports and protocols. | | 88 | + | | 89 | +In order to support these different configurations the library migrated from a single :class:`TPLinkSmartHomeProtocol <kasa.protocol.TPLinkSmartHomeProtocol>` | | 90 | +to support pluggable transports and protocols. | 86 | 91 | The classes providing this functionality are: | 87 | 92 |
| 88 | | -- :class:`~kasa.BaseProtocol` | 89 | | -- :class:`~kasa.IotProtocol` | 90 | | -- :class:`~kasa.SmartProtocol` | | 93 | +- :class:`BaseProtocol <kasa.protocol.BaseProtocol>` | | 94 | +- :class:`IotProtocol <kasa.iotprotocol.IotProtocol>` | | 95 | +- :class:`SmartProtocol <kasa.smartprotocol.SmartProtocol>` | 91 | 96 |
| 92 | | -- :class:`~kasa.BaseTransport` | 93 | | -- :class:`~kasa.XorTransport` | 94 | | -- :class:`~kasa.AesTransport` | 95 | | -- :class:`~kasa.KlapTransport` | 96 | | -- :class:`~kasa.KlapTransportV2` | | 97 | +- :class:`BaseTransport <kasa.protocol.BaseTransport>` | | 98 | +- :class:`AesTransport <kasa.aestransport.AesTransport>` | | 99 | +- :class:`KlapTransport <kasa.klaptransport.KlapTransport>` | | 100 | +- :class:`KlapTransportV2 <kasa.klaptransport.KlapTransportV2>` | 97 | 101 |
| 98 | 102 |
| 99 | 103 | API documentation for modules | @@ -105,35 +109,47 @@ API documentation for modules | 105 | 109 | :inherited-members: | 106 | 110 | :undoc-members: | 107 | 111 |
| | 112 | + | | 113 | + | 108 | 114 | API documentation for protocols and transports | 109 | 115 | ********************************************** | 110 | 116 |
| 111 | | -.. automodule:: kasa.protocol | 112 | | - :noindex: | | 117 | +.. autoclass:: kasa.protocol.BaseProtocol | 113 | 118 | :members: | 114 | 119 | :inherited-members: | 115 | 120 | :undoc-members: | 116 | 121 |
| 117 | | -.. automodule:: kasa.klaptransport | 118 | | - :noindex: | | 122 | +.. autoclass:: kasa.iotprotocol.IotProtocol | 119 | 123 | :members: | 120 | 124 | :inherited-members: | 121 | 125 | :undoc-members: | 122 | 126 |
| 123 | | -.. automodule:: kasa.aestransport | 124 | | - :noindex: | | 127 | +.. autoclass:: kasa.smartprotocol.SmartProtocol | 125 | 128 | :members: | 126 | 129 | :inherited-members: | 127 | 130 | :undoc-members: | 128 | 131 |
| 129 | | -.. automodule:: kasa.iotprotocol | 130 | | - :noindex: | | 132 | +.. autoclass:: kasa.protocol.BaseTransport | 131 | 133 | :members: | 132 | 134 | :inherited-members: | 133 | 135 | :undoc-members: | 134 | 136 |
| 135 | | -.. automodule:: kasa.smartprotocol | 136 | | - :noindex: | | 137 | +.. autoclass:: kasa.klaptransport.KlapTransport | | 138 | + :members: | | 139 | + :inherited-members: | | 140 | + :undoc-members: | | 141 | + | | 142 | +.. autoclass:: kasa.klaptransport.KlapTransportV2 | | 143 | + :members: | | 144 | + :inherited-members: | | 145 | + :undoc-members: | | 146 | + | | 147 | +.. autoclass:: kasa.aestransport.AesTransport | | 148 | + :members: | | 149 | + :inherited-members: | | 150 | + :undoc-members: | | 151 | + | | 152 | +.. autoclass:: kasa.protocol.TPLinkSmartHomeProtocol | 137 | 153 | :members: | 138 | 154 | :inherited-members: | 139 | 155 | :undoc-members: |
Collapse file Copy file name to clipboardExpand all lines: kasa/__init__.py +2-2Lines changed: 2 additions & 2 deletions | Original file line number | Diff line number | Diff line change |
|---|
| 29 | 29 | UnsupportedDeviceException, | 30 | 30 | ) | 31 | 31 | from kasa.iotprotocol import IotProtocol | 32 | | -from kasa.protocol import TPLinkProtocol, TPLinkSmartHomeProtocol | | 32 | +from kasa.protocol import BaseProtocol, TPLinkSmartHomeProtocol | 33 | 33 | from kasa.smartbulb import SmartBulb, SmartBulbPreset, TurnOnBehavior, TurnOnBehaviors | 34 | 34 | from kasa.smartdevice import DeviceType, SmartDevice | 35 | 35 | from kasa.smartdimmer import SmartDimmer | | 44 | 44 | __all__ = [ | 45 | 45 | "Discover", | 46 | 46 | "TPLinkSmartHomeProtocol", | 47 | | - "TPLinkProtocol", | | 47 | + "BaseProtocol", | 48 | 48 | "IotProtocol", | 49 | 49 | "SmartProtocol", | 50 | 50 | "SmartBulb", | |
Collapse file Copy file name to clipboardExpand all lines: kasa/device_factory.py +3-3Lines changed: 3 additions & 3 deletions | Original file line number | Diff line number | Diff line change |
|---|
| 9 | 9 | from .iotprotocol import IotProtocol | 10 | 10 | from .klaptransport import KlapTransport, KlapTransportV2 | 11 | 11 | from .protocol import ( | | 12 | + BaseProtocol, | 12 | 13 | BaseTransport, | 13 | | - TPLinkProtocol, | 14 | 14 | TPLinkSmartHomeProtocol, | 15 | 15 | _XorTransport, | 16 | 16 | ) | @@ -141,14 +141,14 @@ def get_device_class_from_family(device_type: str) -> Optional[Type[SmartDevice] | 141 | 141 |
| 142 | 142 | def get_protocol( | 143 | 143 | config: DeviceConfig, | 144 | | -) -> Optional[TPLinkProtocol]: | | 144 | +) -> Optional[BaseProtocol]: | 145 | 145 | """Return the protocol from the connection name.""" | 146 | 146 | protocol_name = config.connection_type.device_family.value.split(".")[0] | 147 | 147 | protocol_transport_key = ( | 148 | 148 | protocol_name + "." + config.connection_type.encryption_type.value | 149 | 149 | ) | 150 | 150 | supported_device_protocols: Dict[ | 151 | | - str, Tuple[Type[TPLinkProtocol], Type[BaseTransport]] | | 151 | + str, Tuple[Type[BaseProtocol], Type[BaseTransport]] | 152 | 152 | ] = { | 153 | 153 | "IOT.XOR": (TPLinkSmartHomeProtocol, _XorTransport), | 154 | 154 | "IOT.KLAP": (IotProtocol, KlapTransport), | |
Collapse file Copy file name to clipboardExpand all lines: kasa/iotprotocol.py +2-2Lines changed: 2 additions & 2 deletions | Original file line number | Diff line number | Diff line change |
|---|
| 11 | 11 | TimeoutException, | 12 | 12 | ) | 13 | 13 | from .json import dumps as json_dumps | 14 | | -from .protocol import BaseTransport, TPLinkProtocol | | 14 | +from .protocol import BaseProtocol, BaseTransport | 15 | 15 |
| 16 | 16 | _LOGGER = logging.getLogger(__name__) | 17 | 17 |
| 18 | 18 |
| 19 | | -class IotProtocol(TPLinkProtocol): | | 19 | +class IotProtocol(BaseProtocol): | 20 | 20 | """Class for the legacy TPLink IOT KASA Protocol.""" | 21 | 21 |
| 22 | 22 | BACKOFF_SECONDS_AFTER_TIMEOUT = 1 | |
Collapse file Copy file name to clipboardExpand all lines: kasa/protocol.py +3-3Lines changed: 3 additions & 3 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -79,7 +79,7 @@ async def close(self) -> None: | 79 | 79 | """Close the transport. Abstract method to be overriden.""" | 80 | 80 |
| 81 | 81 |
| 82 | | -class TPLinkProtocol(ABC): | | 82 | +class BaseProtocol(ABC): | 83 | 83 | """Base class for all TP-Link Smart Home communication.""" | 84 | 84 |
| 85 | 85 | def __init__( | @@ -140,7 +140,7 @@ async def close(self) -> None: | 140 | 140 | """Close the transport. Abstract method to be overriden.""" | 141 | 141 |
| 142 | 142 |
| 143 | | -class TPLinkSmartHomeProtocol(TPLinkProtocol): | | 143 | +class TPLinkSmartHomeProtocol(BaseProtocol): | 144 | 144 | """Implementation of the TP-Link Smart Home protocol.""" | 145 | 145 |
| 146 | 146 | INITIALIZATION_VECTOR = 171 | @@ -168,7 +168,7 @@ async def query(self, request: Union[str, Dict], retry_count: int = 3) -> Dict: | 168 | 168 |
| 169 | 169 | :param str host: host name or ip address of the device | 170 | 170 | :param request: command to send to the device (can be either dict or | 171 | | - json string) | | 171 | + json string) | 172 | 172 | :param retry_count: how many retries to do in case of failure | 173 | 173 | :return: response dict | 174 | 174 | """ | |
Collapse file Copy file name to clipboardExpand all lines: kasa/smartbulb.py +2-2Lines changed: 2 additions & 2 deletions | Original file line number | Diff line number | Diff line change |
|---|
| 11 | 11 |
| 12 | 12 | from .deviceconfig import DeviceConfig | 13 | 13 | from .modules import Antitheft, Cloud, Countdown, Emeter, Schedule, Time, Usage | 14 | | -from .protocol import TPLinkProtocol | | 14 | +from .protocol import BaseProtocol | 15 | 15 | from .smartdevice import DeviceType, SmartDevice, SmartDeviceException, requires_update | 16 | 16 |
| 17 | 17 |
| @@ -222,7 +222,7 @@ def __init__( | 222 | 222 | host: str, | 223 | 223 | *, | 224 | 224 | config: Optional[DeviceConfig] = None, | 225 | | - protocol: Optional[TPLinkProtocol] = None, | | 225 | + protocol: Optional[BaseProtocol] = None, | 226 | 226 | ) -> None: | 227 | 227 | super().__init__(host=host, config=config, protocol=protocol) | 228 | 228 | self._device_type = DeviceType.Bulb | |
Collapse file Copy file name to clipboardExpand all lines: kasa/smartdevice.py +3-3Lines changed: 3 additions & 3 deletions | Original file line number | Diff line number | Diff line change |
|---|
| 25 | 25 | from .emeterstatus import EmeterStatus | 26 | 26 | from .exceptions import SmartDeviceException | 27 | 27 | from .modules import Emeter, Module | 28 | | -from .protocol import TPLinkProtocol, TPLinkSmartHomeProtocol, _XorTransport | | 28 | +from .protocol import BaseProtocol, TPLinkSmartHomeProtocol, _XorTransport | 29 | 29 |
| 30 | 30 | _LOGGER = logging.getLogger(__name__) | 31 | 31 |
| @@ -196,15 +196,15 @@ def __init__( | 196 | 196 | host: str, | 197 | 197 | *, | 198 | 198 | config: Optional[DeviceConfig] = None, | 199 | | - protocol: Optional[TPLinkProtocol] = None, | | 199 | + protocol: Optional[BaseProtocol] = None, | 200 | 200 | ) -> None: | 201 | 201 | """Create a new SmartDevice instance. | 202 | 202 |
| 203 | 203 | :param str host: host name or ip address on which the device listens | 204 | 204 | """ | 205 | 205 | if config and protocol: | 206 | 206 | protocol._transport._config = config | 207 | | - self.protocol: TPLinkProtocol = protocol or TPLinkSmartHomeProtocol( | | 207 | + self.protocol: BaseProtocol = protocol or TPLinkSmartHomeProtocol( | 208 | 208 | transport=_XorTransport(config=config or DeviceConfig(host=host)), | 209 | 209 | ) | 210 | 210 | _LOGGER.debug("Initializing %s of type %s", self.host, type(self)) | |
Collapse file Copy file name to clipboardExpand all lines: kasa/smartdimmer.py +2-2Lines changed: 2 additions & 2 deletions | Original file line number | Diff line number | Diff line change |
|---|
| 4 | 4 |
| 5 | 5 | from kasa.deviceconfig import DeviceConfig | 6 | 6 | from kasa.modules import AmbientLight, Motion | 7 | | -from kasa.protocol import TPLinkProtocol | | 7 | +from kasa.protocol import BaseProtocol | 8 | 8 | from kasa.smartdevice import DeviceType, SmartDeviceException, requires_update | 9 | 9 | from kasa.smartplug import SmartPlug | 10 | 10 |
| @@ -70,7 +70,7 @@ def __init__( | 70 | 70 | host: str, | 71 | 71 | *, | 72 | 72 | config: Optional[DeviceConfig] = None, | 73 | | - protocol: Optional[TPLinkProtocol] = None, | | 73 | + protocol: Optional[BaseProtocol] = None, | 74 | 74 | ) -> None: | 75 | 75 | super().__init__(host=host, config=config, protocol=protocol) | 76 | 76 | self._device_type = DeviceType.Dimmer | |
Collapse file Copy file name to clipboardExpand all lines: kasa/smartlightstrip.py +2-2Lines changed: 2 additions & 2 deletions | Original file line number | Diff line number | Diff line change |
|---|
| 3 | 3 |
| 4 | 4 | from .deviceconfig import DeviceConfig | 5 | 5 | from .effects import EFFECT_MAPPING_V1, EFFECT_NAMES_V1 | 6 | | -from .protocol import TPLinkProtocol | | 6 | +from .protocol import BaseProtocol | 7 | 7 | from .smartbulb import SmartBulb | 8 | 8 | from .smartdevice import DeviceType, SmartDeviceException, requires_update | 9 | 9 |
| @@ -48,7 +48,7 @@ def __init__( | 48 | 48 | host: str, | 49 | 49 | *, | 50 | 50 | config: Optional[DeviceConfig] = None, | 51 | | - protocol: Optional[TPLinkProtocol] = None, | | 51 | + protocol: Optional[BaseProtocol] = None, | 52 | 52 | ) -> None: | 53 | 53 | super().__init__(host=host, config=config, protocol=protocol) | 54 | 54 | self._device_type = DeviceType.LightStrip | |
Collapse file Copy file name to clipboardExpand all lines: kasa/smartplug.py +2-2Lines changed: 2 additions & 2 deletions | Original file line number | Diff line number | Diff line change |
|---|
| 4 | 4 |
| 5 | 5 | from kasa.deviceconfig import DeviceConfig | 6 | 6 | from kasa.modules import Antitheft, Cloud, Schedule, Time, Usage | 7 | | -from kasa.protocol import TPLinkProtocol | | 7 | +from kasa.protocol import BaseProtocol | 8 | 8 | from kasa.smartdevice import DeviceType, SmartDevice, requires_update | 9 | 9 |
| 10 | 10 | _LOGGER = logging.getLogger(__name__) | @@ -45,7 +45,7 @@ def __init__( | 45 | 45 | host: str, | 46 | 46 | *, | 47 | 47 | config: Optional[DeviceConfig] = None, | 48 | | - protocol: Optional[TPLinkProtocol] = None, | | 48 | + protocol: Optional[BaseProtocol] = None, | 49 | 49 | ) -> None: | 50 | 50 | super().__init__(host=host, config=config, protocol=protocol) | 51 | 51 | self._device_type = DeviceType.Plug | |
|