Commit Graph

76 Commits

Author SHA1 Message Date
Steven B.
296af3192e
Handle KeyboardInterrupts in the cli better (#1391)
Addresses an issue with how `asyncclick` deals with `KeyboardInterrupt`
errors. Instead of the `click.main` receiving `KeyboardInterrupt` it
receives `CancelledError` because it's a task running inside the loop.

Also ensures that discovery catches the `CancelledError` and closes the
http clients.
2024-12-20 14:21:38 +01:00
Steven B.
fe072657b4
Simplify get_protocol to prevent clashes with smartcam and robovac (#1377)
Some checks are pending
CI / Perform linting checks (3.13) (push) Waiting to run
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, macos-latest, 3.11) (push) Blocked by required conditions
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, macos-latest, 3.12) (push) Blocked by required conditions
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, macos-latest, 3.13) (push) Blocked by required conditions
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, ubuntu-latest, 3.11) (push) Blocked by required conditions
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, ubuntu-latest, 3.12) (push) Blocked by required conditions
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, ubuntu-latest, 3.13) (push) Blocked by required conditions
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, windows-latest, 3.11) (push) Blocked by required conditions
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, windows-latest, 3.12) (push) Blocked by required conditions
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, windows-latest, 3.13) (push) Blocked by required conditions
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (true, ubuntu-latest, 3.11) (push) Blocked by required conditions
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (true, ubuntu-latest, 3.12) (push) Blocked by required conditions
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (true, ubuntu-latest, 3.13) (push) Blocked by required conditions
CodeQL checks / Analyze (python) (push) Waiting to run
2024-12-17 07:39:17 +00:00
Steven B.
223f3318ea
Use DeviceInfo consistently across devices (#1338)
Some checks are pending
CI / Perform linting checks (3.13) (push) Waiting to run
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, macos-latest, 3.11) (push) Blocked by required conditions
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, macos-latest, 3.12) (push) Blocked by required conditions
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, macos-latest, 3.13) (push) Blocked by required conditions
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, ubuntu-latest, 3.11) (push) Blocked by required conditions
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, ubuntu-latest, 3.12) (push) Blocked by required conditions
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, ubuntu-latest, 3.13) (push) Blocked by required conditions
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, windows-latest, 3.11) (push) Blocked by required conditions
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, windows-latest, 3.12) (push) Blocked by required conditions
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, windows-latest, 3.13) (push) Blocked by required conditions
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (true, ubuntu-latest, 3.11) (push) Blocked by required conditions
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (true, ubuntu-latest, 3.12) (push) Blocked by required conditions
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (true, ubuntu-latest, 3.13) (push) Blocked by required conditions
CodeQL checks / Analyze (python) (push) Waiting to run
- Make model exclude region for `iot` devices. This is consistent with `smart` and `smartcam` devices.
- Make region it's own attribute on `Device`.
- Ensure that devices consistently use `_get_device_info` static methods for all information relating to device models.
- Fix issue with firmware and hardware being the wrong way round for `smartcam` devices.
2024-12-13 12:37:13 +00:00
Steven B.
8cb5c2e180
Update dump_devinfo for raw discovery json and common redactors (#1358)
Some checks failed
CI / Perform linting checks (3.13) (push) Waiting to run
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, macos-latest, 3.11) (push) Blocked by required conditions
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, macos-latest, 3.12) (push) Blocked by required conditions
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, macos-latest, 3.13) (push) Blocked by required conditions
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, ubuntu-latest, 3.11) (push) Blocked by required conditions
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, ubuntu-latest, 3.12) (push) Blocked by required conditions
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, ubuntu-latest, 3.13) (push) Blocked by required conditions
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, windows-latest, 3.11) (push) Blocked by required conditions
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, windows-latest, 3.12) (push) Blocked by required conditions
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, windows-latest, 3.13) (push) Blocked by required conditions
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (true, ubuntu-latest, 3.11) (push) Blocked by required conditions
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (true, ubuntu-latest, 3.12) (push) Blocked by required conditions
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (true, ubuntu-latest, 3.13) (push) Blocked by required conditions
CodeQL checks / Analyze (python) (push) Has been cancelled
This PR does a few related things to dump_devinfo:

- Store the raw discovery result in the fixture.
- Consolidate redaction logic so it's not duplicated in dump_devinfo.
- Update existing fixtures to:
  - Store raw discovery result under `result`
  - Use `SCRUBBED_CHILD_DEVICE_ID` everywhere
  - Have correct values as per the consolidated redactors.
2024-12-11 14:18:44 +01:00
Steven B.
bf8f0adabe
Return raw discovery result in cli discover raw (#1342)
Add `on_discovered_raw` callback to Discover and adds a cli command `discover raw` which returns the raw json before serializing to a `DiscoveryResult` and attempting to create a device class.
2024-12-10 22:42:14 +00:00
Puxtril
cb89342be1
Add LinkieTransportV2 and basic IOT.IPCAMERA support (#1270)
Add LinkieTransportV2 transport used by kasa cameras and a basic
implementation for IOT.IPCAMERA (kasacam) devices.

---------

Co-authored-by: Zach Price <pricezt@ornl.gov>
Co-authored-by: Steven B <51370195+sdb9696@users.noreply.github.com>
Co-authored-by: Teemu Rytilahti <tpr@iki.fi>
2024-12-07 00:06:58 +01:00
Teemu R.
9966c6094a
Add ssltransport for robovacs (#943)
This PR implements a clear-text, token-based transport protocol seen on
RV30 Plus (#937).

- Client sends `{"username": "email@example.com", "password":
md5(password)}` and gets back a token in the response
- Rest of the communications are done with POST at `/app?token=<token>`

---------

Co-authored-by: Steven B. <51370195+sdb9696@users.noreply.github.com>
2024-12-01 18:06:48 +01:00
Steven B.
5ef8f21b4d
Handle missing mgt_encryption_schm in discovery (#1318) 2024-11-29 15:23:16 +00:00
Teemu R.
f2ba23301a
Make discovery on unsupported devices less noisy (#1291) 2024-11-21 18:22:54 +00:00
Steven B.
2683623997
Update DiscoveryResult to use mashu Annotated Alias (#1279) 2024-11-19 19:09:50 +00:00
Steven B.
a01247d48f
Remove support for python <3.11 (#1273)
Python 3.11 ships with latest Debian Bookworm. 
pypy is not that widely used with this library based on statistics. It could be added back when pypy supports python 3.11.
2024-11-18 18:46:36 +00:00
Steven B.
b8f6651d9b
Remove experimental support (#1256) 2024-11-14 15:55:02 +01:00
Steven B.
e55731c110
Move protocol modules into protocols package (#1254) 2024-11-13 17:50:21 +00:00
Steven B.
254a9af5c1
Update DiscoveryResult to use Mashumaro instead of pydantic (#1231)
Mashumaro is faster and doesn't come with all versioning problems that
pydantic does.

A basic perf test deserializing all of our discovery results fixtures
shows mashumaro as being about 6 times faster deserializing dicts than
pydantic. It's much faster parsing from a json string but that's likely
because it uses orjson under the hood although that's not really our use
case at the moment.

```
PYDANTIC - ms
=================
json       dict
-----------------
4.7665     1.3268
3.1548     1.5922
3.1130     1.8039
4.2834     2.7606
2.0669     1.3757
2.0163     1.6377
3.1667     1.3561
4.1296     2.7297
2.0132     1.3471
4.0648     1.4105

MASHUMARO - ms
=================
json       dict
-----------------
0.5977     0.5543
0.5336     0.2983
0.3955     0.2549
0.6516     0.2742
0.5386     0.2706
0.6678     0.2580
0.4120     0.2511
0.3836     0.2472
0.4020     0.2465
0.4268     0.2487
```
2024-11-12 22:00:04 +01:00
Teemu R.
668ba748c5
Move transports into their own package (#1247)
This moves all transport implementations into a new `transports` package
for cleaner main package & easier to understand project structure.
2024-11-12 14:40:44 +01:00
Teemu R.
66eb17057e
Enable ruff check for ANN (#1139) 2024-11-10 18:55:13 +00:00
Steven B.
77b654a9aa
Update try_connect_all to be more efficient and report attempts (#1222) 2024-11-01 18:17:18 +00:00
Steven B.
6d8dc1cc5f
Only send 20002 discovery request with key included (#1207) 2024-10-29 16:21:24 +00:00
Steven B.
88b7951fee
Allow passing an aiohttp client session during discover try_connect_all (#1198) 2024-10-25 19:43:37 +01:00
Steven B.
048c84d72c
Add https parameter to device class factory (#1184)
`SMART.TAPOHUB` resolves to different device classes based on the https value
2024-10-22 18:09:35 +01:00
Steven B.
3c865b5fb6
Add try_connect_all to allow initialisation without udp broadcast (#1171)
- Try all valid combinations of protocol/transport/device class and attempt to connect. 
- Add cli command `discover config` to return the connection options after connecting via `try_connect_all`.
- The cli command does not return the actual device for processing as this is not a recommended way to regularly connect to devices.
2024-10-22 14:33:46 +01:00
Steven B.
dcc36e1dfe
Initial TapoCamera support (#1165)
Adds experimental support for the Tapo Camera protocol also used by the H200 hub.
Creates a new SslAesTransport and a derived SmartCamera and SmartCameraProtocol.
2024-10-16 16:53:52 +01:00
Steven B.
380fbb93c3
Enable newer encrypted discovery protocol (#1168) 2024-10-16 15:28:27 +01:00
Steven B.
81e2685605
Send empty dictionary instead of null for iot queries (#1145) 2024-10-01 12:47:36 +01:00
Teemu R.
3e43781bb2
Add flake8-logging (LOG) and flake8-logging-format (G) for ruff (#1104)
Enables rules LOG (flake8-logging) and G (flake8-logging-format) for
ruff. This will catch eager log message formatting, among other similar
issues.
2024-08-30 16:13:14 +02:00
Steven B.
7416e855f1
Fix mypy pre-commit hook on windows (#1081) 2024-07-25 09:11:48 +01:00
Steven B.
c4f015a2fb
Redact sensitive info from debug logs (#1069)
Redacts sensitive data when debug logging device responses such as mac,
location and usernames
2024-07-17 19:57:09 +02:00
Teemu R
472008e818
Drop python3.8 support (#992)
Drop support for soon-to-be eol'd python 3.8.
This will allow some minor cleanups & makes it easier to add support for
timezones.

Related to
https://github.com/python-kasa/python-kasa/issues/980#issuecomment-2170889543
2024-06-19 20:24:12 +02:00
Steven B
be5202ccb7
Make device initialisation easier by reducing required imports (#936)
Adds username and password arguments to discovery to remove the need to import Credentials.
Creates TypeAliases in Device for connection configuration classes and DeviceType.
Using the API with these changes will only require importing either Discover or Device
depending on whether using Discover.discover() or Device.connect() to 
initialize and interact with the API.
2024-06-03 19:06:54 +01:00
Steven B
6616d68d42
Update documentation structure and start migrating to markdown (#934)
Starts structuring the documentation library usage into Tutorials, Guides, Explanations and Reference.
Continues migrating new docs from rst to markdown.
Extends the test framework discovery mocks to allow easy writing and testing of code examples.
2024-06-03 10:14:10 +01:00
Steven B
3490a1ef84
Add tutorial doctest module and enable top level await (#919)
Add a tutorial module with examples that can be tested with `doctest`.

In order to simplify the examples they can be run with doctest allowing
top level await statements by adding a fixture to patch the builtins
that xdoctest uses to test code.

---------

Co-authored-by: Teemu R. <tpr@iki.fi>
2024-05-16 18:13:44 +02:00
Teemu R
46338ee21d
Use pydantic.v1 namespace on all pydantic versions (#883)
With https://github.com/pydantic/pydantic/pull/9042 being shipped with
[1.10.15](https://docs.pydantic.dev/latest/changelog/#v11015-2024-04-03),
we can clean up the imports a bit until we make decisions how to move
onward with or without pydantic.

---------

Co-authored-by: Steven B. <51370195+sdb9696@users.noreply.github.com>
2024-05-01 15:59:35 +02:00
Steven B
203bd79253
Enable and convert to future annotations (#838) 2024-04-17 15:39:24 +02:00
Steven B
da441bc697
Update poetry locks and pre-commit hooks (#837)
Also updates CI pypy versions to be 3.9 and 3.10 which are the currently
[supported
versions](https://www.pypy.org/posts/2024/01/pypy-v7315-release.html).
Otherwise latest cryptography doesn't ship with pypy3.8 wheels and is
unable to build on windows.

Also updates the `codecov-action` to v4 which fixed some intermittent
uploading errors.
2024-04-16 20:21:20 +02:00
Steven B
8c39e81a40
Rename and deprecate exception classes (#739)
# Public #
SmartDeviceException -> KasaException
UnsupportedDeviceException(SmartDeviceException) -> UnsupportedDeviceError(KasaException)
TimeoutException(SmartDeviceException, asyncio.TimeoutError) -> TimeoutError(KasaException, asyncio.TimeoutError)

Add new exception for error codes -> DeviceError(KasaException)
AuthenticationException(SmartDeviceException) -> AuthenticationError(DeviceError)

# Internal #
RetryableException(SmartDeviceException) -> _RetryableError(DeviceError)
ConnectionException(SmartDeviceException) -> _ConnectionError(KasaException)
2024-02-21 16:52:55 +01:00
Steven B
215b8d4e4f
Fix discovery cli to print devices not printed during discovery timeout (#670)
* Fix discovery cli to print devices not printed during discovery

* Fix tests

* Fix print exceptions not being propagated

* Fix tests

* Reduce test discover_send time

* Simplify wait logic

* Add tests

* Remove sleep loop and make auth failed a list
2024-02-05 17:53:09 +00:00
Steven B
0d119e63d0
Refactor devices into subpackages and deprecate old names (#716)
* Refactor devices into subpackages and deprecate old names

* Tweak and add tests

* Fix linting

* Remove duplicate implementations affecting project coverage

* Update post review

* Add device base class attributes and rename subclasses

* Rename Module to BaseModule

* Remove has_emeter_history

* Fix missing _time in init

* Update post review

* Fix test_readmeexamples

* Fix erroneously duped files

* Clean up iot and smart imports

* Update post latest review

* Tweak Device docstring
2024-02-04 16:20:08 +01:00
Steven B
0d0f56414c
Switch from TPLinkSmartHomeProtocol to IotProtocol/XorTransport (#710)
* Switch from TPLinkSmartHomeProtocol to IotProtocol/XorTransport

* Add test

* Update docs

* Fix ruff deleting deprecated import
2024-01-26 09:11:31 +00:00
Steven B
ee487ad837
Sleep between discovery packets (#656)
* Sleep between discovery packets

* Add tests
2024-01-22 18:25:23 +01:00
Steven B
fbce755544
Raise TimeoutException on discover_single timeout (#632) 2024-01-11 16:13:44 +01:00
Steven B
5b8280a8d9
Return alias as None for new discovery devices before update (#627)
* Trim the length of the unavailable device alias

* Update to use short mac as auth required alias

* Update to return alias as none
2024-01-11 16:12:02 +01:00
Steven B
3e0cd07b7c
Update docs for newer devices and DeviceConfig (#614)
* Update docs for newer devices and DeviceConfig

* Tweak docs post review

* Move sentence to newline

* Update post review

* Update following review
2024-01-10 20:13:14 +01:00
sdb9696
e9bf9f58ee
Allow serializing and passing of credentials_hashes in DeviceConfig (#607)
* Allow passing of credentials_hashes in DeviceConfig

* Update following review
2024-01-03 22:46:08 +01:00
sdb9696
f6fd898faf
Add DeviceConfig to allow specifying configuration parameters (#569)
* Add DeviceConfig handling

* Update post review

* Further update post latest review

* Update following latest review

* Update docstrings and docs
2023-12-29 20:17:15 +01:00
sdb9696
209391c422
Improve CLI Discovery output (#583)
- Show discovery results for unsupported devices and devices that fail to authenticate.
- Rename `--show-unsupported` to `--verbose`.
- Remove separate `--timeout` parameter from cli discovery so it's not confused with `--timeout` now added to cli command.
- Add tests.
2023-12-19 13:50:33 +01:00
sdb9696
4a00199506
Add klap support for TAPO protocol by splitting out Transports and Protocols (#557)
* Add support for TAPO/SMART KLAP and seperate transports from protocols

* Add tests and some review changes

* Update following review

* Updates following review
2023-12-04 19:50:05 +01:00
sdb9696
63d64ad920
Add support for the protocol used by TAPO devices and some newer KASA devices. (#552)
* Add Tapo protocol support

* Update get_device_instance and test_unsupported following review
2023-11-30 13:10:49 +01:00
sdb9696
9de3f69033
Update dump_devinfo to include 20002 discovery results (#556)
* Fix dump_devinfo and add discovery_result to json

* Update following review.  Do not serialize aliases.

* Delete kasa/tests/fixtures/HS100(UK)_1.0_1.2.6.json
2023-11-29 20:01:20 +01:00
J. Nick Koston
e98252ff17
Move connect_single to SmartDevice.connect (#538)
This refactors `Discover.connect_single` by moving device instance construction into a separate device factory module.
New `SmartDevice.connect(host, *, port, timeout, credentials, device_type)` class method replaces the functionality of `connect_single`,
and also now allows constructing device instances without relying on UDP discovery for type discovery if `device_type` parameter is set.

---------

Co-authored-by: Teemu R. <tpr@iki.fi>
2023-11-21 23:48:53 +01:00
sdb9696
27c4799adc
Do not do update() in discover_single (#542) 2023-11-21 21:58:41 +01:00