Compare commits

..

15 Commits

Author SHA1 Message Date
ZeliardM
579fd5aa2a
Add LB100(US)_1.0_1.8.11 fixture file (#1515)
Some checks failed
CI / Perform linting checks (3.13) (push) Has been cancelled
CodeQL checks / Analyze (python) (push) Has been cancelled
CI / Python 3.11 on macos-latest (push) Has been cancelled
CI / Python 3.12 on macos-latest (push) Has been cancelled
CI / Python 3.13 on macos-latest (push) Has been cancelled
CI / Python 3.11 on ubuntu-latest (push) Has been cancelled
CI / Python 3.12 on ubuntu-latest (push) Has been cancelled
CI / Python 3.13 on ubuntu-latest (push) Has been cancelled
CI / Python 3.11 on windows-latest (push) Has been cancelled
CI / Python 3.12 on windows-latest (push) Has been cancelled
CI / Python 3.13 on windows-latest (push) Has been cancelled
Stale / stale (push) Has been cancelled
The LB100 was already in the device_fixtures.py for tests, but was not
listed in the supported devices nor did it have a fixture file.
2025-03-04 08:16:47 +01:00
Teemu R.
8501390c61
Add a note to emeter guide being kasa-only (#1512)
Some checks failed
CI / Perform linting checks (3.13) (push) Has been cancelled
CodeQL checks / Analyze (python) (push) Has been cancelled
CI / Python 3.11 on macos-latest (push) Has been cancelled
CI / Python 3.12 on macos-latest (push) Has been cancelled
CI / Python 3.13 on macos-latest (push) Has been cancelled
CI / Python 3.11 on ubuntu-latest (push) Has been cancelled
CI / Python 3.12 on ubuntu-latest (push) Has been cancelled
CI / Python 3.13 on ubuntu-latest (push) Has been cancelled
CI / Python 3.11 on windows-latest (push) Has been cancelled
CI / Python 3.12 on windows-latest (push) Has been cancelled
CI / Python 3.13 on windows-latest (push) Has been cancelled
Related to #1511
2025-02-25 22:44:44 +00:00
ZeliardM
f0abc2800d
Add KS225(US)_1.0_1.1.1 and L930-5(EU)_1.0_1.2.5 (#1509)
Some checks are pending
CI / Perform linting checks (3.13) (push) Waiting to run
CI / Python 3.11 on macos-latest (push) Blocked by required conditions
CI / Python 3.12 on macos-latest (push) Blocked by required conditions
CI / Python 3.13 on macos-latest (push) Blocked by required conditions
CI / Python 3.11 on ubuntu-latest (push) Blocked by required conditions
CI / Python 3.12 on ubuntu-latest (push) Blocked by required conditions
CI / Python 3.13 on ubuntu-latest (push) Blocked by required conditions
CI / Python 3.11 on windows-latest (push) Blocked by required conditions
CI / Python 3.12 on windows-latest (push) Blocked by required conditions
CI / Python 3.13 on windows-latest (push) Blocked by required conditions
CodeQL checks / Analyze (python) (push) Waiting to run
Added fixture files, one device was added directly into HomeKit, and one
device was added through Matter from the obd_src. I'm not sure if that
makes a difference for you, but the devices are working correctly
through my plug-in with the latest python-kasa 0.10.2.
2025-02-24 20:42:12 +01:00
Steven B.
f488492c7d
Prepare 0.10.2 (#1505)
Some checks failed
CI / Perform linting checks (3.13) (push) Has been cancelled
CodeQL checks / Analyze (python) (push) Has been cancelled
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, macos-latest, 3.11) (push) Has been cancelled
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, macos-latest, 3.12) (push) Has been cancelled
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, macos-latest, 3.13) (push) Has been cancelled
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, ubuntu-latest, 3.11) (push) Has been cancelled
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, ubuntu-latest, 3.12) (push) Has been cancelled
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, ubuntu-latest, 3.13) (push) Has been cancelled
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, windows-latest, 3.11) (push) Has been cancelled
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, windows-latest, 3.12) (push) Has been cancelled
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, windows-latest, 3.13) (push) Has been cancelled
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (true, ubuntu-latest, 3.11) (push) Has been cancelled
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (true, ubuntu-latest, 3.12) (push) Has been cancelled
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (true, ubuntu-latest, 3.13) (push) Has been cancelled
Stale / stale (push) Has been cancelled
## [0.10.2](https://github.com/python-kasa/python-kasa/tree/0.10.2) (2025-02-12)

[Full Changelog](https://github.com/python-kasa/python-kasa/compare/0.10.1...0.10.2)

**Release summary:**

- Bugfix for [#1499](https://github.com/python-kasa/python-kasa/issues/1499).
- Support for L530B and C110 devices.

**Fixed bugs:**

- H100 - Raised error: not enough values to unpack \(expected 2, got 1\) [\#1499](https://github.com/python-kasa/python-kasa/issues/1499)
- Do not crash on missing build number in fw version [\#1500](https://github.com/python-kasa/python-kasa/pull/1500) (@rytilahti)

**Added support for devices:**

- Add C110\(EU\) 2.0 1.4.3 fixture [\#1503](https://github.com/python-kasa/python-kasa/pull/1503) (@sdb9696)
- Add L530B\(EU\) 3.0 1.1.9 fixture [\#1502](https://github.com/python-kasa/python-kasa/pull/1502) (@sdb9696)

**Project maintenance:**

- Add fixtures for new versions of H100, P110, and T100 devices [\#1501](https://github.com/python-kasa/python-kasa/pull/1501) (@LXGaming)
- Add L530E\(TW\) 2.0 1.1.1 fixture [\#1497](https://github.com/python-kasa/python-kasa/pull/1497) (@bluehomewu)
2025-02-12 19:29:44 +00:00
Alex Thomson
29195fa639
Add fixtures for new versions of H100, P110, and T100 devices (#1501)
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
2025-02-12 11:45:53 +00:00
Steven B.
8b138698b8
Add C110(EU) 2.0 1.4.3 fixture (#1503) 2025-02-12 11:41:16 +00:00
Steven B.
ad8a0eebec
Add L530B(EU) 3.0 1.1.9 fixture (#1502) 2025-02-12 11:38:39 +00:00
Teemu R.
668e32d3a5
Do not crash on missing build number in fw version (#1500)
Some checks failed
CI / Perform linting checks (3.13) (push) Has been cancelled
CodeQL checks / Analyze (python) (push) Has been cancelled
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, macos-latest, 3.11) (push) Has been cancelled
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, macos-latest, 3.12) (push) Has been cancelled
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, macos-latest, 3.13) (push) Has been cancelled
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, ubuntu-latest, 3.11) (push) Has been cancelled
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, ubuntu-latest, 3.12) (push) Has been cancelled
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, ubuntu-latest, 3.13) (push) Has been cancelled
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, windows-latest, 3.11) (push) Has been cancelled
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, windows-latest, 3.12) (push) Has been cancelled
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, windows-latest, 3.13) (push) Has been cancelled
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (true, ubuntu-latest, 3.11) (push) Has been cancelled
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (true, ubuntu-latest, 3.12) (push) Has been cancelled
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (true, ubuntu-latest, 3.13) (push) Has been cancelled
Stale / stale (push) Has been cancelled
Co-authored-by: Steven B <51370195+sdb9696@users.noreply.github.com>
2025-02-10 11:13:01 +00:00
EdwardWu
d5187dc6f1
Add L530E(TW) 2.0 1.1.1 fixture (#1497)
Some checks failed
CI / Perform linting checks (3.13) (push) Has been cancelled
CodeQL checks / Analyze (python) (push) Has been cancelled
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, macos-latest, 3.11) (push) Has been cancelled
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, macos-latest, 3.12) (push) Has been cancelled
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, macos-latest, 3.13) (push) Has been cancelled
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, ubuntu-latest, 3.11) (push) Has been cancelled
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, ubuntu-latest, 3.12) (push) Has been cancelled
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, ubuntu-latest, 3.13) (push) Has been cancelled
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, windows-latest, 3.11) (push) Has been cancelled
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, windows-latest, 3.12) (push) Has been cancelled
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, windows-latest, 3.13) (push) Has been cancelled
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (true, ubuntu-latest, 3.11) (push) Has been cancelled
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (true, ubuntu-latest, 3.12) (push) Has been cancelled
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (true, ubuntu-latest, 3.13) (push) Has been cancelled
2025-02-07 08:02:21 +00:00
Steven B.
cbab40a59e
Prepare 0.10.1 (#1494)
Some checks failed
CI / Perform linting checks (3.13) (push) Has been cancelled
CodeQL checks / Analyze (python) (push) Has been cancelled
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, macos-latest, 3.11) (push) Has been cancelled
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, macos-latest, 3.12) (push) Has been cancelled
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, macos-latest, 3.13) (push) Has been cancelled
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, ubuntu-latest, 3.11) (push) Has been cancelled
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, ubuntu-latest, 3.12) (push) Has been cancelled
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, ubuntu-latest, 3.13) (push) Has been cancelled
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, windows-latest, 3.11) (push) Has been cancelled
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, windows-latest, 3.12) (push) Has been cancelled
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, windows-latest, 3.13) (push) Has been cancelled
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (true, ubuntu-latest, 3.11) (push) Has been cancelled
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (true, ubuntu-latest, 3.12) (push) Has been cancelled
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (true, ubuntu-latest, 3.13) (push) Has been cancelled
## [0.10.1](https://github.com/python-kasa/python-kasa/tree/0.10.1) (2025-02-02)

[Full Changelog](https://github.com/python-kasa/python-kasa/compare/0.10.0...0.10.1)

**Release summary:**

Small patch release for bugfixes

**Implemented enhancements:**

- dustbin\_mode: add 'off' mode for cleaner downstream impl [\#1488](https://github.com/python-kasa/python-kasa/pull/1488) (@rytilahti)
- Add Dimmer Configuration Support [\#1484](https://github.com/python-kasa/python-kasa/pull/1484) (@ryenitcher)

**Fixed bugs:**

- Do not return empty string for custom light effect name [\#1491](https://github.com/python-kasa/python-kasa/pull/1491) (@sdb9696)
- Add FeatureAttributes to smartcam Alarm [\#1489](https://github.com/python-kasa/python-kasa/pull/1489) (@sdb9696)

**Project maintenance:**

- Add module.device to the public api [\#1478](https://github.com/python-kasa/python-kasa/pull/1478) (@sdb9696)
2025-02-02 14:02:19 +00:00
Ryan Nitcher
bff5409d22
Add Dimmer Configuration Support (#1484) 2025-02-02 13:48:34 +00:00
Teemu R.
8259d28b12
dustbin_mode: add 'off' mode for cleaner downstream impl (#1488)
Adds a new artificial "Off" mode for dustbin_mode,
which will allow avoiding the need to expose both a toggle and a select
in homeassistant.

This changes the behavior of the existing mode selection, as it is not
anymore possible to change the mode without activating the auto
collection.

* Mode is Off, if auto collection has been disabled
* When setting mode to "Off", this will disable the auto collection
* When setting mode to anything else than "Off", the auto collection
will be automatically enabled.
2025-02-02 14:00:49 +01:00
Steven B.
44c561b04d
Add FeatureAttributes to smartcam Alarm (#1489)
Some checks failed
CI / Perform linting checks (3.13) (push) Has been cancelled
CodeQL checks / Analyze (python) (push) Has been cancelled
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, macos-latest, 3.11) (push) Has been cancelled
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, macos-latest, 3.12) (push) Has been cancelled
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, macos-latest, 3.13) (push) Has been cancelled
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, ubuntu-latest, 3.11) (push) Has been cancelled
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, ubuntu-latest, 3.12) (push) Has been cancelled
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, ubuntu-latest, 3.13) (push) Has been cancelled
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, windows-latest, 3.11) (push) Has been cancelled
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, windows-latest, 3.12) (push) Has been cancelled
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, windows-latest, 3.13) (push) Has been cancelled
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (true, ubuntu-latest, 3.11) (push) Has been cancelled
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (true, ubuntu-latest, 3.12) (push) Has been cancelled
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (true, ubuntu-latest, 3.13) (push) Has been cancelled
Co-authored-by: Teemu R. <tpr@iki.fi>
2025-01-29 19:32:01 +00:00
Steven B.
ebd370da74
Add module.device to the public api (#1478) 2025-01-29 19:49:38 +01:00
Steven B.
82fbe1226e
Do not return empty string for custom light effect name (#1491) 2025-01-29 18:49:06 +00:00
42 changed files with 5441 additions and 281 deletions

View File

@ -2,7 +2,7 @@ repos:
- repo: https://github.com/astral-sh/uv-pre-commit - repo: https://github.com/astral-sh/uv-pre-commit
# uv version. # uv version.
rev: 0.5.24 rev: 0.5.30
hooks: hooks:
# Update the uv lockfile # Update the uv lockfile
- id: uv-lock - id: uv-lock
@ -22,7 +22,7 @@ repos:
- "--indent=4" - "--indent=4"
- repo: https://github.com/astral-sh/ruff-pre-commit - repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.9.3 rev: v0.9.6
hooks: hooks:
- id: ruff - id: ruff
args: [--fix, --exit-non-zero-on-fix] args: [--fix, --exit-non-zero-on-fix]

View File

@ -1,5 +1,51 @@
# Changelog # Changelog
## [0.10.2](https://github.com/python-kasa/python-kasa/tree/0.10.2) (2025-02-12)
[Full Changelog](https://github.com/python-kasa/python-kasa/compare/0.10.1...0.10.2)
**Release summary:**
- Bugfix for [#1499](https://github.com/python-kasa/python-kasa/issues/1499).
- Support for L530B and C110 devices.
**Fixed bugs:**
- H100 - Raised error: not enough values to unpack \(expected 2, got 1\) [\#1499](https://github.com/python-kasa/python-kasa/issues/1499)
- Do not crash on missing build number in fw version [\#1500](https://github.com/python-kasa/python-kasa/pull/1500) (@rytilahti)
**Added support for devices:**
- Add C110\(EU\) 2.0 1.4.3 fixture [\#1503](https://github.com/python-kasa/python-kasa/pull/1503) (@sdb9696)
- Add L530B\(EU\) 3.0 1.1.9 fixture [\#1502](https://github.com/python-kasa/python-kasa/pull/1502) (@sdb9696)
**Project maintenance:**
- Add fixtures for new versions of H100, P110, and T100 devices [\#1501](https://github.com/python-kasa/python-kasa/pull/1501) (@LXGaming)
- Add L530E\(TW\) 2.0 1.1.1 fixture [\#1497](https://github.com/python-kasa/python-kasa/pull/1497) (@bluehomewu)
## [0.10.1](https://github.com/python-kasa/python-kasa/tree/0.10.1) (2025-02-02)
[Full Changelog](https://github.com/python-kasa/python-kasa/compare/0.10.0...0.10.1)
**Release summary:**
Small patch release for bugfixes
**Implemented enhancements:**
- dustbin\_mode: add 'off' mode for cleaner downstream impl [\#1488](https://github.com/python-kasa/python-kasa/pull/1488) (@rytilahti)
- Add Dimmer Configuration Support [\#1484](https://github.com/python-kasa/python-kasa/pull/1484) (@ryenitcher)
**Fixed bugs:**
- Do not return empty string for custom light effect name [\#1491](https://github.com/python-kasa/python-kasa/pull/1491) (@sdb9696)
- Add FeatureAttributes to smartcam Alarm [\#1489](https://github.com/python-kasa/python-kasa/pull/1489) (@sdb9696)
**Project maintenance:**
- Add module.device to the public api [\#1478](https://github.com/python-kasa/python-kasa/pull/1478) (@sdb9696)
## [0.10.0](https://github.com/python-kasa/python-kasa/tree/0.10.0) (2025-01-26) ## [0.10.0](https://github.com/python-kasa/python-kasa/tree/0.10.0) (2025-01-26)
[Full Changelog](https://github.com/python-kasa/python-kasa/compare/0.9.1...0.10.0) [Full Changelog](https://github.com/python-kasa/python-kasa/compare/0.9.1...0.10.0)
@ -31,11 +77,7 @@ Many thanks to testers and new contributors - @steveredden, @DawidPietrykowski,
- Expose more battery sensors for D230 [\#1451](https://github.com/python-kasa/python-kasa/issues/1451) - Expose more battery sensors for D230 [\#1451](https://github.com/python-kasa/python-kasa/issues/1451)
- dumping HTTP POST Body for Tapo Vacuum \(RV30 Plus\) [\#937](https://github.com/python-kasa/python-kasa/issues/937) - dumping HTTP POST Body for Tapo Vacuum \(RV30 Plus\) [\#937](https://github.com/python-kasa/python-kasa/issues/937)
- Add common alarm interface [\#1479](https://github.com/python-kasa/python-kasa/pull/1479) (@sdb9696)
- Add common childsetup interface [\#1470](https://github.com/python-kasa/python-kasa/pull/1470) (@sdb9696)
- Add childsetup module to smartcam hubs [\#1469](https://github.com/python-kasa/python-kasa/pull/1469) (@sdb9696)
- Add smartcam pet detection toggle module [\#1465](https://github.com/python-kasa/python-kasa/pull/1465) (@DawidPietrykowski) - Add smartcam pet detection toggle module [\#1465](https://github.com/python-kasa/python-kasa/pull/1465) (@DawidPietrykowski)
- Only log one warning per unknown clean error code and status [\#1462](https://github.com/python-kasa/python-kasa/pull/1462) (@rytilahti)
- Add childlock module for vacuums [\#1461](https://github.com/python-kasa/python-kasa/pull/1461) (@rytilahti) - Add childlock module for vacuums [\#1461](https://github.com/python-kasa/python-kasa/pull/1461) (@rytilahti)
- Add ultra mode \(fanspeed = 5\) for vacuums [\#1459](https://github.com/python-kasa/python-kasa/pull/1459) (@rytilahti) - Add ultra mode \(fanspeed = 5\) for vacuums [\#1459](https://github.com/python-kasa/python-kasa/pull/1459) (@rytilahti)
- Add setting to change carpet clean mode [\#1458](https://github.com/python-kasa/python-kasa/pull/1458) (@rytilahti) - Add setting to change carpet clean mode [\#1458](https://github.com/python-kasa/python-kasa/pull/1458) (@rytilahti)
@ -46,49 +88,53 @@ Many thanks to testers and new contributors - @steveredden, @DawidPietrykowski,
- Add battery module to smartcam devices [\#1452](https://github.com/python-kasa/python-kasa/pull/1452) (@sdb9696) - Add battery module to smartcam devices [\#1452](https://github.com/python-kasa/python-kasa/pull/1452) (@sdb9696)
- Allow update of camera modules after setting values [\#1450](https://github.com/python-kasa/python-kasa/pull/1450) (@sdb9696) - Allow update of camera modules after setting values [\#1450](https://github.com/python-kasa/python-kasa/pull/1450) (@sdb9696)
- Update hub children on first update and delay subsequent updates [\#1438](https://github.com/python-kasa/python-kasa/pull/1438) (@sdb9696) - Update hub children on first update and delay subsequent updates [\#1438](https://github.com/python-kasa/python-kasa/pull/1438) (@sdb9696)
- Add support for doorbells and chimes [\#1435](https://github.com/python-kasa/python-kasa/pull/1435) (@steveredden)
- Implement vacuum dustbin module \(dust\_bucket\) [\#1423](https://github.com/python-kasa/python-kasa/pull/1423) (@rytilahti) - Implement vacuum dustbin module \(dust\_bucket\) [\#1423](https://github.com/python-kasa/python-kasa/pull/1423) (@rytilahti)
- Allow https for klaptransport [\#1415](https://github.com/python-kasa/python-kasa/pull/1415) (@rytilahti)
- Add smartcam child device support for smartcam hubs [\#1413](https://github.com/python-kasa/python-kasa/pull/1413) (@sdb9696) - Add smartcam child device support for smartcam hubs [\#1413](https://github.com/python-kasa/python-kasa/pull/1413) (@sdb9696)
- Add powerprotection module [\#1337](https://github.com/python-kasa/python-kasa/pull/1337) (@rytilahti)
- Add vacuum speaker controls [\#1332](https://github.com/python-kasa/python-kasa/pull/1332) (@rytilahti) - Add vacuum speaker controls [\#1332](https://github.com/python-kasa/python-kasa/pull/1332) (@rytilahti)
- Add consumables module for vacuums [\#1327](https://github.com/python-kasa/python-kasa/pull/1327) (@rytilahti) - Add consumables module for vacuums [\#1327](https://github.com/python-kasa/python-kasa/pull/1327) (@rytilahti)
- Add ADC Value to PIR Enabled Switches [\#1263](https://github.com/python-kasa/python-kasa/pull/1263) (@ryenitcher) - Add ADC Value to PIR Enabled Switches [\#1263](https://github.com/python-kasa/python-kasa/pull/1263) (@ryenitcher)
- Add support for cleaning records [\#945](https://github.com/python-kasa/python-kasa/pull/945) (@rytilahti) - Add support for cleaning records [\#945](https://github.com/python-kasa/python-kasa/pull/945) (@rytilahti)
- Initial support for vacuums \(clean module\) [\#944](https://github.com/python-kasa/python-kasa/pull/944) (@rytilahti) - Initial support for vacuums \(clean module\) [\#944](https://github.com/python-kasa/python-kasa/pull/944) (@rytilahti)
- Add support for pairing devices with hubs [\#859](https://github.com/python-kasa/python-kasa/pull/859) (@rytilahti) - Add support for pairing devices with hubs [\#859](https://github.com/python-kasa/python-kasa/pull/859) (@rytilahti)
- Add common alarm interface [\#1479](https://github.com/python-kasa/python-kasa/pull/1479) (@sdb9696)
- Add common childsetup interface [\#1470](https://github.com/python-kasa/python-kasa/pull/1470) (@sdb9696)
- Add childsetup module to smartcam hubs [\#1469](https://github.com/python-kasa/python-kasa/pull/1469) (@sdb9696)
- Only log one warning per unknown clean error code and status [\#1462](https://github.com/python-kasa/python-kasa/pull/1462) (@rytilahti)
- Add support for doorbells and chimes [\#1435](https://github.com/python-kasa/python-kasa/pull/1435) (@steveredden)
- Allow https for klaptransport [\#1415](https://github.com/python-kasa/python-kasa/pull/1415) (@rytilahti)
- Add powerprotection module [\#1337](https://github.com/python-kasa/python-kasa/pull/1337) (@rytilahti)
**Fixed bugs:** **Fixed bugs:**
- TP-Link HS300 Wi-Fi Power-Strip - "Parent On/Off" not functioning. [\#637](https://github.com/python-kasa/python-kasa/issues/637) - TP-Link HS300 Wi-Fi Power-Strip - "Parent On/Off" not functioning. [\#637](https://github.com/python-kasa/python-kasa/issues/637)
- Convert carpet\_clean\_mode to carpet\_boost switch [\#1486](https://github.com/python-kasa/python-kasa/pull/1486) (@rytilahti)
- Change category for empty dustbin feature from Primary to Config [\#1485](https://github.com/python-kasa/python-kasa/pull/1485) (@rytilahti)
- Report 0 for instead of None for zero current and voltage [\#1483](https://github.com/python-kasa/python-kasa/pull/1483) (@ryenitcher) - Report 0 for instead of None for zero current and voltage [\#1483](https://github.com/python-kasa/python-kasa/pull/1483) (@ryenitcher)
- Disable iot camera creation until more complete [\#1480](https://github.com/python-kasa/python-kasa/pull/1480) (@sdb9696)
- ssltransport: use debug logger for sending requests [\#1443](https://github.com/python-kasa/python-kasa/pull/1443) (@rytilahti) - ssltransport: use debug logger for sending requests [\#1443](https://github.com/python-kasa/python-kasa/pull/1443) (@rytilahti)
- Fix discover cli command with host [\#1437](https://github.com/python-kasa/python-kasa/pull/1437) (@sdb9696) - Fix discover cli command with host [\#1437](https://github.com/python-kasa/python-kasa/pull/1437) (@sdb9696)
- Fallback to is\_low for batterysensor's battery\_low [\#1420](https://github.com/python-kasa/python-kasa/pull/1420) (@rytilahti) - Fallback to is\_low for batterysensor's battery\_low [\#1420](https://github.com/python-kasa/python-kasa/pull/1420) (@rytilahti)
- Convert carpet\_clean\_mode to carpet\_boost switch [\#1486](https://github.com/python-kasa/python-kasa/pull/1486) (@rytilahti)
- Change category for empty dustbin feature from Primary to Config [\#1485](https://github.com/python-kasa/python-kasa/pull/1485) (@rytilahti)
- Disable iot camera creation until more complete [\#1480](https://github.com/python-kasa/python-kasa/pull/1480) (@sdb9696)
- Add error code 7 for clean module [\#1474](https://github.com/python-kasa/python-kasa/pull/1474) (@rytilahti)
- Fix iot strip turn on and off from parent [\#639](https://github.com/python-kasa/python-kasa/pull/639) (@Obbay2) - Fix iot strip turn on and off from parent [\#639](https://github.com/python-kasa/python-kasa/pull/639) (@Obbay2)
**Added support for devices:** **Added support for devices:**
- Add D130\(US\) 1.0 1.1.9 fixture [\#1476](https://github.com/python-kasa/python-kasa/pull/1476) (@sdb9696)
- Add D100C\(US\) 1.0 1.1.3 fixture [\#1475](https://github.com/python-kasa/python-kasa/pull/1475) (@sdb9696)
- Add C220\(EU\) 1.0 1.2.2 camera fixture [\#1466](https://github.com/python-kasa/python-kasa/pull/1466) (@DawidPietrykowski) - Add C220\(EU\) 1.0 1.2.2 camera fixture [\#1466](https://github.com/python-kasa/python-kasa/pull/1466) (@DawidPietrykowski)
- Add D230\(EU\) 1.20 1.1.19 fixture [\#1448](https://github.com/python-kasa/python-kasa/pull/1448) (@sdb9696) - Add D230\(EU\) 1.20 1.1.19 fixture [\#1448](https://github.com/python-kasa/python-kasa/pull/1448) (@sdb9696)
- Add fixture for C720 camera [\#1433](https://github.com/python-kasa/python-kasa/pull/1433) (@steveredden) - Add fixture for C720 camera [\#1433](https://github.com/python-kasa/python-kasa/pull/1433) (@steveredden)
- Add D130\(US\) 1.0 1.1.9 fixture [\#1476](https://github.com/python-kasa/python-kasa/pull/1476) (@sdb9696)
- Add D100C\(US\) 1.0 1.1.3 fixture [\#1475](https://github.com/python-kasa/python-kasa/pull/1475) (@sdb9696)
**Project maintenance:** **Project maintenance:**
- Update ruff to 0.9 [\#1482](https://github.com/python-kasa/python-kasa/pull/1482) (@sdb9696)
- Cancel in progress CI workflows after new pushes [\#1481](https://github.com/python-kasa/python-kasa/pull/1481) (@sdb9696)
- Update test framework to support smartcam device discovery. [\#1477](https://github.com/python-kasa/python-kasa/pull/1477) (@sdb9696)
- Add error code 7 for clean module [\#1474](https://github.com/python-kasa/python-kasa/pull/1474) (@rytilahti)
- Enable CI workflow on PRs to feat/ fix/ and janitor/ [\#1471](https://github.com/python-kasa/python-kasa/pull/1471) (@sdb9696) - Enable CI workflow on PRs to feat/ fix/ and janitor/ [\#1471](https://github.com/python-kasa/python-kasa/pull/1471) (@sdb9696)
- Add commit-hook to prettify JSON files [\#1455](https://github.com/python-kasa/python-kasa/pull/1455) (@rytilahti) - Add commit-hook to prettify JSON files [\#1455](https://github.com/python-kasa/python-kasa/pull/1455) (@rytilahti)
- Add required sphinx.configuration [\#1446](https://github.com/python-kasa/python-kasa/pull/1446) (@rytilahti) - Add required sphinx.configuration [\#1446](https://github.com/python-kasa/python-kasa/pull/1446) (@rytilahti)
- Add more redactors for smartcams [\#1439](https://github.com/python-kasa/python-kasa/pull/1439) (@sdb9696) - Add more redactors for smartcams [\#1439](https://github.com/python-kasa/python-kasa/pull/1439) (@sdb9696)
- Add KS230\(US\) 2.0 1.0.11 IOT Fixture [\#1430](https://github.com/python-kasa/python-kasa/pull/1430) (@ZeliardM) - Add KS230\(US\) 2.0 1.0.11 IOT Fixture [\#1430](https://github.com/python-kasa/python-kasa/pull/1430) (@ZeliardM)
- Update ruff to 0.9 [\#1482](https://github.com/python-kasa/python-kasa/pull/1482) (@sdb9696)
- Cancel in progress CI workflows after new pushes [\#1481](https://github.com/python-kasa/python-kasa/pull/1481) (@sdb9696)
- Update test framework to support smartcam device discovery. [\#1477](https://github.com/python-kasa/python-kasa/pull/1477) (@sdb9696)
- Add tests for dump\_devinfo parent/child smartcam fixture generation [\#1428](https://github.com/python-kasa/python-kasa/pull/1428) (@sdb9696) - Add tests for dump\_devinfo parent/child smartcam fixture generation [\#1428](https://github.com/python-kasa/python-kasa/pull/1428) (@sdb9696)
- Raise errors on single smartcam child requests [\#1427](https://github.com/python-kasa/python-kasa/pull/1427) (@sdb9696) - Raise errors on single smartcam child requests [\#1427](https://github.com/python-kasa/python-kasa/pull/1427) (@sdb9696)

View File

@ -189,7 +189,7 @@ The following devices have been tested and confirmed as working. If your device
- **Plugs**: EP10, EP25[^1], HS100[^2], HS103, HS105, HS110, KP100, KP105, KP115, KP125, KP125M[^1], KP401 - **Plugs**: EP10, EP25[^1], HS100[^2], HS103, HS105, HS110, KP100, KP105, KP115, KP125, KP125M[^1], KP401
- **Power Strips**: EP40, EP40M[^1], HS107, HS300, KP200, KP303, KP400 - **Power Strips**: EP40, EP40M[^1], HS107, HS300, KP200, KP303, KP400
- **Wall Switches**: ES20M, HS200[^2], HS210, HS220[^2], KP405, KS200, KS200M, KS205[^1], KS220, KS220M, KS225[^1], KS230, KS240[^1] - **Wall Switches**: ES20M, HS200[^2], HS210, HS220[^2], KP405, KS200, KS200M, KS205[^1], KS220, KS220M, KS225[^1], KS230, KS240[^1]
- **Bulbs**: KL110, KL120, KL125, KL130, KL135, KL50, KL60, LB110 - **Bulbs**: KL110, KL120, KL125, KL130, KL135, KL50, KL60, LB100, LB110
- **Light Strips**: KL400L5, KL420L5, KL430 - **Light Strips**: KL400L5, KL420L5, KL430
- **Hubs**: KH100[^1] - **Hubs**: KH100[^1]
- **Hub-Connected Devices[^3]**: KE100[^1] - **Hub-Connected Devices[^3]**: KE100[^1]
@ -199,9 +199,9 @@ The following devices have been tested and confirmed as working. If your device
- **Plugs**: P100, P110, P110M, P115, P125M, P135, TP15 - **Plugs**: P100, P110, P110M, P115, P125M, P135, TP15
- **Power Strips**: P210M, P300, P304M, P306, TP25 - **Power Strips**: P210M, P300, P304M, P306, TP25
- **Wall Switches**: S210, S220, S500D, S505, S505D - **Wall Switches**: S210, S220, S500D, S505, S505D
- **Bulbs**: L510B, L510E, L530E, L630 - **Bulbs**: L510B, L510E, L530B, L530E, L630
- **Light Strips**: L900-10, L900-5, L920-5, L930-5 - **Light Strips**: L900-10, L900-5, L920-5, L930-5
- **Cameras**: C100, C210, C220, C225, C325WB, C520WS, C720, TC65, TC70 - **Cameras**: C100, C110, C210, C220, C225, C325WB, C520WS, C720, TC65, TC70
- **Doorbells and chimes**: D100C, D130, D230 - **Doorbells and chimes**: D100C, D130, D230
- **Vacuums**: RV20 Max Plus, RV30 Max - **Vacuums**: RV20 Max Plus, RV30 Max
- **Hubs**: H100, H200 - **Hubs**: H100, H200

View File

@ -118,6 +118,7 @@ Some newer Kasa devices require authentication. These are marked with [^1] in th
- **KS225** - **KS225**
- Hardware: 1.0 (US) / Firmware: 1.0.2[^1] - Hardware: 1.0 (US) / Firmware: 1.0.2[^1]
- Hardware: 1.0 (US) / Firmware: 1.1.0[^1] - Hardware: 1.0 (US) / Firmware: 1.1.0[^1]
- Hardware: 1.0 (US) / Firmware: 1.1.1[^1]
- **KS230** - **KS230**
- Hardware: 1.0 (US) / Firmware: 1.0.14 - Hardware: 1.0 (US) / Firmware: 1.0.14
- Hardware: 2.0 (US) / Firmware: 1.0.11 - Hardware: 2.0 (US) / Firmware: 1.0.11
@ -148,6 +149,8 @@ Some newer Kasa devices require authentication. These are marked with [^1] in th
- **KL60** - **KL60**
- Hardware: 1.0 (UN) / Firmware: 1.1.4 - Hardware: 1.0 (UN) / Firmware: 1.1.4
- Hardware: 1.0 (US) / Firmware: 1.1.13 - Hardware: 1.0 (US) / Firmware: 1.1.13
- **LB100**
- Hardware: 1.0 (US) / Firmware: 1.8.11
- **LB110** - **LB110**
- Hardware: 1.0 (US) / Firmware: 1.8.11 - Hardware: 1.0 (US) / Firmware: 1.8.11
@ -191,6 +194,7 @@ All Tapo devices require authentication.<br>Hub-Connected Devices may work acros
- Hardware: 1.0.0 (US) / Firmware: 1.3.7 - Hardware: 1.0.0 (US) / Firmware: 1.3.7
- Hardware: 1.0.0 (US) / Firmware: 1.4.0 - Hardware: 1.0.0 (US) / Firmware: 1.4.0
- **P110** - **P110**
- Hardware: 1.0 (AU) / Firmware: 1.3.1
- Hardware: 1.0 (EU) / Firmware: 1.0.7 - Hardware: 1.0 (EU) / Firmware: 1.0.7
- Hardware: 1.0 (EU) / Firmware: 1.2.3 - Hardware: 1.0 (EU) / Firmware: 1.2.3
- Hardware: 1.0 (UK) / Firmware: 1.3.0 - Hardware: 1.0 (UK) / Firmware: 1.3.0
@ -243,10 +247,13 @@ All Tapo devices require authentication.<br>Hub-Connected Devices may work acros
- **L510E** - **L510E**
- Hardware: 3.0 (US) / Firmware: 1.0.5 - Hardware: 3.0 (US) / Firmware: 1.0.5
- Hardware: 3.0 (US) / Firmware: 1.1.2 - Hardware: 3.0 (US) / Firmware: 1.1.2
- **L530B**
- Hardware: 3.0 (EU) / Firmware: 1.1.9
- **L530E** - **L530E**
- Hardware: 3.0 (EU) / Firmware: 1.0.6 - Hardware: 3.0 (EU) / Firmware: 1.0.6
- Hardware: 3.0 (EU) / Firmware: 1.1.0 - Hardware: 3.0 (EU) / Firmware: 1.1.0
- Hardware: 3.0 (EU) / Firmware: 1.1.6 - Hardware: 3.0 (EU) / Firmware: 1.1.6
- Hardware: 2.0 (TW) / Firmware: 1.1.1
- Hardware: 2.0 (US) / Firmware: 1.1.0 - Hardware: 2.0 (US) / Firmware: 1.1.0
- **L630** - **L630**
- Hardware: 1.0 (EU) / Firmware: 1.1.2 - Hardware: 1.0 (EU) / Firmware: 1.1.2
@ -265,12 +272,15 @@ All Tapo devices require authentication.<br>Hub-Connected Devices may work acros
- Hardware: 1.0 (US) / Firmware: 1.1.0 - Hardware: 1.0 (US) / Firmware: 1.1.0
- Hardware: 1.0 (US) / Firmware: 1.1.3 - Hardware: 1.0 (US) / Firmware: 1.1.3
- **L930-5** - **L930-5**
- Hardware: 1.0 (EU) / Firmware: 1.2.5
- Hardware: 1.0 (US) / Firmware: 1.1.2 - Hardware: 1.0 (US) / Firmware: 1.1.2
### Cameras ### Cameras
- **C100** - **C100**
- Hardware: 4.0 / Firmware: 1.3.14 - Hardware: 4.0 / Firmware: 1.3.14
- **C110**
- Hardware: 2.0 (EU) / Firmware: 1.4.3
- **C210** - **C210**
- Hardware: 2.0 / Firmware: 1.3.11 - Hardware: 2.0 / Firmware: 1.3.11
- Hardware: 2.0 (EU) / Firmware: 1.4.2 - Hardware: 2.0 (EU) / Firmware: 1.4.2
@ -309,6 +319,7 @@ All Tapo devices require authentication.<br>Hub-Connected Devices may work acros
### Hubs ### Hubs
- **H100** - **H100**
- Hardware: 1.0 (AU) / Firmware: 1.5.23
- Hardware: 1.0 (EU) / Firmware: 1.2.3 - Hardware: 1.0 (EU) / Firmware: 1.2.3
- Hardware: 1.0 (EU) / Firmware: 1.5.10 - Hardware: 1.0 (EU) / Firmware: 1.5.10
- Hardware: 1.0 (EU) / Firmware: 1.5.5 - Hardware: 1.0 (EU) / Firmware: 1.5.5
@ -327,6 +338,7 @@ All Tapo devices require authentication.<br>Hub-Connected Devices may work acros
- Hardware: 1.0 (EU) / Firmware: 1.12.0 - Hardware: 1.0 (EU) / Firmware: 1.12.0
- **T100** - **T100**
- Hardware: 1.0 (EU) / Firmware: 1.12.0 - Hardware: 1.0 (EU) / Firmware: 1.12.0
- Hardware: 1.0 (US) / Firmware: 1.12.0
- **T110** - **T110**
- Hardware: 1.0 (EU) / Firmware: 1.8.0 - Hardware: 1.0 (EU) / Firmware: 1.8.0
- Hardware: 1.0 (EU) / Firmware: 1.9.0 - Hardware: 1.0 (EU) / Firmware: 1.9.0

View File

@ -725,15 +725,6 @@ async def get_smart_test_calls(protocol: SmartProtocol):
successes = [] successes = []
child_device_components = {} child_device_components = {}
extra_test_calls = [
SmartCall(
module="temp_humidity_records",
request=SmartRequest.get_raw_request("get_temp_humidity_records").to_dict(),
should_succeed=False,
child_device_id="",
),
]
click.echo("Testing component_nego call ..", nl=False) click.echo("Testing component_nego call ..", nl=False)
responses = await _make_requests_or_exit( responses = await _make_requests_or_exit(
protocol, protocol,
@ -812,8 +803,6 @@ async def get_smart_test_calls(protocol: SmartProtocol):
click.echo(f"Skipping {component_id}..", nl=False) click.echo(f"Skipping {component_id}..", nl=False)
click.echo(click.style("UNSUPPORTED", fg="yellow")) click.echo(click.style("UNSUPPORTED", fg="yellow"))
test_calls.extend(extra_test_calls)
# Child component calls # Child component calls
for child_device_id, child_components in child_device_components.items(): for child_device_id, child_components in child_device_components.items():
test_calls.append( test_calls.append(
@ -839,12 +828,6 @@ async def get_smart_test_calls(protocol: SmartProtocol):
else: else:
click.echo(f"Skipping {component_id}..", nl=False) click.echo(f"Skipping {component_id}..", nl=False)
click.echo(click.style("UNSUPPORTED", fg="yellow")) click.echo(click.style("UNSUPPORTED", fg="yellow"))
# Add the extra calls for each child
for extra_call in extra_test_calls:
extra_child_call = dataclasses.replace(
extra_call, child_device_id=child_device_id
)
test_calls.append(extra_child_call)
return test_calls, successes return test_calls, successes

View File

@ -425,6 +425,7 @@ COMPONENT_REQUESTS = {
"get_trigger_logs", SmartRequest.GetTriggerLogsParams() "get_trigger_logs", SmartRequest.GetTriggerLogsParams()
) )
], ],
"temp_humidity_record": [SmartRequest.get_raw_request("get_temp_humidity_records")],
"double_click": [SmartRequest.get_raw_request("get_double_click_info")], "double_click": [SmartRequest.get_raw_request("get_double_click_info")],
"child_device": [ "child_device": [
SmartRequest.get_raw_request("get_child_device_list"), SmartRequest.get_raw_request("get_child_device_list"),

View File

@ -1,6 +1,10 @@
# Get Energy Consumption and Usage Statistics # Get Energy Consumption and Usage Statistics
:::{note}
The documentation on this page applies only to KASA-branded devices.
:::
:::{note} :::{note}
In order to use the helper methods to calculate the statistics correctly, your devices need to have correct time set. In order to use the helper methods to calculate the statistics correctly, your devices need to have correct time set.
The devices use NTP (123/UDP) and public servers from [NTP Pool Project](https://www.ntppool.org/) to synchronize their time. The devices use NTP (123/UDP) and public servers from [NTP Pool Project](https://www.ntppool.org/) to synchronize their time.

View File

@ -48,7 +48,7 @@ async def state(ctx, dev: Device):
) )
echo( echo(
f"Firmware: {dev.device_info.firmware_version}" f"Firmware: {dev.device_info.firmware_version}"
f" {dev.device_info.firmware_build}" f"{' ' + build if (build := dev.device_info.firmware_build) else ''}"
) )
echo(f"MAC (rssi): {dev.mac} ({dev.rssi})") echo(f"MAC (rssi): {dev.mac} ({dev.rssi})")
if verbose: if verbose:

View File

@ -161,7 +161,7 @@ class DeviceInfo:
device_type: DeviceType device_type: DeviceType
hardware_version: str hardware_version: str
firmware_version: str firmware_version: str
firmware_build: str firmware_build: str | None
requires_auth: bool requires_auth: bool
region: str | None region: str | None

View File

@ -28,7 +28,7 @@ class Energy(Module, ABC):
_supported: ModuleFeature = ModuleFeature(0) _supported: ModuleFeature = ModuleFeature(0)
def supports(self, module_feature: ModuleFeature) -> bool: def supports(self, module_feature: Energy.ModuleFeature) -> bool:
"""Return True if module supports the feature.""" """Return True if module supports the feature."""
return module_feature in self._supported return module_feature in self._supported

View File

@ -51,6 +51,7 @@ class LightEffect(Module, ABC):
"""Interface to represent a light effect module.""" """Interface to represent a light effect module."""
LIGHT_EFFECTS_OFF = "Off" LIGHT_EFFECTS_OFF = "Off"
LIGHT_EFFECTS_UNNAMED_CUSTOM = "Custom"
def _initialize_features(self) -> None: def _initialize_features(self) -> None:
"""Initialize features.""" """Initialize features."""
@ -77,7 +78,7 @@ class LightEffect(Module, ABC):
@property @property
@abstractmethod @abstractmethod
def effect(self) -> str: def effect(self) -> str:
"""Return effect state or name.""" """Return effect name."""
@property @property
@abstractmethod @abstractmethod

View File

@ -760,7 +760,10 @@ class IotDevice(Device):
device_family = sys_info.get("type", sys_info.get("mic_type")) device_family = sys_info.get("type", sys_info.get("mic_type"))
device_type = IotDevice._get_device_type_from_sys_info(info) device_type = IotDevice._get_device_type_from_sys_info(info)
fw_version_full = sys_info["sw_ver"] fw_version_full = sys_info["sw_ver"]
firmware_version, firmware_build = fw_version_full.split(" ", maxsplit=1) if " " in fw_version_full:
firmware_version, firmware_build = fw_version_full.split(" ", maxsplit=1)
else:
firmware_version, firmware_build = fw_version_full, None
auth = bool(discovery_info and ("mgt_encrypt_schm" in discovery_info)) auth = bool(discovery_info and ("mgt_encrypt_schm" in discovery_info))
return DeviceInfo( return DeviceInfo(

View File

@ -11,7 +11,7 @@ from ..module import Module
from ..protocols import BaseProtocol from ..protocols import BaseProtocol
from .iotdevice import KasaException, requires_update from .iotdevice import KasaException, requires_update
from .iotplug import IotPlug from .iotplug import IotPlug
from .modules import AmbientLight, Light, Motion from .modules import AmbientLight, Dimmer, Light, Motion
class ButtonAction(Enum): class ButtonAction(Enum):
@ -87,6 +87,7 @@ class IotDimmer(IotPlug):
# TODO: need to be figured out what's the best approach to detect support # TODO: need to be figured out what's the best approach to detect support
self.add_module(Module.IotMotion, Motion(self, "smartlife.iot.PIR")) self.add_module(Module.IotMotion, Motion(self, "smartlife.iot.PIR"))
self.add_module(Module.IotAmbientLight, AmbientLight(self, "smartlife.iot.LAS")) self.add_module(Module.IotAmbientLight, AmbientLight(self, "smartlife.iot.LAS"))
self.add_module(Module.IotDimmer, Dimmer(self, "smartlife.iot.dimmer"))
self.add_module(Module.Light, Light(self, "light")) self.add_module(Module.Light, Light(self, "light"))
@property # type: ignore @property # type: ignore

View File

@ -4,6 +4,7 @@ from .ambientlight import AmbientLight
from .antitheft import Antitheft from .antitheft import Antitheft
from .cloud import Cloud from .cloud import Cloud
from .countdown import Countdown from .countdown import Countdown
from .dimmer import Dimmer
from .emeter import Emeter from .emeter import Emeter
from .led import Led from .led import Led
from .light import Light from .light import Light
@ -20,6 +21,7 @@ __all__ = [
"Antitheft", "Antitheft",
"Cloud", "Cloud",
"Countdown", "Countdown",
"Dimmer",
"Emeter", "Emeter",
"Led", "Led",
"Light", "Light",

270
kasa/iot/modules/dimmer.py Normal file
View File

@ -0,0 +1,270 @@
"""Implementation of the dimmer config module found in dimmers."""
from __future__ import annotations
import logging
from datetime import timedelta
from typing import Any, Final, cast
from ...exceptions import KasaException
from ...feature import Feature
from ..iotmodule import IotModule, merge
_LOGGER = logging.getLogger(__name__)
def _td_to_ms(td: timedelta) -> int:
"""
Convert timedelta to integer milliseconds.
Uses default float to integer rounding.
"""
return int(td / timedelta(milliseconds=1))
class Dimmer(IotModule):
"""Implements the dimmer config module."""
THRESHOLD_ABS_MIN: Final[int] = 0
# Strange value, but verified against hardware (KS220).
THRESHOLD_ABS_MAX: Final[int] = 51
FADE_TIME_ABS_MIN: Final[timedelta] = timedelta(seconds=0)
# Arbitrary, but set low intending GENTLE FADE for longer fades.
FADE_TIME_ABS_MAX: Final[timedelta] = timedelta(seconds=10)
GENTLE_TIME_ABS_MIN: Final[timedelta] = timedelta(seconds=0)
# Arbitrary, but reasonable default.
GENTLE_TIME_ABS_MAX: Final[timedelta] = timedelta(seconds=120)
# Verified against KS220.
RAMP_RATE_ABS_MIN: Final[int] = 10
# Verified against KS220.
RAMP_RATE_ABS_MAX: Final[int] = 50
def _initialize_features(self) -> None:
"""Initialize features after the initial update."""
self._add_feature(
Feature(
device=self._device,
container=self,
id="dimmer_threshold_min",
name="Minimum dimming level",
icon="mdi:lightbulb-on-20",
attribute_getter="threshold_min",
attribute_setter="set_threshold_min",
range_getter=lambda: (self.THRESHOLD_ABS_MIN, self.THRESHOLD_ABS_MAX),
type=Feature.Type.Number,
category=Feature.Category.Config,
)
)
self._add_feature(
Feature(
device=self._device,
container=self,
id="dimmer_fade_off_time",
name="Dimmer fade off time",
icon="mdi:clock-in",
attribute_getter="fade_off_time",
attribute_setter="set_fade_off_time",
range_getter=lambda: (
_td_to_ms(self.FADE_TIME_ABS_MIN),
_td_to_ms(self.FADE_TIME_ABS_MAX),
),
type=Feature.Type.Number,
category=Feature.Category.Config,
)
)
self._add_feature(
Feature(
device=self._device,
container=self,
id="dimmer_fade_on_time",
name="Dimmer fade on time",
icon="mdi:clock-out",
attribute_getter="fade_on_time",
attribute_setter="set_fade_on_time",
range_getter=lambda: (
_td_to_ms(self.FADE_TIME_ABS_MIN),
_td_to_ms(self.FADE_TIME_ABS_MAX),
),
type=Feature.Type.Number,
category=Feature.Category.Config,
)
)
self._add_feature(
Feature(
device=self._device,
container=self,
id="dimmer_gentle_off_time",
name="Dimmer gentle off time",
icon="mdi:clock-in",
attribute_getter="gentle_off_time",
attribute_setter="set_gentle_off_time",
range_getter=lambda: (
_td_to_ms(self.GENTLE_TIME_ABS_MIN),
_td_to_ms(self.GENTLE_TIME_ABS_MAX),
),
type=Feature.Type.Number,
category=Feature.Category.Config,
)
)
self._add_feature(
Feature(
device=self._device,
container=self,
id="dimmer_gentle_on_time",
name="Dimmer gentle on time",
icon="mdi:clock-out",
attribute_getter="gentle_on_time",
attribute_setter="set_gentle_on_time",
range_getter=lambda: (
_td_to_ms(self.GENTLE_TIME_ABS_MIN),
_td_to_ms(self.GENTLE_TIME_ABS_MAX),
),
type=Feature.Type.Number,
category=Feature.Category.Config,
)
)
self._add_feature(
Feature(
device=self._device,
container=self,
id="dimmer_ramp_rate",
name="Dimmer ramp rate",
icon="mdi:clock-fast",
attribute_getter="ramp_rate",
attribute_setter="set_ramp_rate",
range_getter=lambda: (self.RAMP_RATE_ABS_MIN, self.RAMP_RATE_ABS_MAX),
type=Feature.Type.Number,
category=Feature.Category.Config,
)
)
def query(self) -> dict:
"""Request Dimming configuration."""
req = merge(
self.query_for_command("get_dimmer_parameters"),
self.query_for_command("get_default_behavior"),
)
return req
@property
def config(self) -> dict[str, Any]:
"""Return current configuration."""
return self.data["get_dimmer_parameters"]
@property
def threshold_min(self) -> int:
"""Return the minimum dimming level for this dimmer."""
return self.config["minThreshold"]
async def set_threshold_min(self, min: int) -> dict:
"""Set the minimum dimming level for this dimmer.
The value will depend on the luminaries connected to the dimmer.
:param min: The minimum dimming level, in the range 0-51.
"""
if min < self.THRESHOLD_ABS_MIN or min > self.THRESHOLD_ABS_MAX:
raise KasaException(
"Minimum dimming threshold is outside the supported range: "
f"{self.THRESHOLD_ABS_MIN}-{self.THRESHOLD_ABS_MAX}"
)
return await self.call("calibrate_brightness", {"minThreshold": min})
@property
def fade_off_time(self) -> timedelta:
"""Return the fade off animation duration."""
return timedelta(milliseconds=cast(int, self.config["fadeOffTime"]))
async def set_fade_off_time(self, time: int | timedelta) -> dict:
"""Set the duration of the fade off animation.
:param time: The animation duration, in ms.
"""
if isinstance(time, int):
time = timedelta(milliseconds=time)
if time < self.FADE_TIME_ABS_MIN or time > self.FADE_TIME_ABS_MAX:
raise KasaException(
"Fade time is outside the bounds of the supported range:"
f"{self.FADE_TIME_ABS_MIN}-{self.FADE_TIME_ABS_MAX}"
)
return await self.call("set_fade_off_time", {"fadeTime": _td_to_ms(time)})
@property
def fade_on_time(self) -> timedelta:
"""Return the fade on animation duration."""
return timedelta(milliseconds=cast(int, self.config["fadeOnTime"]))
async def set_fade_on_time(self, time: int | timedelta) -> dict:
"""Set the duration of the fade on animation.
:param time: The animation duration, in ms.
"""
if isinstance(time, int):
time = timedelta(milliseconds=time)
if time < self.FADE_TIME_ABS_MIN or time > self.FADE_TIME_ABS_MAX:
raise KasaException(
"Fade time is outside the bounds of the supported range:"
f"{self.FADE_TIME_ABS_MIN}-{self.FADE_TIME_ABS_MAX}"
)
return await self.call("set_fade_on_time", {"fadeTime": _td_to_ms(time)})
@property
def gentle_off_time(self) -> timedelta:
"""Return the gentle fade off animation duration."""
return timedelta(milliseconds=cast(int, self.config["gentleOffTime"]))
async def set_gentle_off_time(self, time: int | timedelta) -> dict:
"""Set the duration of the gentle fade off animation.
:param time: The animation duration, in ms.
"""
if isinstance(time, int):
time = timedelta(milliseconds=time)
if time < self.GENTLE_TIME_ABS_MIN or time > self.GENTLE_TIME_ABS_MAX:
raise KasaException(
"Gentle off time is outside the bounds of the supported range: "
f"{self.GENTLE_TIME_ABS_MIN}-{self.GENTLE_TIME_ABS_MAX}."
)
return await self.call("set_gentle_off_time", {"duration": _td_to_ms(time)})
@property
def gentle_on_time(self) -> timedelta:
"""Return the gentle fade on animation duration."""
return timedelta(milliseconds=cast(int, self.config["gentleOnTime"]))
async def set_gentle_on_time(self, time: int | timedelta) -> dict:
"""Set the duration of the gentle fade on animation.
:param time: The animation duration, in ms.
"""
if isinstance(time, int):
time = timedelta(milliseconds=time)
if time < self.GENTLE_TIME_ABS_MIN or time > self.GENTLE_TIME_ABS_MAX:
raise KasaException(
"Gentle off time is outside the bounds of the supported range: "
f"{self.GENTLE_TIME_ABS_MIN}-{self.GENTLE_TIME_ABS_MAX}."
)
return await self.call("set_gentle_on_time", {"duration": _td_to_ms(time)})
@property
def ramp_rate(self) -> int:
"""Return the rate that the dimmer buttons increment the dimmer level."""
return self.config["rampRate"]
async def set_ramp_rate(self, rate: int) -> dict:
"""Set how quickly to ramp the dimming level when using the dimmer buttons.
:param rate: The rate to increment the dimming level with each press.
"""
if rate < self.RAMP_RATE_ABS_MIN or rate > self.RAMP_RATE_ABS_MAX:
raise KasaException(
"Gentle off time is outside the bounds of the supported range:"
f"{self.RAMP_RATE_ABS_MIN}-{self.RAMP_RATE_ABS_MAX}"
)
return await self.call("set_button_ramp_rate", {"rampRate": rate})

View File

@ -12,20 +12,11 @@ class LightEffect(IotModule, LightEffectInterface):
@property @property
def effect(self) -> str: def effect(self) -> str:
"""Return effect state. """Return effect name."""
Example:
{'brightness': 50,
'custom': 0,
'enable': 0,
'id': '',
'name': ''}
"""
eff = self.data["lighting_effect_state"] eff = self.data["lighting_effect_state"]
name = eff["name"] name = eff["name"]
if eff["enable"]: if eff["enable"]:
return name return name or self.LIGHT_EFFECTS_UNNAMED_CUSTOM
return self.LIGHT_EFFECTS_OFF return self.LIGHT_EFFECTS_OFF
@property @property

View File

@ -111,6 +111,7 @@ class Module(ABC):
IotAmbientLight: Final[ModuleName[iot.AmbientLight]] = ModuleName("ambient") IotAmbientLight: Final[ModuleName[iot.AmbientLight]] = ModuleName("ambient")
IotAntitheft: Final[ModuleName[iot.Antitheft]] = ModuleName("anti_theft") IotAntitheft: Final[ModuleName[iot.Antitheft]] = ModuleName("anti_theft")
IotCountdown: Final[ModuleName[iot.Countdown]] = ModuleName("countdown") IotCountdown: Final[ModuleName[iot.Countdown]] = ModuleName("countdown")
IotDimmer: Final[ModuleName[iot.Dimmer]] = ModuleName("dimmer")
IotMotion: Final[ModuleName[iot.Motion]] = ModuleName("motion") IotMotion: Final[ModuleName[iot.Motion]] = ModuleName("motion")
IotSchedule: Final[ModuleName[iot.Schedule]] = ModuleName("schedule") IotSchedule: Final[ModuleName[iot.Schedule]] = ModuleName("schedule")
IotUsage: Final[ModuleName[iot.Usage]] = ModuleName("usage") IotUsage: Final[ModuleName[iot.Usage]] = ModuleName("usage")
@ -182,6 +183,11 @@ class Module(ABC):
self._module = module self._module = module
self._module_features: dict[str, Feature] = {} self._module_features: dict[str, Feature] = {}
@property
def device(self) -> Device:
"""Return the device exposing the module."""
return self._device
@property @property
def _all_features(self) -> dict[str, Feature]: def _all_features(self) -> dict[str, Feature]:
"""Get the features for this module and any sub modules.""" """Get the features for this module and any sub modules."""

View File

@ -19,6 +19,8 @@ class Mode(IntEnum):
Balanced = 2 Balanced = 2
Max = 3 Max = 3
Off = -1_000
class Dustbin(SmartModule): class Dustbin(SmartModule):
"""Implementation of vacuum dustbin.""" """Implementation of vacuum dustbin."""
@ -91,6 +93,8 @@ class Dustbin(SmartModule):
@property @property
def mode(self) -> str: def mode(self) -> str:
"""Return auto-emptying mode.""" """Return auto-emptying mode."""
if self.auto_collection is False:
return Mode.Off.name
return Mode(self._settings["dust_collection_mode"]).name return Mode(self._settings["dust_collection_mode"]).name
async def set_mode(self, mode: str) -> dict: async def set_mode(self, mode: str) -> dict:
@ -101,8 +105,14 @@ class Dustbin(SmartModule):
"Invalid auto/emptying mode speed %s, available %s", mode, name_to_value "Invalid auto/emptying mode speed %s, available %s", mode, name_to_value
) )
if mode == Mode.Off.name:
return await self.set_auto_collection(False)
# Make a copy just in case, even when we are overriding both settings
settings = self._settings.copy() settings = self._settings.copy()
settings["auto_dust_collection"] = True
settings["dust_collection_mode"] = name_to_value[mode] settings["dust_collection_mode"] = name_to_value[mode]
return await self.call("setDustCollectionInfo", settings) return await self.call("setDustCollectionInfo", settings)
@property @property

View File

@ -37,20 +37,14 @@ class LightStripEffect(SmartModule, SmartLightEffect):
@property @property
def effect(self) -> str: def effect(self) -> str:
"""Return effect state. """Return effect name."""
Example:
{'brightness': 50,
'custom': 0,
'enable': 0,
'id': '',
'name': ''}
"""
eff = self.data["lighting_effect"] eff = self.data["lighting_effect"]
name = eff["name"] name = eff["name"]
# When devices are unpaired effect name is softAP which is not in our list # When devices are unpaired effect name is softAP which is not in our list
if eff["enable"] and name in self._effect_list: if eff["enable"] and name in self._effect_list:
return name return name
if eff["enable"] and eff["custom"]:
return name or self.LIGHT_EFFECTS_UNNAMED_CUSTOM
return self.LIGHT_EFFECTS_OFF return self.LIGHT_EFFECTS_OFF
@property @property

View File

@ -913,7 +913,10 @@ class SmartDevice(Device):
components, device_family components, device_family
) )
fw_version_full = di["fw_ver"] fw_version_full = di["fw_ver"]
firmware_version, firmware_build = fw_version_full.split(" ", maxsplit=1) if " " in fw_version_full:
firmware_version, firmware_build = fw_version_full.split(" ", maxsplit=1)
else:
firmware_version, firmware_build = fw_version_full, None
_protocol, devicetype = device_family.split(".") _protocol, devicetype = device_family.split(".")
# Brand inferred from SMART.KASAPLUG/SMART.TAPOPLUG etc. # Brand inferred from SMART.KASAPLUG/SMART.TAPOPLUG etc.
brand = devicetype[:4].lower() brand = devicetype[:4].lower()

View File

@ -3,7 +3,8 @@
from __future__ import annotations from __future__ import annotations
import logging import logging
from collections.abc import Awaitable, Callable, Coroutine from collections.abc import Callable, Coroutine
from functools import wraps
from typing import TYPE_CHECKING, Any, Concatenate, ParamSpec, TypeVar from typing import TYPE_CHECKING, Any, Concatenate, ParamSpec, TypeVar
from ..exceptions import DeviceError, KasaException, SmartErrorCode from ..exceptions import DeviceError, KasaException, SmartErrorCode
@ -20,15 +21,16 @@ _R = TypeVar("_R")
def allow_update_after( def allow_update_after(
func: Callable[Concatenate[_T, _P], Awaitable[dict]], func: Callable[Concatenate[_T, _P], Coroutine[Any, Any, _R]],
) -> Callable[Concatenate[_T, _P], Coroutine[Any, Any, dict]]: ) -> Callable[Concatenate[_T, _P], Coroutine[Any, Any, _R]]:
"""Define a wrapper to set _last_update_time to None. """Define a wrapper to set _last_update_time to None.
This will ensure that a module is updated in the next update cycle after This will ensure that a module is updated in the next update cycle after
a value has been changed. a value has been changed.
""" """
async def _async_wrap(self: _T, *args: _P.args, **kwargs: _P.kwargs) -> dict: @wraps(func)
async def _async_wrap(self: _T, *args: _P.args, **kwargs: _P.kwargs) -> _R:
try: try:
return await func(self, *args, **kwargs) return await func(self, *args, **kwargs)
finally: finally:
@ -40,6 +42,7 @@ def allow_update_after(
def raise_if_update_error(func: Callable[[_T], _R]) -> Callable[[_T], _R]: def raise_if_update_error(func: Callable[[_T], _R]) -> Callable[[_T], _R]:
"""Define a wrapper to raise an error if the last module update was an error.""" """Define a wrapper to raise an error if the last module update was an error."""
@wraps(func)
def _wrap(self: _T) -> _R: def _wrap(self: _T) -> _R:
if err := self._last_update_error: if err := self._last_update_error:
raise err raise err

View File

@ -2,8 +2,11 @@
from __future__ import annotations from __future__ import annotations
from typing import Annotated
from ...feature import Feature from ...feature import Feature
from ...interfaces import Alarm as AlarmInterface from ...interfaces import Alarm as AlarmInterface
from ...module import FeatureAttribute
from ...smart.smartmodule import allow_update_after from ...smart.smartmodule import allow_update_after
from ..smartcammodule import SmartCamModule from ..smartcammodule import SmartCamModule
@ -105,12 +108,12 @@ class Alarm(SmartCamModule, AlarmInterface):
) )
@property @property
def alarm_sound(self) -> str: def alarm_sound(self) -> Annotated[str, FeatureAttribute()]:
"""Return current alarm sound.""" """Return current alarm sound."""
return self.data["getSirenConfig"]["siren_type"] return self.data["getSirenConfig"]["siren_type"]
@allow_update_after @allow_update_after
async def set_alarm_sound(self, sound: str) -> dict: async def set_alarm_sound(self, sound: str) -> Annotated[dict, FeatureAttribute()]:
"""Set alarm sound. """Set alarm sound.
See *alarm_sounds* for list of available sounds. See *alarm_sounds* for list of available sounds.
@ -124,7 +127,7 @@ class Alarm(SmartCamModule, AlarmInterface):
return self.data["getSirenTypeList"]["siren_type_list"] return self.data["getSirenTypeList"]["siren_type_list"]
@property @property
def alarm_volume(self) -> int: def alarm_volume(self) -> Annotated[int, FeatureAttribute()]:
"""Return alarm volume. """Return alarm volume.
Unlike duration the device expects/returns a string for volume. Unlike duration the device expects/returns a string for volume.
@ -132,18 +135,22 @@ class Alarm(SmartCamModule, AlarmInterface):
return int(self.data["getSirenConfig"]["volume"]) return int(self.data["getSirenConfig"]["volume"])
@allow_update_after @allow_update_after
async def set_alarm_volume(self, volume: int) -> dict: async def set_alarm_volume(
self, volume: int
) -> Annotated[dict, FeatureAttribute()]:
"""Set alarm volume.""" """Set alarm volume."""
config = self._validate_and_get_config(volume=volume) config = self._validate_and_get_config(volume=volume)
return await self.call("setSirenConfig", {"siren": config}) return await self.call("setSirenConfig", {"siren": config})
@property @property
def alarm_duration(self) -> int: def alarm_duration(self) -> Annotated[int, FeatureAttribute()]:
"""Return alarm duration.""" """Return alarm duration."""
return self.data["getSirenConfig"]["duration"] return self.data["getSirenConfig"]["duration"]
@allow_update_after @allow_update_after
async def set_alarm_duration(self, duration: int) -> dict: async def set_alarm_duration(
self, duration: int
) -> Annotated[dict, FeatureAttribute()]:
"""Set alarm volume.""" """Set alarm volume."""
config = self._validate_and_get_config(duration=duration) config = self._validate_and_get_config(duration=duration)
return await self.call("setSirenConfig", {"siren": config}) return await self.call("setSirenConfig", {"siren": config})

View File

@ -103,7 +103,10 @@ class SmartCamChild(SmartChildDevice, SmartCamDevice):
model = cifp["device_model"] model = cifp["device_model"]
device_type = SmartCamDevice._get_device_type_from_sysinfo(cifp) device_type = SmartCamDevice._get_device_type_from_sysinfo(cifp)
fw_version_full = cifp["sw_ver"] fw_version_full = cifp["sw_ver"]
firmware_version, firmware_build = fw_version_full.split(" ", maxsplit=1) if " " in fw_version_full:
firmware_version, firmware_build = fw_version_full.split(" ", maxsplit=1)
else:
firmware_version, firmware_build = fw_version_full, None
return DeviceInfo( return DeviceInfo(
short_name=model, short_name=model,
long_name=model, long_name=model,

View File

@ -47,7 +47,10 @@ class SmartCamDevice(SmartDevice):
long_name = discovery_info["device_model"] if discovery_info else short_name long_name = discovery_info["device_model"] if discovery_info else short_name
device_type = SmartCamDevice._get_device_type_from_sysinfo(basic_info) device_type = SmartCamDevice._get_device_type_from_sysinfo(basic_info)
fw_version_full = basic_info["sw_version"] fw_version_full = basic_info["sw_version"]
firmware_version, firmware_build = fw_version_full.split(" ", maxsplit=1) if " " in fw_version_full:
firmware_version, firmware_build = fw_version_full.split(" ", maxsplit=1)
else:
firmware_version, firmware_build = fw_version_full, None
return DeviceInfo( return DeviceInfo(
short_name=basic_info["device_model"], short_name=basic_info["device_model"],
long_name=long_name, long_name=long_name,

View File

@ -1,6 +1,6 @@
[project] [project]
name = "python-kasa" name = "python-kasa"
version = "0.10.0" version = "0.10.2"
description = "Python API for TP-Link Kasa and Tapo devices" description = "Python API for TP-Link Kasa and Tapo devices"
license = {text = "GPL-3.0-or-later"} license = {text = "GPL-3.0-or-later"}
authors = [ { name = "python-kasa developers" }] authors = [ { name = "python-kasa developers" }]

View File

@ -0,0 +1,135 @@
{
"smartlife.iot.common.cloud": {
"get_info": {
"binded": 1,
"cld_connection": 1,
"err_code": 0,
"fwDlPage": "",
"fwNotifyType": 0,
"illegalType": 0,
"server": "n-devs.tplinkcloud.com",
"stopConnect": 0,
"tcspInfo": "",
"tcspStatus": 1,
"username": "user@example.com"
},
"get_intl_fw_list": {
"err_code": 0,
"fw_list": []
}
},
"smartlife.iot.common.emeter": {
"get_realtime": {
"err_code": 0,
"power_mw": 4400
}
},
"smartlife.iot.common.schedule": {
"get_next_action": {
"err_code": 0,
"type": -1
},
"get_rules": {
"enable": 1,
"err_code": 0,
"rule_list": [],
"version": 2
}
},
"smartlife.iot.smartbulb.lightingservice": {
"get_default_behavior": {
"err_code": 0,
"hard_on": {
"mode": "last_status"
},
"soft_on": {
"mode": "last_status"
}
},
"get_light_details": {
"color_rendering_index": 80,
"err_code": 0,
"incandescent_equivalent": 50,
"lamp_beam_angle": 270,
"max_lumens": 600,
"max_voltage": 120,
"min_voltage": 110,
"wattage": 7
},
"get_light_state": {
"brightness": 50,
"color_temp": 2700,
"err_code": 0,
"hue": 0,
"mode": "normal",
"on_off": 1,
"saturation": 0
}
},
"system": {
"get_sysinfo": {
"active_mode": "none",
"alias": "#MASKED_NAME#",
"ctrl_protocols": {
"name": "Linkie",
"version": "1.0"
},
"description": "Smart Wi-Fi LED Bulb with Dimmable Light",
"dev_state": "normal",
"deviceId": "0000000000000000000000000000000000000000",
"disco_ver": "1.0",
"err_code": 0,
"heapsize": 291960,
"hwId": "00000000000000000000000000000000",
"hw_ver": "1.0",
"is_color": 0,
"is_dimmable": 1,
"is_factory": false,
"is_variable_color_temp": 0,
"light_state": {
"brightness": 50,
"color_temp": 2700,
"hue": 0,
"mode": "normal",
"on_off": 1,
"saturation": 0
},
"mic_mac": "50C7BF000000",
"mic_type": "IOT.SMARTBULB",
"model": "LB100(US)",
"oemId": "00000000000000000000000000000000",
"preferred_state": [
{
"brightness": 100,
"color_temp": 2700,
"hue": 0,
"index": 0,
"saturation": 0
},
{
"brightness": 75,
"color_temp": 2700,
"hue": 0,
"index": 1,
"saturation": 0
},
{
"brightness": 25,
"color_temp": 2700,
"hue": 0,
"index": 2,
"saturation": 0
},
{
"brightness": 1,
"color_temp": 2700,
"hue": 0,
"index": 3,
"saturation": 0
}
],
"rssi": -46,
"sw_ver": "1.8.11 Build 191113 Rel.105336"
}
}
}

View File

@ -0,0 +1,513 @@
{
"component_nego": {
"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
}
]
},
"discovery_result": {
"error_code": 0,
"result": {
"device_id": "00000000000000000000000000000000",
"device_model": "H100(AU)",
"device_type": "SMART.TAPOHUB",
"factory_default": false,
"ip": "127.0.0.123",
"is_support_iot_cloud": true,
"mac": "9C-A2-F4-00-00-00",
"mgt_encrypt_schm": {
"encrypt_type": "KLAP",
"http_port": 80,
"is_support_https": false,
"lv": 2
},
"obd_src": "tplink",
"owner": "00000000000000000000000000000000",
"protocol_version": 1
}
},
"get_alarm_configure": {
"duration": 300,
"type": "Connection 2",
"volume": "low"
},
"get_auto_update_info": {
"enable": true,
"random_range": 120,
"time": 180
},
"get_child_device_component_list": {
"child_component_list": [
{
"component_list": [
{
"id": "device",
"ver_code": 2
},
{
"id": "quick_setup",
"ver_code": 3
},
{
"id": "trigger_log",
"ver_code": 1
},
{
"id": "time",
"ver_code": 1
},
{
"id": "device_local_time",
"ver_code": 1
},
{
"id": "account",
"ver_code": 1
},
{
"id": "synchronize",
"ver_code": 1
},
{
"id": "cloud_connect",
"ver_code": 1
},
{
"id": "iot_cloud",
"ver_code": 1
},
{
"id": "firmware",
"ver_code": 1
},
{
"id": "localSmart",
"ver_code": 1
},
{
"id": "battery_detect",
"ver_code": 1
},
{
"id": "temperature",
"ver_code": 1
},
{
"id": "humidity",
"ver_code": 1
},
{
"id": "temp_humidity_record",
"ver_code": 1
},
{
"id": "comfort_temperature",
"ver_code": 1
},
{
"id": "comfort_humidity",
"ver_code": 1
},
{
"id": "report_mode",
"ver_code": 1
}
],
"device_id": "SCRUBBED_CHILD_DEVICE_ID_1"
},
{
"component_list": [
{
"id": "device",
"ver_code": 2
},
{
"id": "quick_setup",
"ver_code": 3
},
{
"id": "trigger_log",
"ver_code": 1
},
{
"id": "time",
"ver_code": 1
},
{
"id": "device_local_time",
"ver_code": 1
},
{
"id": "account",
"ver_code": 1
},
{
"id": "synchronize",
"ver_code": 1
},
{
"id": "cloud_connect",
"ver_code": 1
},
{
"id": "iot_cloud",
"ver_code": 1
},
{
"id": "firmware",
"ver_code": 1
},
{
"id": "localSmart",
"ver_code": 1
},
{
"id": "battery_detect",
"ver_code": 1
},
{
"id": "sensitivity",
"ver_code": 1
}
],
"device_id": "SCRUBBED_CHILD_DEVICE_ID_2"
}
],
"start_index": 0,
"sum": 2
},
"get_child_device_list": {
"child_device_list": [
{
"at_low_battery": false,
"avatar": "sensor_t310",
"bind_count": 1,
"category": "subg.trigger.temp-hmdt-sensor",
"current_humidity": 61,
"current_humidity_exception": 1,
"current_temp": 19.5,
"current_temp_exception": 0,
"device_id": "SCRUBBED_CHILD_DEVICE_ID_1",
"fw_ver": "1.5.0",
"hw_id": "00000000000000000000000000000000",
"hw_ver": "1.0",
"jamming_rssi": -105,
"jamming_signal_level": 2,
"lastOnboardingTimestamp": 1690859014,
"mac": "788CB5000000",
"model": "T310",
"nickname": "I01BU0tFRF9OQU1FIw==",
"oem_id": "00000000000000000000000000000000",
"parent_device_id": "0000000000000000000000000000000000000000",
"region": "Pacific/Auckland",
"report_interval": 8,
"rssi": -57,
"signal_level": 3,
"specs": "US",
"status": "online",
"status_follow_edge": false,
"temp_unit": "celsius",
"type": "SMART.TAPOSENSOR"
},
{
"at_low_battery": false,
"avatar": "sensor",
"bind_count": 1,
"category": "subg.trigger.motion-sensor",
"detected": true,
"device_id": "SCRUBBED_CHILD_DEVICE_ID_2",
"fw_ver": "1.12.0 Build 230512 Rel.103040",
"hw_id": "00000000000000000000000000000000",
"hw_ver": "1.0",
"jamming_rssi": -115,
"jamming_signal_level": 1,
"lastOnboardingTimestamp": 1734051318,
"mac": "E4FAC4000000",
"model": "T100",
"nickname": "I01BU0tFRF9OQU1FIw==",
"oem_id": "00000000000000000000000000000000",
"parent_device_id": "0000000000000000000000000000000000000000",
"region": "Pacific/Auckland",
"report_interval": 16,
"rssi": -59,
"signal_level": 3,
"specs": "US",
"status": "online",
"status_follow_edge": false,
"type": "SMART.TAPOSENSOR"
}
],
"start_index": 0,
"sum": 2
},
"get_connect_cloud_state": {
"status": 0
},
"get_device_info": {
"avatar": "",
"device_id": "0000000000000000000000000000000000000000",
"fw_id": "00000000000000000000000000000000",
"fw_ver": "1.5.23 Build 241106 Rel.093525",
"has_set_location_info": true,
"hw_id": "00000000000000000000000000000000",
"hw_ver": "1.0",
"in_alarm": false,
"in_alarm_source": "",
"ip": "127.0.0.123",
"lang": "en_US",
"latitude": 0,
"longitude": 0,
"mac": "9C-A2-F4-00-00-00",
"model": "H100",
"nickname": "I01BU0tFRF9OQU1FIw==",
"oem_id": "00000000000000000000000000000000",
"overheated": false,
"region": "Pacific/Auckland",
"rssi": -52,
"signal_level": 2,
"specs": "AU",
"ssid": "I01BU0tFRF9TU0lEIw==",
"time_diff": 720,
"type": "SMART.TAPOHUB"
},
"get_device_load_info": {
"cur_load_num": 3,
"load_level": "light",
"max_load_num": 64,
"total_memory": 4352,
"used_memory": 1433
},
"get_device_time": {
"region": "Pacific/Auckland",
"time_diff": 720,
"timestamp": 1739230245
},
"get_device_usage": {},
"get_fw_download_state": {
"auto_upgrade": false,
"download_progress": 0,
"reboot_time": 5,
"status": 0,
"upgrade_time": 5
},
"get_inherit_info": null,
"get_latest_fw": {
"fw_size": 0,
"fw_ver": "1.5.23 Build 241106 Rel.093525",
"hw_id": "",
"need_to_upgrade": false,
"oem_id": "",
"release_date": "",
"release_note": "",
"type": 0
},
"get_led_info": {
"bri_config": {
"bri_type": "overall",
"overall_bri": 50
},
"led_rule": "never",
"led_status": false,
"night_mode": {
"end_time": 410,
"night_mode_type": "sunrise_sunset",
"start_time": 1252,
"sunrise_offset": 0,
"sunset_offset": 0
}
},
"get_matter_setup_info": {
"setup_code": "00000000000",
"setup_payload": "00:0000000000000000000"
},
"get_support_alarm_type_list": {
"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",
"Connection 2"
]
},
"get_support_child_device_category": {
"device_category_list": [
{
"category": "subg.trv"
},
{
"category": "subg.trigger"
},
{
"category": "subg.plugswitch"
}
]
},
"get_wireless_scan_info": {
"ap_list": [
{
"bssid": "000000000000",
"channel": 0,
"cipher_type": 2,
"key_type": "wpa2_psk",
"signal_level": 2,
"ssid": "I01BU0tFRF9TU0lEIw=="
},
{
"bssid": "000000000000",
"channel": 0,
"cipher_type": 2,
"key_type": "wpa2_psk",
"signal_level": 2,
"ssid": "I01BU0tFRF9TU0lEIw=="
},
{
"bssid": "000000000000",
"channel": 0,
"cipher_type": 2,
"key_type": "wpa2_psk",
"signal_level": 1,
"ssid": "I01BU0tFRF9TU0lEIw=="
}
],
"start_index": 0,
"sum": 3,
"wep_supported": false
},
"qs_component_nego": {
"component_list": [
{
"id": "quick_setup",
"ver_code": 3
},
{
"id": "sunrise_sunset",
"ver_code": 1
},
{
"id": "iot_cloud",
"ver_code": 1
},
{
"id": "inherit",
"ver_code": 1
},
{
"id": "firmware",
"ver_code": 2
},
{
"id": "matter",
"ver_code": 3
}
],
"extra_info": {
"device_model": "H100",
"device_type": "SMART.TAPOHUB",
"is_klap": true
}
}
}

View File

@ -0,0 +1,304 @@
{
"component_nego": {
"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": "schedule",
"ver_code": 2
},
{
"id": "countdown",
"ver_code": 2
},
{
"id": "antitheft",
"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": "device_local_time",
"ver_code": 1
},
{
"id": "default_states",
"ver_code": 1
},
{
"id": "brightness",
"ver_code": 1
},
{
"id": "preset",
"ver_code": 1
},
{
"id": "on_off_gradually",
"ver_code": 2
},
{
"id": "dimmer_calibration",
"ver_code": 1
},
{
"id": "overheat_protection",
"ver_code": 1
},
{
"id": "matter",
"ver_code": 2
}
]
},
"discovery_result": {
"error_code": 0,
"result": {
"device_id": "00000000000000000000000000000000",
"device_model": "KS225(US)",
"device_type": "SMART.KASASWITCH",
"factory_default": false,
"ip": "127.0.0.123",
"is_support_iot_cloud": true,
"mac": "3C-52-A1-00-00-00",
"mgt_encrypt_schm": {
"encrypt_type": "KLAP",
"http_port": 80,
"is_support_https": false,
"lv": 2
},
"obd_src": "matter",
"owner": "00000000000000000000000000000000",
"protocol_version": 1
}
},
"get_antitheft_rules": {
"antitheft_rule_max_count": 1,
"enable": false,
"rule_list": []
},
"get_auto_update_info": {
"enable": true,
"random_range": 120,
"time": 180
},
"get_connect_cloud_state": {
"status": 0
},
"get_countdown_rules": {
"countdown_rule_max_count": 1,
"enable": false,
"rule_list": []
},
"get_device_info": {
"avatar": "switch_s500d",
"brightness": 25,
"default_states": {
"re_power_type": "always_off",
"re_power_type_capability": [
"last_states",
"always_on",
"always_off"
],
"type": "last_states"
},
"device_id": "0000000000000000000000000000000000000000",
"device_on": false,
"fw_id": "00000000000000000000000000000000",
"fw_ver": "1.1.1 Build 240626 Rel.175125",
"has_set_location_info": true,
"hw_id": "00000000000000000000000000000000",
"hw_ver": "1.0",
"ip": "127.0.0.123",
"lang": "en_US",
"latitude": 0,
"longitude": 0,
"mac": "3C-52-A1-00-00-00",
"model": "KS225",
"nickname": "I01BU0tFRF9OQU1FIw==",
"oem_id": "00000000000000000000000000000000",
"on_time": 0,
"overheat_status": "normal",
"region": "America/Toronto",
"rssi": -38,
"signal_level": 3,
"specs": "",
"ssid": "I01BU0tFRF9TU0lEIw==",
"time_diff": -300,
"type": "SMART.KASASWITCH"
},
"get_device_time": {
"region": "America/Toronto",
"time_diff": -300,
"timestamp": 1739199350
},
"get_device_usage": {
"time_usage": {
"past30": 2189,
"past7": 705,
"today": 0
}
},
"get_fw_download_state": {
"auto_upgrade": false,
"download_progress": 0,
"reboot_time": 5,
"status": 0,
"upgrade_time": 5
},
"get_inherit_info": null,
"get_latest_fw": {
"fw_size": 0,
"fw_ver": "1.1.1 Build 240626 Rel.175125",
"hw_id": "",
"need_to_upgrade": false,
"oem_id": "",
"release_date": "",
"release_note": "",
"type": 0
},
"get_led_info": {
"bri_config": {
"bri_type": "overall",
"overall_bri": 50
},
"led_rule": "always",
"led_status": true,
"night_mode": {
"end_time": 423,
"night_mode_type": "sunrise_sunset",
"start_time": 1036,
"sunrise_offset": 0,
"sunset_offset": 0
}
},
"get_matter_setup_info": {
"setup_code": "00000000000",
"setup_payload": "00:000000-000000000000"
},
"get_next_event": {},
"get_on_off_gradually_info": {
"off_state": {
"duration": 3,
"enable": true,
"max_duration": 60
},
"on_state": {
"duration": 3,
"enable": true,
"max_duration": 60
}
},
"get_preset_rules": {
"brightness": [
100,
75,
50,
25,
1
]
},
"get_schedule_rules": {
"enable": false,
"rule_list": [],
"schedule_rule_max_count": 32,
"start_index": 0,
"sum": 0
},
"get_wireless_scan_info": {
"ap_list": [
{
"bssid": "000000000000",
"channel": 0,
"cipher_type": 2,
"key_type": "wpa2_psk",
"signal_level": 3,
"ssid": "I01BU0tFRF9TU0lEIw=="
}
],
"start_index": 0,
"sum": 19,
"wep_supported": false
},
"qs_component_nego": {
"component_list": [
{
"id": "quick_setup",
"ver_code": 3
},
{
"id": "sunrise_sunset",
"ver_code": 1
},
{
"id": "ble_whole_setup",
"ver_code": 1
},
{
"id": "matter",
"ver_code": 2
},
{
"id": "iot_cloud",
"ver_code": 1
},
{
"id": "inherit",
"ver_code": 1
},
{
"id": "firmware",
"ver_code": 2
}
],
"extra_info": {
"device_model": "KS225",
"device_type": "SMART.KASASWITCH",
"is_klap": true
}
}
}

View File

@ -0,0 +1,480 @@
{
"component_nego": {
"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": "schedule",
"ver_code": 2
},
{
"id": "countdown",
"ver_code": 2
},
{
"id": "antitheft",
"ver_code": 1
},
{
"id": "account",
"ver_code": 1
},
{
"id": "synchronize",
"ver_code": 1
},
{
"id": "sunrise_sunset",
"ver_code": 1
},
{
"id": "cloud_connect",
"ver_code": 1
},
{
"id": "default_states",
"ver_code": 1
},
{
"id": "preset",
"ver_code": 1
},
{
"id": "brightness",
"ver_code": 1
},
{
"id": "color",
"ver_code": 1
},
{
"id": "color_temperature",
"ver_code": 1
},
{
"id": "auto_light",
"ver_code": 1
},
{
"id": "on_off_gradually",
"ver_code": 3
},
{
"id": "device_local_time",
"ver_code": 1
},
{
"id": "light_effect",
"ver_code": 1
},
{
"id": "iot_cloud",
"ver_code": 1
},
{
"id": "bulb_quick_control",
"ver_code": 1
},
{
"id": "localSmart",
"ver_code": 1
}
]
},
"discovery_result": {
"error_code": 0,
"result": {
"device_id": "00000000000000000000000000000000",
"device_model": "L530B(EU)",
"device_type": "SMART.TAPOBULB",
"factory_default": false,
"ip": "127.0.0.123",
"is_support_iot_cloud": true,
"mac": "F0-A7-31-00-00-00",
"mgt_encrypt_schm": {
"encrypt_type": "KLAP",
"http_port": 80,
"is_support_https": false,
"lv": 2
},
"obd_src": "tplink",
"owner": "00000000000000000000000000000000",
"protocol_version": 1
}
},
"get_antitheft_rules": {
"antitheft_rule_max_count": 1,
"enable": false,
"rule_list": []
},
"get_auto_light_info": {
"enable": false,
"mode": "light_track"
},
"get_auto_update_info": {
"enable": true,
"random_range": 120,
"time": 180
},
"get_connect_cloud_state": {
"status": 0
},
"get_countdown_rules": {
"countdown_rule_max_count": 1,
"enable": false,
"rule_list": []
},
"get_device_info": {
"avatar": "bulb",
"brightness": 10,
"color_temp": 4000,
"color_temp_range": [
2500,
6500
],
"default_states": {
"re_power_type": "always_on",
"state": {
"brightness": 10,
"color_temp": 4000,
"hue": 0,
"saturation": 100
},
"type": "last_states"
},
"device_id": "0000000000000000000000000000000000000000",
"device_on": false,
"dynamic_light_effect_enable": false,
"fw_id": "00000000000000000000000000000000",
"fw_ver": "1.1.9 Build 240524 Rel.144922",
"has_set_location_info": true,
"hue": 0,
"hw_id": "00000000000000000000000000000000",
"hw_ver": "3.0",
"ip": "127.0.0.123",
"lang": "en_US",
"latitude": 0,
"longitude": 0,
"mac": "F0-A7-31-00-00-00",
"model": "L530",
"nickname": "I01BU0tFRF9OQU1FIw==",
"oem_id": "00000000000000000000000000000000",
"overheated": false,
"region": "Pacific/Auckland",
"rssi": -55,
"saturation": 100,
"signal_level": 2,
"specs": "",
"ssid": "I01BU0tFRF9TU0lEIw==",
"time_diff": 720,
"type": "SMART.TAPOBULB"
},
"get_device_time": {
"region": "Pacific/Auckland",
"time_diff": 720,
"timestamp": 1739230276
},
"get_device_usage": {
"power_usage": {
"past30": 437,
"past7": 88,
"today": 2
},
"saved_power": {
"past30": 7987,
"past7": 2005,
"today": 62
},
"time_usage": {
"past30": 8424,
"past7": 2093,
"today": 64
}
},
"get_dynamic_light_effect_rules": {
"enable": false,
"max_count": 2,
"rule_list": [
{
"change_mode": "direct",
"change_time": 1000,
"color_status_list": [
[
100,
0,
0,
2700
],
[
100,
321,
99,
0
],
[
100,
196,
99,
0
],
[
100,
6,
97,
0
],
[
100,
160,
100,
0
],
[
100,
274,
95,
0
],
[
100,
48,
100,
0
],
[
100,
242,
99,
0
]
],
"id": "L1",
"scene_name": ""
},
{
"change_mode": "bln",
"change_time": 2000,
"color_status_list": [
[
100,
54,
6,
0
],
[
100,
19,
39,
0
],
[
100,
194,
52,
0
],
[
100,
324,
24,
0
],
[
100,
170,
34,
0
],
[
100,
276,
27,
0
],
[
100,
56,
46,
0
],
[
100,
221,
36,
0
]
],
"id": "L2",
"scene_name": ""
}
],
"start_index": 0,
"sum": 2
},
"get_fw_download_state": {
"auto_upgrade": false,
"download_progress": 0,
"reboot_time": 5,
"status": 0,
"upgrade_time": 5
},
"get_inherit_info": null,
"get_latest_fw": {
"fw_size": 0,
"fw_ver": "1.1.9 Build 240524 Rel.144922",
"hw_id": "",
"need_to_upgrade": false,
"oem_id": "",
"release_date": "",
"release_note": "",
"type": 0
},
"get_next_event": {},
"get_on_off_gradually_info": {
"off_state": {
"duration": 2,
"enable": false,
"max_duration": 60
},
"on_state": {
"duration": 2,
"enable": false,
"max_duration": 60
}
},
"get_preset_rules": {
"states": [
{
"brightness": 100,
"color_temp": 4000,
"hue": 0,
"saturation": 100
},
{
"brightness": 50,
"color_temp": 4000,
"hue": 240,
"saturation": 100
},
{
"brightness": 100,
"color_temp": 0,
"hue": 0,
"saturation": 100
},
{
"brightness": 100,
"color_temp": 0,
"hue": 120,
"saturation": 100
},
{
"brightness": 100,
"color_temp": 0,
"hue": 240,
"saturation": 100
},
{
"brightness": 100,
"color_temp": 0,
"hue": 60,
"saturation": 100
},
{
"brightness": 100,
"color_temp": 0,
"hue": 300,
"saturation": 100
}
]
},
"get_schedule_rules": {
"enable": false,
"rule_list": [],
"schedule_rule_max_count": 32,
"start_index": 0,
"sum": 0
},
"get_wireless_scan_info": {
"ap_list": [
{
"bssid": "000000000000",
"channel": 0,
"cipher_type": 2,
"key_type": "wpa2_psk",
"signal_level": 2,
"ssid": "I01BU0tFRF9TU0lEIw=="
},
{
"bssid": "000000000000",
"channel": 0,
"cipher_type": 2,
"key_type": "wpa2_psk",
"signal_level": 2,
"ssid": "I01BU0tFRF9TU0lEIw=="
},
{
"bssid": "000000000000",
"channel": 0,
"cipher_type": 2,
"key_type": "wpa2_psk",
"signal_level": 1,
"ssid": "I01BU0tFRF9TU0lEIw=="
}
],
"start_index": 0,
"sum": 3,
"wep_supported": false
},
"qs_component_nego": {
"component_list": [
{
"id": "quick_setup",
"ver_code": 3
},
{
"id": "sunrise_sunset",
"ver_code": 1
},
{
"id": "inherit",
"ver_code": 1
},
{
"id": "iot_cloud",
"ver_code": 1
},
{
"id": "firmware",
"ver_code": 2
}
],
"extra_info": {
"device_model": "L530",
"device_type": "SMART.TAPOBULB",
"is_klap": true
}
}
}

View File

@ -0,0 +1,616 @@
{
"component_nego": {
"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": "schedule",
"ver_code": 2
},
{
"id": "countdown",
"ver_code": 2
},
{
"id": "antitheft",
"ver_code": 1
},
{
"id": "account",
"ver_code": 1
},
{
"id": "synchronize",
"ver_code": 1
},
{
"id": "sunrise_sunset",
"ver_code": 1
},
{
"id": "cloud_connect",
"ver_code": 1
},
{
"id": "default_states",
"ver_code": 1
},
{
"id": "preset",
"ver_code": 1
},
{
"id": "brightness",
"ver_code": 1
},
{
"id": "color",
"ver_code": 1
},
{
"id": "color_temperature",
"ver_code": 1
},
{
"id": "auto_light",
"ver_code": 1
},
{
"id": "on_off_gradually",
"ver_code": 3
},
{
"id": "device_local_time",
"ver_code": 1
},
{
"id": "light_effect",
"ver_code": 1
},
{
"id": "iot_cloud",
"ver_code": 1
},
{
"id": "bulb_quick_control",
"ver_code": 1
},
{
"id": "localSmart",
"ver_code": 1
}
]
},
"discovery_result": {
"error_code": 0,
"result": {
"device_id": "00000000000000000000000000000000",
"device_model": "L530E(TW)",
"device_type": "SMART.TAPOBULB",
"factory_default": false,
"ip": "127.0.0.123",
"is_support_iot_cloud": true,
"mac": "5C-62-8B-00-00-00",
"mgt_encrypt_schm": {
"encrypt_type": "KLAP",
"http_port": 80,
"is_support_https": false,
"lv": 2
},
"obd_src": "tplink",
"owner": "00000000000000000000000000000000",
"protocol_version": 1
}
},
"get_antitheft_rules": {
"antitheft_rule_max_count": 1,
"enable": false,
"rule_list": []
},
"get_auto_light_info": {
"enable": false,
"mode": "light_track"
},
"get_auto_update_info": {
"enable": true,
"random_range": 120,
"time": 180
},
"get_connect_cloud_state": {
"status": 0
},
"get_countdown_rules": {
"countdown_rule_max_count": 1,
"enable": false,
"rule_list": []
},
"get_device_info": {
"avatar": "bulb",
"brightness": 100,
"color_temp": 6500,
"color_temp_range": [
2500,
6500
],
"default_states": {
"re_power_type": "always_on",
"state": {
"brightness": 100,
"color_temp": 6500,
"hue": 0,
"saturation": 0
},
"type": "last_states"
},
"device_id": "0000000000000000000000000000000000000000",
"device_on": false,
"dynamic_light_effect_enable": false,
"fw_id": "00000000000000000000000000000000",
"fw_ver": "1.1.1 Build 240623 Rel.114041",
"has_set_location_info": true,
"hue": 0,
"hw_id": "00000000000000000000000000000000",
"hw_ver": "2.0",
"ip": "127.0.0.123",
"lang": "zh_TW",
"latitude": 0,
"longitude": 0,
"mac": "5C-62-8B-00-00-00",
"model": "L530",
"nickname": "I01BU0tFRF9OQU1FIw==",
"oem_id": "00000000000000000000000000000000",
"overheated": false,
"region": "Asia/Taipei",
"rssi": -44,
"saturation": 0,
"signal_level": 3,
"specs": "",
"ssid": "I01BU0tFRF9TU0lEIw==",
"time_diff": 480,
"type": "SMART.TAPOBULB"
},
"get_device_time": {
"region": "Asia/Taipei",
"time_diff": 480,
"timestamp": 1738811667
},
"get_device_usage": {
"power_usage": {
"past30": 17,
"past7": 17,
"today": 17
},
"saved_power": {
"past30": 416,
"past7": 416,
"today": 416
},
"time_usage": {
"past30": 433,
"past7": 433,
"today": 433
}
},
"get_dynamic_light_effect_rules": {
"enable": false,
"max_count": 2,
"rule_list": [
{
"change_mode": "direct",
"change_time": 1000,
"color_status_list": [
[
100,
0,
0,
2700
],
[
100,
321,
99,
0
],
[
100,
196,
99,
0
],
[
100,
6,
97,
0
],
[
100,
160,
100,
0
],
[
100,
274,
95,
0
],
[
100,
48,
100,
0
],
[
100,
242,
99,
0
]
],
"id": "L1",
"scene_name": ""
},
{
"change_mode": "bln",
"change_time": 2000,
"color_status_list": [
[
100,
54,
6,
0
],
[
100,
19,
39,
0
],
[
100,
194,
52,
0
],
[
100,
324,
24,
0
],
[
100,
170,
34,
0
],
[
100,
276,
27,
0
],
[
100,
56,
46,
0
],
[
100,
221,
36,
0
]
],
"id": "L2",
"scene_name": ""
}
],
"start_index": 0,
"sum": 2
},
"get_fw_download_state": {
"auto_upgrade": false,
"download_progress": 0,
"reboot_time": 5,
"status": 0,
"upgrade_time": 5
},
"get_inherit_info": null,
"get_latest_fw": {
"fw_size": 0,
"fw_ver": "1.1.1 Build 240623 Rel.114041",
"hw_id": "",
"need_to_upgrade": false,
"oem_id": "",
"release_date": "",
"release_note": "",
"type": 0
},
"get_next_event": {},
"get_on_off_gradually_info": {
"off_state": {
"duration": 2,
"enable": false,
"max_duration": 60
},
"on_state": {
"duration": 2,
"enable": false,
"max_duration": 60
}
},
"get_preset_rules": {
"states": [
{
"brightness": 50,
"color_temp": 2700,
"hue": 0,
"saturation": 100
},
{
"brightness": 100,
"color_temp": 0,
"hue": 240,
"saturation": 100
},
{
"brightness": 100,
"color_temp": 0,
"hue": 0,
"saturation": 100
},
{
"brightness": 100,
"color_temp": 0,
"hue": 120,
"saturation": 100
},
{
"brightness": 100,
"color_temp": 0,
"hue": 277,
"saturation": 86
},
{
"brightness": 100,
"color_temp": 0,
"hue": 60,
"saturation": 100
},
{
"brightness": 100,
"color_temp": 0,
"hue": 300,
"saturation": 100
}
]
},
"get_schedule_rules": {
"enable": false,
"rule_list": [],
"schedule_rule_max_count": 32,
"start_index": 0,
"sum": 0
},
"get_wireless_scan_info": {
"ap_list": [
{
"bssid": "000000000000",
"channel": 0,
"cipher_type": 2,
"key_type": "wpa2_psk",
"signal_level": 3,
"ssid": "I01BU0tFRF9TU0lEIw=="
},
{
"bssid": "000000000000",
"channel": 0,
"cipher_type": 2,
"key_type": "wpa2_psk",
"signal_level": 3,
"ssid": "I01BU0tFRF9TU0lEIw=="
},
{
"bssid": "000000000000",
"channel": 0,
"cipher_type": 2,
"key_type": "wpa2_psk",
"signal_level": 2,
"ssid": "I01BU0tFRF9TU0lEIw=="
},
{
"bssid": "000000000000",
"channel": 0,
"cipher_type": 2,
"key_type": "wpa2_psk",
"signal_level": 2,
"ssid": "I01BU0tFRF9TU0lEIw=="
},
{
"bssid": "000000000000",
"channel": 0,
"cipher_type": 2,
"key_type": "wpa2_psk",
"signal_level": 2,
"ssid": "I01BU0tFRF9TU0lEIw=="
},
{
"bssid": "000000000000",
"channel": 0,
"cipher_type": 2,
"key_type": "wpa2_psk",
"signal_level": 1,
"ssid": "I01BU0tFRF9TU0lEIw=="
},
{
"bssid": "000000000000",
"channel": 0,
"cipher_type": 2,
"key_type": "wpa2_psk",
"signal_level": 1,
"ssid": "I01BU0tFRF9TU0lEIw=="
},
{
"bssid": "000000000000",
"channel": 0,
"cipher_type": 2,
"key_type": "wpa2_psk",
"signal_level": 1,
"ssid": "I01BU0tFRF9TU0lEIw=="
},
{
"bssid": "000000000000",
"channel": 0,
"cipher_type": 2,
"key_type": "wpa2_psk",
"signal_level": 1,
"ssid": "I01BU0tFRF9TU0lEIw=="
},
{
"bssid": "000000000000",
"channel": 0,
"cipher_type": 2,
"key_type": "wpa2_psk",
"signal_level": 1,
"ssid": "I01BU0tFRF9TU0lEIw=="
},
{
"bssid": "000000000000",
"channel": 0,
"cipher_type": 2,
"key_type": "wpa2_psk",
"signal_level": 1,
"ssid": "I01BU0tFRF9TU0lEIw=="
},
{
"bssid": "000000000000",
"channel": 0,
"cipher_type": 2,
"key_type": "wpa2_psk",
"signal_level": 1,
"ssid": "I01BU0tFRF9TU0lEIw=="
},
{
"bssid": "000000000000",
"channel": 0,
"cipher_type": 2,
"key_type": "wpa2_psk",
"signal_level": 1,
"ssid": "I01BU0tFRF9TU0lEIw=="
},
{
"bssid": "000000000000",
"channel": 0,
"cipher_type": 2,
"key_type": "wpa2_psk",
"signal_level": 1,
"ssid": "I01BU0tFRF9TU0lEIw=="
},
{
"bssid": "000000000000",
"channel": 0,
"cipher_type": 2,
"key_type": "wpa2_psk",
"signal_level": 1,
"ssid": "I01BU0tFRF9TU0lEIw=="
},
{
"bssid": "000000000000",
"channel": 0,
"cipher_type": 2,
"key_type": "wpa2_psk",
"signal_level": 1,
"ssid": "I01BU0tFRF9TU0lEIw=="
},
{
"bssid": "000000000000",
"channel": 0,
"cipher_type": 2,
"key_type": "wpa2_psk",
"signal_level": 1,
"ssid": "I01BU0tFRF9TU0lEIw=="
},
{
"bssid": "000000000000",
"channel": 0,
"cipher_type": 2,
"key_type": "wpa2_psk",
"signal_level": 1,
"ssid": "I01BU0tFRF9TU0lEIw=="
},
{
"bssid": "000000000000",
"channel": 0,
"cipher_type": 2,
"key_type": "wpa2_psk",
"signal_level": 1,
"ssid": "I01BU0tFRF9TU0lEIw=="
},
{
"bssid": "000000000000",
"channel": 0,
"cipher_type": 2,
"key_type": "wpa2_psk",
"signal_level": 1,
"ssid": "I01BU0tFRF9TU0lEIw=="
}
],
"start_index": 0,
"sum": 20,
"wep_supported": false
},
"qs_component_nego": {
"component_list": [
{
"id": "quick_setup",
"ver_code": 3
},
{
"id": "sunrise_sunset",
"ver_code": 1
},
{
"id": "inherit",
"ver_code": 1
},
{
"id": "iot_cloud",
"ver_code": 1
},
{
"id": "firmware",
"ver_code": 2
}
],
"extra_info": {
"device_model": "L530",
"device_type": "SMART.TAPOBULB",
"is_klap": true
}
}
}

View File

@ -0,0 +1,528 @@
{
"component_nego": {
"component_list": [
{
"id": "device",
"ver_code": 2
},
{
"id": "light_strip",
"ver_code": 1
},
{
"id": "light_strip_lighting_effect",
"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": "schedule",
"ver_code": 2
},
{
"id": "countdown",
"ver_code": 2
},
{
"id": "antitheft",
"ver_code": 1
},
{
"id": "account",
"ver_code": 1
},
{
"id": "synchronize",
"ver_code": 1
},
{
"id": "sunrise_sunset",
"ver_code": 1
},
{
"id": "brightness",
"ver_code": 1
},
{
"id": "cloud_connect",
"ver_code": 1
},
{
"id": "color_temperature",
"ver_code": 1
},
{
"id": "default_states",
"ver_code": 1
},
{
"id": "preset",
"ver_code": 3
},
{
"id": "color",
"ver_code": 1
},
{
"id": "on_off_gradually",
"ver_code": 1
},
{
"id": "device_local_time",
"ver_code": 1
},
{
"id": "iot_cloud",
"ver_code": 1
},
{
"id": "music_rhythm",
"ver_code": 3
},
{
"id": "music_rhythm_v2",
"ver_code": 4
},
{
"id": "bulb_quick_control",
"ver_code": 1
},
{
"id": "localSmart",
"ver_code": 1
},
{
"id": "homekit",
"ver_code": 2
},
{
"id": "segment",
"ver_code": 1
},
{
"id": "segment_effect",
"ver_code": 1
},
{
"id": "auto_light",
"ver_code": 1
}
]
},
"discovery_result": {
"error_code": 0,
"result": {
"device_id": "00000000000000000000000000000000",
"device_model": "L930-5(EU)",
"device_type": "SMART.TAPOBULB",
"factory_default": false,
"ip": "127.0.0.123",
"is_support_iot_cloud": true,
"mac": "78-8C-B5-00-00-00",
"mgt_encrypt_schm": {
"encrypt_type": "KLAP",
"http_port": 80,
"is_support_https": false,
"lv": 2
},
"obd_src": "apple",
"owner": "00000000000000000000000000000000",
"protocol_version": 1
}
},
"get_antitheft_rules": {
"antitheft_rule_max_count": 1,
"enable": false,
"rule_list": []
},
"get_auto_light_info": {
"enable": false,
"mode": "light_track"
},
"get_auto_update_info": {
"enable": true,
"random_range": 120,
"time": 180
},
"get_connect_cloud_state": {
"status": 0
},
"get_countdown_rules": {
"countdown_rule_max_count": 1,
"enable": false,
"rule_list": []
},
"get_device_info": {
"avatar": "light_strip",
"brightness": 100,
"color_temp": 0,
"color_temp_range": [
2500,
6500
],
"default_states": {
"state": {
"brightness": 100,
"color_temp": 0,
"hue": 255,
"saturation": 68
},
"type": "last_states"
},
"device_id": "0000000000000000000000000000000000000000",
"device_on": true,
"fw_id": "00000000000000000000000000000000",
"fw_ver": "1.2.5 Build 240727 Rel.102843",
"has_set_location_info": false,
"hue": 255,
"hw_id": "00000000000000000000000000000000",
"hw_ver": "1.0",
"ip": "127.0.0.123",
"lang": "en_US",
"latitude": 0,
"lighting_effect": {
"brightness": 50,
"custom": 0,
"display_colors": [],
"enable": 0,
"id": "",
"name": "station"
},
"longitude": 0,
"mac": "78-8C-B5-00-00-00",
"model": "L930",
"music_rhythm_enable": false,
"music_rhythm_mode": "single_lamp",
"nickname": "I01BU0tFRF9OQU1FIw==",
"oem_id": "00000000000000000000000000000000",
"overheated": false,
"region": "Europe/London",
"rssi": -73,
"saturation": 68,
"segment_effect": {
"brightness": 0,
"custom": 0,
"display_colors": [],
"enable": 0,
"id": "",
"name": "station"
},
"signal_level": 1,
"specs": "",
"ssid": "I01BU0tFRF9TU0lEIw==",
"time_diff": 0,
"type": "SMART.TAPOBULB"
},
"get_device_segment": {
"segment": 50
},
"get_device_time": {
"region": "Europe/London",
"time_diff": 0,
"timestamp": 1739740342
},
"get_device_usage": {
"power_usage": {
"past30": 3515,
"past7": 314,
"today": 229
},
"saved_power": {
"past30": 31361,
"past7": 1442,
"today": 1043
},
"time_usage": {
"past30": 34876,
"past7": 1756,
"today": 1272
}
},
"get_fw_download_state": {
"auto_upgrade": false,
"download_progress": 0,
"reboot_time": 5,
"status": 0,
"upgrade_time": 5
},
"get_homekit_info": {
"mfi_setup_code": "000-00-000",
"mfi_setup_id": "0000",
"mfi_token_token": "000000000000000000000000000/000000000000000000/000000+00000000/00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000+000000000000000000000000000000000000000000000000/0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000+00000000000000000000=",
"mfi_token_uuid": "00000000-0000-0000-0000-000000000000"
},
"get_inherit_info": null,
"get_latest_fw": {
"fw_size": 0,
"fw_ver": "1.2.5 Build 240727 Rel.102843",
"hw_id": "",
"need_to_upgrade": false,
"oem_id": "",
"release_date": "",
"release_note": "",
"type": 0
},
"get_lighting_effect": {
"brightness": 50,
"custom": 0,
"direction": 1,
"display_colors": [],
"duration": 0,
"enable": 0,
"expansion_strategy": 2,
"id": "",
"name": "station",
"repeat_times": 1,
"segment_length": 1,
"sequence": [
[
300,
100,
50
],
[
240,
100,
50
],
[
180,
100,
50
],
[
120,
100,
50
],
[
60,
100,
50
],
[
0,
100,
50
],
[
0,
0,
50
],
[
0,
0,
50
],
[
0,
0,
50
],
[
0,
0,
50
],
[
0,
0,
50
],
[
0,
0,
50
]
],
"spread": 16,
"transition": 400,
"type": "sequence"
},
"get_next_event": {},
"get_on_off_gradually_info": {
"enable": false
},
"get_preset_rules": {
"start_index": 0,
"states": [
{
"brightness": 50,
"color_temp": 4500,
"hue": 0,
"saturation": 100
},
{
"brightness": 100,
"color_temp": 0,
"hue": 240,
"saturation": 100
},
{
"brightness": 100,
"color_temp": 0,
"hue": 0,
"saturation": 100
},
{
"brightness": 100,
"color_temp": 0,
"hue": 120,
"saturation": 100
},
{
"brightness": 100,
"color_temp": 0,
"hue": 277,
"saturation": 86
},
{
"brightness": 100,
"color_temp": 0,
"hue": 60,
"saturation": 100
},
{
"brightness": 100,
"color_temp": 0,
"hue": 300,
"saturation": 100
}
],
"sum": 7
},
"get_schedule_rules": {
"enable": false,
"rule_list": [],
"schedule_rule_max_count": 32,
"start_index": 0,
"sum": 0
},
"get_segment_effect_rule": {
"brightness": 0,
"custom": 0,
"display_colors": [],
"enable": 0,
"id": "",
"name": "station"
},
"get_wireless_scan_info": {
"ap_list": [
{
"bssid": "000000000000",
"channel": 0,
"cipher_type": 2,
"key_type": "wpa2_psk",
"signal_level": 2,
"ssid": "I01BU0tFRF9TU0lEIw=="
},
{
"bssid": "000000000000",
"channel": 0,
"cipher_type": 2,
"key_type": "wpa2_psk",
"signal_level": 1,
"ssid": "I01BU0tFRF9TU0lEIw=="
},
{
"bssid": "000000000000",
"channel": 0,
"cipher_type": 2,
"key_type": "wpa2_psk",
"signal_level": 1,
"ssid": "I01BU0tFRF9TU0lEIw=="
},
{
"bssid": "000000000000",
"channel": 0,
"cipher_type": 2,
"key_type": "wpa2_psk",
"signal_level": 1,
"ssid": "I01BU0tFRF9TU0lEIw=="
},
{
"bssid": "000000000000",
"channel": 0,
"cipher_type": 2,
"key_type": "wpa2_psk",
"signal_level": 1,
"ssid": "I01BU0tFRF9TU0lEIw=="
},
{
"bssid": "000000000000",
"channel": 0,
"cipher_type": 2,
"key_type": "wpa2_psk",
"signal_level": 1,
"ssid": "I01BU0tFRF9TU0lEIw=="
},
{
"bssid": "000000000000",
"channel": 0,
"cipher_type": 2,
"key_type": "wpa2_psk",
"signal_level": 1,
"ssid": "I01BU0tFRF9TU0lEIw=="
},
{
"bssid": "000000000000",
"channel": 0,
"cipher_type": 0,
"key_type": "none",
"signal_level": 1,
"ssid": "I01BU0tFRF9TU0lEIw=="
}
],
"start_index": 0,
"sum": 8,
"wep_supported": false
},
"qs_component_nego": {
"component_list": [
{
"id": "quick_setup",
"ver_code": 3
},
{
"id": "sunrise_sunset",
"ver_code": 1
},
{
"id": "inherit",
"ver_code": 1
},
{
"id": "iot_cloud",
"ver_code": 1
},
{
"id": "firmware",
"ver_code": 2
}
],
"extra_info": {
"device_model": "L930",
"device_type": "SMART.TAPOBULB",
"is_klap": true
}
}
}

View File

@ -0,0 +1,460 @@
{
"component_nego": {
"component_list": [
{
"id": "device",
"ver_code": 2
},
{
"id": "firmware",
"ver_code": 2
},
{
"id": "quick_setup",
"ver_code": 3
},
{
"id": "time",
"ver_code": 1
},
{
"id": "wireless",
"ver_code": 1
},
{
"id": "schedule",
"ver_code": 2
},
{
"id": "countdown",
"ver_code": 2
},
{
"id": "antitheft",
"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": "device_local_time",
"ver_code": 1
},
{
"id": "default_states",
"ver_code": 1
},
{
"id": "auto_off",
"ver_code": 2
},
{
"id": "localSmart",
"ver_code": 1
},
{
"id": "energy_monitoring",
"ver_code": 2
},
{
"id": "power_protection",
"ver_code": 1
},
{
"id": "charging_protection",
"ver_code": 2
},
{
"id": "current_protection",
"ver_code": 1
}
]
},
"discovery_result": {
"error_code": 0,
"result": {
"device_id": "00000000000000000000000000000000",
"device_model": "P110(AU)",
"device_type": "SMART.TAPOPLUG",
"factory_default": false,
"ip": "127.0.0.123",
"is_support_iot_cloud": true,
"mac": "9C-53-22-00-00-00",
"mgt_encrypt_schm": {
"encrypt_type": "KLAP",
"http_port": 80,
"is_support_https": false,
"lv": 2
},
"obd_src": "tplink",
"owner": "00000000000000000000000000000000",
"protocol_version": 1
}
},
"get_antitheft_rules": {
"antitheft_rule_max_count": 1,
"enable": false,
"rule_list": []
},
"get_auto_off_config": {
"delay_min": 120,
"enable": false
},
"get_auto_update_info": {
"enable": true,
"random_range": 120,
"time": 180
},
"get_connect_cloud_state": {
"status": 0
},
"get_countdown_rules": {
"countdown_rule_max_count": 1,
"enable": false,
"rule_list": []
},
"get_current_power": {
"current_power": 0
},
"get_device_info": {
"auto_off_remain_time": 0,
"auto_off_status": "off",
"avatar": "plug",
"charging_status": "normal",
"default_states": {
"state": {},
"type": "last_states"
},
"device_id": "0000000000000000000000000000000000000000",
"device_on": false,
"fw_id": "00000000000000000000000000000000",
"fw_ver": "1.3.1 Build 240621 Rel.162048",
"has_set_location_info": true,
"hw_id": "00000000000000000000000000000000",
"hw_ver": "1.0",
"ip": "127.0.0.123",
"lang": "en_US",
"latitude": 0,
"longitude": 0,
"mac": "9C-53-22-00-00-00",
"model": "P110",
"nickname": "I01BU0tFRF9OQU1FIw==",
"oem_id": "00000000000000000000000000000000",
"on_time": 0,
"overcurrent_status": "normal",
"overheat_status": "normal",
"power_protection_status": "normal",
"region": "Pacific/Auckland",
"rssi": -53,
"signal_level": 2,
"specs": "",
"ssid": "I01BU0tFRF9TU0lEIw==",
"time_diff": 720,
"type": "SMART.TAPOPLUG"
},
"get_device_time": {
"region": "Pacific/Auckland",
"time_diff": 720,
"timestamp": 1739230299
},
"get_device_usage": {
"power_usage": {
"past30": 11,
"past7": 2,
"today": 0
},
"saved_power": {
"past30": 0,
"past7": 8,
"today": 0
},
"time_usage": {
"past30": 10,
"past7": 10,
"today": 0
}
},
"get_electricity_price_config": {
"constant_price": 0,
"time_of_use_config": {
"summer": {
"midpeak": 0,
"offpeak": 0,
"onpeak": 0,
"period": [
0,
0,
0,
0
],
"weekday_config": [
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1
],
"weekend_config": [
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1
]
},
"winter": {
"midpeak": 0,
"offpeak": 0,
"onpeak": 0,
"period": [
0,
0,
0,
0
],
"weekday_config": [
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1
],
"weekend_config": [
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1
]
}
},
"type": "constant"
},
"get_emeter_data": {
"current_ma": 0,
"energy_wh": 0,
"power_mw": 0,
"voltage_mv": 238609
},
"get_emeter_vgain_igain": {
"igain": 11437,
"vgain": 127146
},
"get_energy_usage": {
"current_power": 0,
"electricity_charge": [
0,
0,
0
],
"local_time": "2025-02-11 12:31:41",
"month_energy": 4,
"month_runtime": 10,
"today_energy": 0,
"today_runtime": 0
},
"get_fw_download_state": {
"auto_upgrade": false,
"download_progress": 0,
"reboot_time": 5,
"status": 0,
"upgrade_time": 5
},
"get_latest_fw": {
"fw_size": 0,
"fw_ver": "1.3.1 Build 240621 Rel.162048",
"hw_id": "",
"need_to_upgrade": false,
"oem_id": "",
"release_date": "",
"release_note": "",
"type": 0
},
"get_led_info": {
"bri_config": {
"bri_type": "overall",
"overall_bri": 50
},
"led_rule": "always",
"led_status": false,
"night_mode": {
"end_time": 410,
"night_mode_type": "sunrise_sunset",
"start_time": 1252,
"sunrise_offset": 0,
"sunset_offset": 0
}
},
"get_max_power": {
"max_power": 2541
},
"get_next_event": {},
"get_protection_power": {
"enabled": false,
"protection_power": 0
},
"get_schedule_rules": {
"enable": false,
"rule_list": [],
"schedule_rule_max_count": 32,
"start_index": 0,
"sum": 0
},
"get_wireless_scan_info": {
"ap_list": [
{
"bssid": "000000000000",
"channel": 0,
"cipher_type": 2,
"key_type": "wpa2_psk",
"signal_level": 2,
"ssid": "I01BU0tFRF9TU0lEIw=="
},
{
"bssid": "000000000000",
"channel": 0,
"cipher_type": 2,
"key_type": "wpa2_psk",
"signal_level": 2,
"ssid": "I01BU0tFRF9TU0lEIw=="
},
{
"bssid": "000000000000",
"channel": 0,
"cipher_type": 2,
"key_type": "wpa2_psk",
"signal_level": 1,
"ssid": "I01BU0tFRF9TU0lEIw=="
}
],
"start_index": 0,
"sum": 3,
"wep_supported": false
},
"qs_component_nego": {
"component_list": [
{
"id": "quick_setup",
"ver_code": 3
},
{
"id": "sunrise_sunset",
"ver_code": 1
},
{
"id": "iot_cloud",
"ver_code": 1
},
{
"id": "inherit",
"ver_code": 1
},
{
"id": "firmware",
"ver_code": 2
}
],
"extra_info": {
"device_model": "P110",
"device_type": "SMART.TAPOPLUG",
"is_klap": true
}
}
}

View File

@ -0,0 +1,141 @@
{
"component_nego": {
"component_list": [
{
"id": "device",
"ver_code": 2
},
{
"id": "quick_setup",
"ver_code": 3
},
{
"id": "trigger_log",
"ver_code": 1
},
{
"id": "time",
"ver_code": 1
},
{
"id": "device_local_time",
"ver_code": 1
},
{
"id": "account",
"ver_code": 1
},
{
"id": "synchronize",
"ver_code": 1
},
{
"id": "cloud_connect",
"ver_code": 1
},
{
"id": "iot_cloud",
"ver_code": 1
},
{
"id": "firmware",
"ver_code": 1
},
{
"id": "localSmart",
"ver_code": 1
},
{
"id": "battery_detect",
"ver_code": 1
},
{
"id": "sensitivity",
"ver_code": 1
}
]
},
"get_connect_cloud_state": {
"status": 0
},
"get_device_info": {
"at_low_battery": false,
"avatar": "sensor",
"bind_count": 1,
"category": "subg.trigger.motion-sensor",
"detected": true,
"device_id": "SCRUBBED_CHILD_DEVICE_ID_2",
"fw_ver": "1.12.0 Build 230512 Rel.103040",
"hw_id": "00000000000000000000000000000000",
"hw_ver": "1.0",
"jamming_rssi": -115,
"jamming_signal_level": 1,
"lastOnboardingTimestamp": 1734051318,
"mac": "E4FAC4000000",
"model": "T100",
"nickname": "I01BU0tFRF9OQU1FIw==",
"oem_id": "00000000000000000000000000000000",
"parent_device_id": "0000000000000000000000000000000000000000",
"region": "Pacific/Auckland",
"report_interval": 16,
"rssi": -59,
"signal_level": 3,
"specs": "US",
"status": "online",
"status_follow_edge": false,
"type": "SMART.TAPOSENSOR"
},
"get_fw_download_state": {
"cloud_cache_seconds": 1,
"download_progress": 0,
"reboot_time": 5,
"status": 0,
"upgrade_time": 5
},
"get_latest_fw": {
"fw_size": 0,
"fw_ver": "1.12.0 Build 230512 Rel.103040",
"hw_id": "",
"need_to_upgrade": false,
"oem_id": "",
"release_date": "",
"release_note": "",
"type": 0
},
"get_trigger_logs": {
"logs": [
{
"event": "motion",
"eventId": "51281c8e-c763-3914-0281-c8ec76339140",
"id": 24,
"timestamp": 1739230242
},
{
"event": "motion",
"eventId": "120180c0-e874-b251-2018-0c0e874b2512",
"id": 23,
"timestamp": 1739230209
},
{
"event": "motion",
"eventId": "752388d5-7ba4-c378-adc7-72a845b3c875",
"id": 22,
"timestamp": 1739230188
},
{
"event": "motion",
"eventId": "efa20c53-74e7-264e-fa20-c5374e7264ef",
"id": 21,
"timestamp": 1739230153
},
{
"event": "motion",
"eventId": "962d70de-0962-df09-62d7-0de0962df096",
"id": 20,
"timestamp": 1739230137
}
],
"start_id": 24,
"sum": 24
}
}

View File

@ -75,7 +75,6 @@
} }
] ]
}, },
"get_auto_update_info": -1001,
"get_connect_cloud_state": { "get_connect_cloud_state": {
"status": 0 "status": 0
}, },
@ -84,25 +83,25 @@
"avatar": "sensor_t310", "avatar": "sensor_t310",
"bind_count": 1, "bind_count": 1,
"category": "subg.trigger.temp-hmdt-sensor", "category": "subg.trigger.temp-hmdt-sensor",
"current_humidity": 49, "current_humidity": 61,
"current_humidity_exception": 0, "current_humidity_exception": 1,
"current_temp": 21.7, "current_temp": 21.0,
"current_temp_exception": 0, "current_temp_exception": 0,
"device_id": "SCRUBBED_CHILD_DEVICE_ID_1", "device_id": "SCRUBBED_CHILD_DEVICE_ID_1",
"fw_ver": "1.5.0 Build 230105 Rel.180832", "fw_ver": "1.5.0",
"hw_id": "00000000000000000000000000000000", "hw_id": "00000000000000000000000000000000",
"hw_ver": "1.0", "hw_ver": "1.0",
"jamming_rssi": -111, "jamming_rssi": -108,
"jamming_signal_level": 1, "jamming_signal_level": 2,
"lastOnboardingTimestamp": 1724637745, "lastOnboardingTimestamp": 1690859014,
"mac": "F0A731000000", "mac": "788CB5000000",
"model": "T310", "model": "T310",
"nickname": "I01BU0tFRF9OQU1FIw==", "nickname": "I01BU0tFRF9OQU1FIw==",
"oem_id": "00000000000000000000000000000000", "oem_id": "00000000000000000000000000000000",
"parent_device_id": "0000000000000000000000000000000000000000", "parent_device_id": "0000000000000000000000000000000000000000",
"region": "Australia/Canberra", "region": "Pacific/Auckland",
"report_interval": 16, "report_interval": 8,
"rssi": -46, "rssi": -56,
"signal_level": 3, "signal_level": 3,
"specs": "US", "specs": "US",
"status": "online", "status": "online",
@ -110,8 +109,6 @@
"temp_unit": "celsius", "temp_unit": "celsius",
"type": "SMART.TAPOSENSOR" "type": "SMART.TAPOSENSOR"
}, },
"get_device_time": -1001,
"get_device_usage": -1001,
"get_fw_download_state": { "get_fw_download_state": {
"cloud_cache_seconds": 1, "cloud_cache_seconds": 1,
"download_progress": 0, "download_progress": 0,
@ -121,7 +118,7 @@
}, },
"get_latest_fw": { "get_latest_fw": {
"fw_size": 0, "fw_size": 0,
"fw_ver": "1.5.0 Build 230105 Rel.180832", "fw_ver": "1.5.0",
"hw_id": "", "hw_id": "",
"need_to_upgrade": false, "need_to_upgrade": false,
"oem_id": "", "oem_id": "",
@ -129,10 +126,405 @@
"release_note": "", "release_note": "",
"type": 0 "type": 0
}, },
"get_temp_humidity_records": {
"local_time": 1739107441,
"past24h_humidity": [
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
58,
57,
57,
57,
56,
56,
55,
55,
55,
55,
54,
54,
55,
56,
57,
57,
58,
58,
58,
58,
59,
59,
59,
59,
59,
59,
59,
59,
59,
60,
60,
60,
60,
60,
60,
60,
60,
61,
82,
59,
60,
61,
61,
61,
61
],
"past24h_humidity_exception": [
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
1,
22,
0,
0,
1,
1,
1,
1
],
"past24h_temp": [
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
213,
213,
212,
211,
210,
208,
207,
206,
205,
204,
203,
202,
201,
202,
203,
205,
206,
208,
209,
210,
210,
211,
211,
212,
212,
212,
212,
212,
212,
212,
213,
213,
213,
213,
213,
213,
213,
215,
254,
221,
214,
212,
211,
210,
210
],
"past24h_temp_exception": [
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
-1000,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
4,
0,
0,
0,
0,
0,
0
],
"temp_unit": "celsius"
},
"get_trigger_logs": { "get_trigger_logs": {
"logs": [], "logs": [],
"start_id": 0, "start_id": 0,
"sum": 0 "sum": 0
}, }
"qs_component_nego": -1001
} }

View File

@ -0,0 +1,960 @@
{
"discovery_result": {
"error_code": 0,
"result": {
"decrypted_data": {
"connect_ssid": "#MASKED_SSID#",
"connect_type": "wireless",
"device_id": "0000000000000000000000000000000000000000",
"http_port": 443,
"last_alarm_time": "0",
"last_alarm_type": "",
"owner": "00000000000000000000000000000000",
"sd_status": "normal"
},
"device_id": "00000000000000000000000000000000",
"device_model": "C110",
"device_name": "#MASKED_NAME#",
"device_type": "SMART.IPCAMERA",
"encrypt_info": {
"data": "",
"key": "",
"sym_schm": "AES"
},
"encrypt_type": [
"3"
],
"factory_default": false,
"firmware_version": "1.4.3 Build 240919 Rel.70035n",
"hardware_version": "2.0",
"ip": "127.0.0.123",
"is_support_iot_cloud": true,
"mac": "98-25-4A-00-00-00",
"mgt_encrypt_schm": {
"is_support_https": true
},
"protocol_version": 1
}
},
"getAlertConfig": {
"msg_alarm": {
"capability": {
"alarm_duration_support": "1",
"alarm_volume_support": "1",
"alert_event_type_support": "1",
"usr_def_audio_alarm_max_num": "15",
"usr_def_audio_alarm_support": "1",
"usr_def_audio_max_duration": "15",
"usr_def_audio_type": "0",
"usr_def_start_file_id": "8195"
},
"chn1_msg_alarm_info": {
"alarm_duration": "0",
"alarm_mode": [
"sound",
"light"
],
"alarm_type": "0",
"alarm_volume": "high",
"enabled": "off",
"light_alarm_enabled": "on",
"light_type": "1",
"sound_alarm_enabled": "on"
},
"usr_def_audio": []
}
},
"getAlertPlan": {
"msg_alarm_plan": {
"chn1_msg_alarm_plan": {
"alarm_plan_1": "0000-0000,127",
"enabled": "off"
}
}
},
"getAlertTypeList": {
"msg_alarm": {
"alert_type": {
"alert_type_list": [
"Siren",
"Tone"
]
}
}
},
"getAppComponentList": {
"app_component": {
"app_component_list": [
{
"name": "sdCard",
"version": 1
},
{
"name": "timezone",
"version": 1
},
{
"name": "system",
"version": 3
},
{
"name": "led",
"version": 1
},
{
"name": "playback",
"version": 6
},
{
"name": "detection",
"version": 3
},
{
"name": "alert",
"version": 1
},
{
"name": "firmware",
"version": 2
},
{
"name": "account",
"version": 2
},
{
"name": "quickSetup",
"version": 1
},
{
"name": "video",
"version": 2
},
{
"name": "lensMask",
"version": 2
},
{
"name": "lightFrequency",
"version": 1
},
{
"name": "dayNightMode",
"version": 1
},
{
"name": "osd",
"version": 2
},
{
"name": "record",
"version": 1
},
{
"name": "videoRotation",
"version": 1
},
{
"name": "audio",
"version": 2
},
{
"name": "diagnose",
"version": 1
},
{
"name": "msgPush",
"version": 3
},
{
"name": "deviceShare",
"version": 1
},
{
"name": "tamperDetection",
"version": 1
},
{
"name": "tapoCare",
"version": 1
},
{
"name": "blockZone",
"version": 1
},
{
"name": "babyCryDetection",
"version": 1
},
{
"name": "personDetection",
"version": 2
},
{
"name": "needSubscriptionServiceList",
"version": 1
},
{
"name": "nvmp",
"version": 1
},
{
"name": "detectionRegion",
"version": 2
},
{
"name": "iotCloud",
"version": 1
},
{
"name": "recordDownload",
"version": 1
},
{
"name": "staticIp",
"version": 2
}
]
}
},
"getAudioConfig": {
"audio_config": {
"microphone": {
"bitrate": "64",
"channels": "1",
"echo_cancelling": "off",
"encode_type": "G711alaw",
"input_device_type": "MicIn",
"mute": "off",
"noise_cancelling": "on",
"sampling_rate": "8",
"volume": "100"
},
"speaker": {
"mute": "off",
"output_device_type": "SpeakerOut",
"volume": "100"
}
}
},
"getBCDConfig": {
"sound_detection": {
"bcd": {
"digital_sensitivity": "50",
"enabled": "off",
"sensitivity": "medium"
}
}
},
"getCircularRecordingConfig": {
"harddisk_manage": {
"harddisk": {
"loop": "on"
}
}
},
"getClockStatus": {
"system": {
"clock_status": {
"local_time": "2025-02-11 12:32:27",
"seconds_from_1970": 1739230347
}
}
},
"getConnectStatus": {
"onboarding": {
"get_connect_status": {
"status": 0
}
}
},
"getConnectionType": {
"link_type": "wifi",
"rssi": "3",
"rssiValue": -51,
"ssid": "I01BU0tFRF9TU0lEIw=="
},
"getDetectionConfig": {
"motion_detection": {
"motion_det": {
"digital_sensitivity": "60",
"enabled": "on",
"non_vehicle_enabled": "off",
"people_enabled": "off",
"sensitivity": "medium",
"vehicle_enabled": "off"
}
}
},
"getDeviceInfo": {
"device_info": {
"basic_info": {
"avatar": "camera c100",
"barcode": "",
"dev_id": "0000000000000000000000000000000000000000",
"device_alias": "#MASKED_NAME#",
"device_info": "C110 2.0 IPC",
"device_model": "C110",
"device_name": "#MASKED_NAME#",
"device_type": "SMART.IPCAMERA",
"features": 3,
"ffs": false,
"has_set_location_info": 1,
"hw_desc": "00000000000000000000000000000000",
"hw_id": "00000000000000000000000000000000",
"hw_version": "2.0",
"is_cal": true,
"latitude": 0,
"longitude": 0,
"mac": "98-25-4A-00-00-00",
"manufacturer_name": "TP-LINK",
"mobile_access": "0",
"oem_id": "00000000000000000000000000000000",
"region": "EU",
"sw_version": "1.4.3 Build 240919 Rel.70035n"
}
}
},
"getFirmwareAutoUpgradeConfig": {
"auto_upgrade": {
"common": {
"enabled": "on",
"random_range": "120",
"time": "03:00"
}
}
},
"getFirmwareUpdateStatus": {
"cloud_config": {
"upgrade_status": {
"lastUpgradingSuccess": true,
"state": "normal"
}
}
},
"getLastAlarmInfo": {
"system": {
"last_alarm_info": {
"last_alarm_time": "0",
"last_alarm_type": ""
}
}
},
"getLdc": {
"image": {
"common": {
"area_compensation": "default",
"auto_exp_antiflicker": "off",
"auto_exp_gain_max": "0",
"backlight": "off",
"chroma": "50",
"contrast": "50",
"dehaze": "off",
"eis": "off",
"exp_gain": "0",
"exp_level": "0",
"exp_type": "auto",
"focus_limited": "10",
"focus_type": "manual",
"high_light_compensation": "off",
"inf_delay": "5",
"inf_end_time": "21600",
"inf_sensitivity": "1",
"inf_sensitivity_day2night": "1400",
"inf_sensitivity_night2day": "9100",
"inf_start_time": "64800",
"inf_type": "auto",
"iris_level": "160",
"light_freq_mode": "auto",
"lock_blue_colton": "0",
"lock_blue_gain": "0",
"lock_gb_gain": "0",
"lock_gr_gain": "0",
"lock_green_colton": "0",
"lock_red_colton": "0",
"lock_red_gain": "0",
"lock_source": "local",
"luma": "50",
"saturation": "50",
"sharpness": "50",
"shutter": "1/25",
"smartir": "off",
"smartir_level": "100",
"smartwtl": "auto_wtl",
"smartwtl_digital_level": "100",
"smartwtl_level": "5",
"style": "standard",
"wb_B_gain": "50",
"wb_G_gain": "50",
"wb_R_gain": "50",
"wb_type": "auto",
"wd_gain": "50",
"wide_dynamic": "off",
"wtl_delay": "5",
"wtl_end_time": "21600",
"wtl_sensitivity": "4",
"wtl_sensitivity_day2night": "1400",
"wtl_sensitivity_night2day": "9100",
"wtl_start_time": "64800",
"wtl_type": "auto"
},
"switch": {
"best_view_distance": "0",
"clear_licence_plate_mode": "off",
"flip_type": "off",
"full_color_min_keep_time": "5",
"full_color_people_enhance": "off",
"image_scene_mode": "normal",
"image_scene_mode_autoday": "normal",
"image_scene_mode_autonight": "normal",
"image_scene_mode_common": "normal",
"image_scene_mode_shedday": "normal",
"image_scene_mode_shednight": "normal",
"ldc": "off",
"night_vision_mode": "inf_night_vision",
"overexposure_people_suppression": "off",
"rotate_type": "off",
"schedule_end_time": "64800",
"schedule_start_time": "21600",
"switch_mode": "common",
"wtl_force_time": "300",
"wtl_intensity_level": "5",
"wtl_manual_start_flag": "off"
}
}
},
"getLedStatus": {
"led": {
"config": {
"enabled": "off"
}
}
},
"getLensMaskConfig": {
"lens_mask": {
"lens_mask_info": {
"enabled": "off"
}
}
},
"getLightFrequencyInfo": {
"image": {
"common": {
"area_compensation": "default",
"auto_exp_antiflicker": "off",
"auto_exp_gain_max": "0",
"backlight": "off",
"chroma": "50",
"contrast": "50",
"dehaze": "off",
"eis": "off",
"exp_gain": "0",
"exp_level": "0",
"exp_type": "auto",
"focus_limited": "10",
"focus_type": "manual",
"high_light_compensation": "off",
"inf_delay": "5",
"inf_end_time": "21600",
"inf_sensitivity": "1",
"inf_sensitivity_day2night": "1400",
"inf_sensitivity_night2day": "9100",
"inf_start_time": "64800",
"inf_type": "auto",
"iris_level": "160",
"light_freq_mode": "auto",
"lock_blue_colton": "0",
"lock_blue_gain": "0",
"lock_gb_gain": "0",
"lock_gr_gain": "0",
"lock_green_colton": "0",
"lock_red_colton": "0",
"lock_red_gain": "0",
"lock_source": "local",
"luma": "50",
"saturation": "50",
"sharpness": "50",
"shutter": "1/25",
"smartir": "off",
"smartir_level": "100",
"smartwtl": "auto_wtl",
"smartwtl_digital_level": "100",
"smartwtl_level": "5",
"style": "standard",
"wb_B_gain": "50",
"wb_G_gain": "50",
"wb_R_gain": "50",
"wb_type": "auto",
"wd_gain": "50",
"wide_dynamic": "off",
"wtl_delay": "5",
"wtl_end_time": "21600",
"wtl_sensitivity": "4",
"wtl_sensitivity_day2night": "1400",
"wtl_sensitivity_night2day": "9100",
"wtl_start_time": "64800",
"wtl_type": "auto"
}
}
},
"getMediaEncrypt": {
"cet": {
"media_encrypt": {
"enabled": "off"
}
}
},
"getMsgPushConfig": {
"msg_push": {
"chn1_msg_push_info": {
"notification_enabled": "on",
"rich_notification_enabled": "off"
}
}
},
"getNightVisionCapability": {
"image_capability": {
"supplement_lamp": {
"night_vision_mode_range": [
"inf_night_vision"
],
"supplement_lamp_type": [
"infrared_lamp"
]
}
}
},
"getNightVisionModeConfig": {
"image": {
"switch": {
"best_view_distance": "0",
"clear_licence_plate_mode": "off",
"flip_type": "off",
"full_color_min_keep_time": "5",
"full_color_people_enhance": "off",
"image_scene_mode": "normal",
"image_scene_mode_autoday": "normal",
"image_scene_mode_autonight": "normal",
"image_scene_mode_common": "normal",
"image_scene_mode_shedday": "normal",
"image_scene_mode_shednight": "normal",
"ldc": "off",
"night_vision_mode": "inf_night_vision",
"overexposure_people_suppression": "off",
"rotate_type": "off",
"schedule_end_time": "64800",
"schedule_start_time": "21600",
"switch_mode": "common",
"wtl_force_time": "300",
"wtl_intensity_level": "5",
"wtl_manual_start_flag": "off"
}
}
},
"getPersonDetectionConfig": {
"people_detection": {
"detection": {
"enabled": "on",
"sensitivity": "60"
}
}
},
"getRecordPlan": {
"record_plan": {
"chn1_channel": {
"enabled": "on",
"friday": "[\"0000-2400:2\"]",
"monday": "[\"0000-2400:2\"]",
"saturday": "[\"0000-2400:2\"]",
"sunday": "[\"0000-2400:2\"]",
"thursday": "[\"0000-2400:2\"]",
"tuesday": "[\"0000-2400:2\"]",
"wednesday": "[\"0000-2400:2\"]"
}
}
},
"getRotationStatus": {
"image": {
"switch": {
"best_view_distance": "0",
"clear_licence_plate_mode": "off",
"flip_type": "off",
"full_color_min_keep_time": "5",
"full_color_people_enhance": "off",
"image_scene_mode": "normal",
"image_scene_mode_autoday": "normal",
"image_scene_mode_autonight": "normal",
"image_scene_mode_common": "normal",
"image_scene_mode_shedday": "normal",
"image_scene_mode_shednight": "normal",
"ldc": "off",
"night_vision_mode": "inf_night_vision",
"overexposure_people_suppression": "off",
"rotate_type": "off",
"schedule_end_time": "64800",
"schedule_start_time": "21600",
"switch_mode": "common",
"wtl_force_time": "300",
"wtl_intensity_level": "5",
"wtl_manual_start_flag": "off"
}
}
},
"getSdCardStatus": {
"harddisk_manage": {
"hd_info": [
{
"hd_info_1": {
"crossline_free_space": "0B",
"crossline_free_space_accurate": "0B",
"crossline_total_space": "0B",
"crossline_total_space_accurate": "0B",
"detect_status": "normal",
"disk_name": "1",
"free_space": "113.3GB",
"free_space_accurate": "121601261568B",
"loop_record_status": "0",
"msg_push_free_space": "0B",
"msg_push_free_space_accurate": "0B",
"msg_push_total_space": "0B",
"msg_push_total_space_accurate": "0B",
"percent": "100",
"picture_free_space": "0B",
"picture_free_space_accurate": "0B",
"picture_total_space": "0B",
"picture_total_space_accurate": "0B",
"record_duration": "0",
"record_free_duration": "0",
"record_start_time": "1734403667",
"rw_attr": "rw",
"status": "normal",
"total_space": "113.5GB",
"total_space_accurate": "121869697024B",
"type": "local",
"video_free_space": "113.3GB",
"video_free_space_accurate": "121601261568B",
"video_total_space": "113.5GB",
"video_total_space_accurate": "121869697024B",
"write_protect": "0"
}
}
]
}
},
"getTamperDetectionConfig": {
"tamper_detection": {
"tamper_det": {
"digital_sensitivity": "50",
"enabled": "on",
"sensitivity": "medium"
}
}
},
"getTimezone": {
"system": {
"basic": {
"timezone": "UTC+12:00",
"timing_mode": "ntp",
"zone_id": "Pacific/Auckland"
}
}
},
"getVideoCapability": {
"video_capability": {
"main": {
"bitrate_types": [
"cbr",
"vbr"
],
"bitrates": [
"256",
"512",
"1024",
"1382",
"2048"
],
"change_fps_support": "1",
"encode_types": [
"H264",
"H265"
],
"frame_rates": [
"65551",
"65556",
"65561"
],
"minor_stream_support": "0",
"qualitys": [
"1",
"3",
"5"
],
"resolutions": [
"2304*1296",
"1920*1080",
"1280*720"
]
}
}
},
"getVideoQualities": {
"video": {
"main": {
"bitrate": "1382",
"bitrate_type": "vbr",
"default_bitrate": "1382",
"encode_type": "H264",
"frame_rate": "65566",
"name": "VideoEncoder_1",
"quality": "3",
"resolution": "2304*1296",
"smart_codec": "off"
}
}
},
"getWhitelampConfig": {
"image": {
"switch": {
"best_view_distance": "0",
"clear_licence_plate_mode": "off",
"flip_type": "off",
"full_color_min_keep_time": "5",
"full_color_people_enhance": "off",
"image_scene_mode": "normal",
"image_scene_mode_autoday": "normal",
"image_scene_mode_autonight": "normal",
"image_scene_mode_common": "normal",
"image_scene_mode_shedday": "normal",
"image_scene_mode_shednight": "normal",
"ldc": "off",
"night_vision_mode": "inf_night_vision",
"overexposure_people_suppression": "off",
"rotate_type": "off",
"schedule_end_time": "64800",
"schedule_start_time": "21600",
"switch_mode": "common",
"wtl_force_time": "300",
"wtl_intensity_level": "5",
"wtl_manual_start_flag": "off"
}
}
},
"getWhitelampStatus": {
"rest_time": 0,
"status": 0
},
"get_audio_capability": {
"get": {
"audio_capability": {
"device_microphone": {
"aec": "1",
"channels": "1",
"echo_cancelling": "0",
"encode_type": [
"G711alaw"
],
"half_duplex": "1",
"mute": "1",
"noise_cancelling": "1",
"sampling_rate": [
"8",
"16"
],
"volume": "1"
},
"device_speaker": {
"channels": "1",
"decode_type": [
"G711alaw",
"G711ulaw"
],
"mute": "0",
"output_device_type": "0",
"sampling_rate": [
"8",
"16"
],
"system_volume": "100",
"volume": "1"
}
}
}
},
"get_audio_config": {
"get": {
"audio_config": {
"microphone": {
"bitrate": "64",
"channels": "1",
"echo_cancelling": "off",
"encode_type": "G711alaw",
"input_device_type": "MicIn",
"mute": "off",
"noise_cancelling": "on",
"sampling_rate": "8",
"volume": "100"
},
"speaker": {
"mute": "off",
"output_device_type": "SpeakerOut",
"volume": "100"
}
}
}
},
"get_cet": {
"get": {
"cet": {
"vhttpd": {
"port": "8800"
}
}
}
},
"get_function": {
"get": {
"function": {
"module_spec": {
"ae_weighting_table_resolution": "5*5",
"ai_enhance_capability": "1",
"ai_enhance_range": [
"traditional_enhance"
],
"ai_firmware_upgrade": "0",
"alarm_out_num": "0",
"app_version": "1.0.0",
"audio": [
"speaker",
"microphone"
],
"auth_encrypt": "1",
"auto_ip_configurable": "1",
"backlight_coexistence": "1",
"change_password": "1",
"client_info": "1",
"cloud_storage_version": "1.0",
"config_recovery": [
"audio_config",
"OSD",
"image",
"video"
],
"custom_area_compensation": "1",
"custom_auto_mode_exposure_level": "1",
"daynight_subdivision": "1",
"device_share": [
"preview",
"playback",
"voice",
"cloud_storage"
],
"download": [
"video"
],
"events": [
"motion",
"tamper"
],
"force_iframe_support": "1",
"greeter": "1.0",
"http_system_state_audio_support": "1",
"image_capability": "1",
"image_list": [
"supplement_lamp",
"expose"
],
"ir_led_pwm_control": "1",
"led": "1",
"lens_mask": "1",
"linkage_capability": "1",
"local_storage": "1",
"media_encrypt": "1",
"motor": "0",
"msg_alarm": "1",
"msg_alarm_list": [
"sound",
"light"
],
"msg_push": "1",
"multi_user": "0",
"multicast": "0",
"network": [
"wifi"
],
"osd_capability": "1",
"ota_upgrade": "1",
"p2p_support_versions": [
"1.1"
],
"personalized_audio_alarm": "0",
"playback": [
"local",
"p2p",
"relay"
],
"playback_scale": "1",
"preview": [
"local",
"p2p",
"relay"
],
"privacy_mask_api_version": "1.0",
"record_max_slot_cnt": "10",
"record_type": [
"timing",
"motion"
],
"relay_support_versions": [
"1.3"
],
"remote_upgrade": "1",
"reonboarding": "1",
"smart_codec": "0",
"smart_detection": "1",
"smart_msg_push_capability": "1",
"ssl_cer_version": "1.0",
"storage_api_version": "2.2",
"storage_capability": "1",
"stream_max_sessions": "10",
"streaming_support_versions": [
"1.0"
],
"tapo_care_version": "1.0.0",
"target_track": "0",
"timing_reboot": "1",
"verification_change_password": "1",
"video_codec": [
"h264"
],
"video_detection_digital_sensitivity": "1",
"wide_range_inf_sensitivity": "1",
"wifi_cascade_connection": "1",
"wifi_connection_info": "1",
"wireless_hotspot": "1"
}
}
}
},
"scanApList": {
"onboarding": {
"scan": {
"ap_list": [
{
"auth": 4,
"bssid": "000000000000",
"encryption": 3,
"rssi": 4,
"ssid": "I01BU0tFRF9TU0lEIw=="
},
{
"auth": 4,
"bssid": "000000000000",
"encryption": 3,
"rssi": 2,
"ssid": "I01BU0tFRF9TU0lEIw=="
}
],
"wpa3_supported": "false"
}
}
}
}

View File

@ -0,0 +1,204 @@
from datetime import timedelta
from typing import Final
import pytest
from pytest_mock import MockerFixture
from kasa import KasaException, Module
from kasa.iot import IotDimmer
from kasa.iot.modules.dimmer import Dimmer
from ...device_fixtures import dimmer_iot
_TD_ONE_MS: Final[timedelta] = timedelta(milliseconds=1)
@dimmer_iot
def test_dimmer_getters(dev: IotDimmer):
assert Module.IotDimmer in dev.modules
dimmer: Dimmer = dev.modules[Module.IotDimmer]
assert dimmer.threshold_min == dimmer.config["minThreshold"]
assert int(dimmer.fade_off_time / _TD_ONE_MS) == dimmer.config["fadeOffTime"]
assert int(dimmer.fade_on_time / _TD_ONE_MS) == dimmer.config["fadeOnTime"]
assert int(dimmer.gentle_off_time / _TD_ONE_MS) == dimmer.config["gentleOffTime"]
assert int(dimmer.gentle_on_time / _TD_ONE_MS) == dimmer.config["gentleOnTime"]
assert dimmer.ramp_rate == dimmer.config["rampRate"]
@dimmer_iot
async def test_dimmer_setters(dev: IotDimmer, mocker: MockerFixture):
dimmer: Dimmer = dev.modules[Module.IotDimmer]
query_helper = mocker.patch("kasa.iot.IotDimmer._query_helper")
test_threshold = 10
await dimmer.set_threshold_min(test_threshold)
query_helper.assert_called_with(
"smartlife.iot.dimmer", "calibrate_brightness", {"minThreshold": test_threshold}
)
test_time = 100
await dimmer.set_fade_off_time(test_time)
query_helper.assert_called_with(
"smartlife.iot.dimmer", "set_fade_off_time", {"fadeTime": test_time}
)
await dimmer.set_fade_on_time(test_time)
query_helper.assert_called_with(
"smartlife.iot.dimmer", "set_fade_on_time", {"fadeTime": test_time}
)
test_time = 1000
await dimmer.set_gentle_off_time(test_time)
query_helper.assert_called_with(
"smartlife.iot.dimmer", "set_gentle_off_time", {"duration": test_time}
)
await dimmer.set_gentle_on_time(test_time)
query_helper.assert_called_with(
"smartlife.iot.dimmer", "set_gentle_on_time", {"duration": test_time}
)
test_rate = 30
await dimmer.set_ramp_rate(test_rate)
query_helper.assert_called_with(
"smartlife.iot.dimmer", "set_button_ramp_rate", {"rampRate": test_rate}
)
@dimmer_iot
async def test_dimmer_setter_min(dev: IotDimmer, mocker: MockerFixture):
dimmer: Dimmer = dev.modules[Module.IotDimmer]
query_helper = mocker.patch("kasa.iot.IotDimmer._query_helper")
test_threshold = dimmer.THRESHOLD_ABS_MIN
await dimmer.set_threshold_min(test_threshold)
query_helper.assert_called_with(
"smartlife.iot.dimmer", "calibrate_brightness", {"minThreshold": test_threshold}
)
test_time = int(dimmer.FADE_TIME_ABS_MIN / _TD_ONE_MS)
await dimmer.set_fade_off_time(test_time)
query_helper.assert_called_with(
"smartlife.iot.dimmer", "set_fade_off_time", {"fadeTime": test_time}
)
await dimmer.set_fade_on_time(test_time)
query_helper.assert_called_with(
"smartlife.iot.dimmer", "set_fade_on_time", {"fadeTime": test_time}
)
test_time = int(dimmer.GENTLE_TIME_ABS_MIN / _TD_ONE_MS)
await dimmer.set_gentle_off_time(test_time)
query_helper.assert_called_with(
"smartlife.iot.dimmer", "set_gentle_off_time", {"duration": test_time}
)
await dimmer.set_gentle_on_time(test_time)
query_helper.assert_called_with(
"smartlife.iot.dimmer", "set_gentle_on_time", {"duration": test_time}
)
test_rate = dimmer.RAMP_RATE_ABS_MIN
await dimmer.set_ramp_rate(test_rate)
query_helper.assert_called_with(
"smartlife.iot.dimmer", "set_button_ramp_rate", {"rampRate": test_rate}
)
@dimmer_iot
async def test_dimmer_setter_max(dev: IotDimmer, mocker: MockerFixture):
dimmer: Dimmer = dev.modules[Module.IotDimmer]
query_helper = mocker.patch("kasa.iot.IotDimmer._query_helper")
test_threshold = dimmer.THRESHOLD_ABS_MAX
await dimmer.set_threshold_min(test_threshold)
query_helper.assert_called_with(
"smartlife.iot.dimmer", "calibrate_brightness", {"minThreshold": test_threshold}
)
test_time = int(dimmer.FADE_TIME_ABS_MAX / _TD_ONE_MS)
await dimmer.set_fade_off_time(test_time)
query_helper.assert_called_with(
"smartlife.iot.dimmer", "set_fade_off_time", {"fadeTime": test_time}
)
await dimmer.set_fade_on_time(test_time)
query_helper.assert_called_with(
"smartlife.iot.dimmer", "set_fade_on_time", {"fadeTime": test_time}
)
test_time = int(dimmer.GENTLE_TIME_ABS_MAX / _TD_ONE_MS)
await dimmer.set_gentle_off_time(test_time)
query_helper.assert_called_with(
"smartlife.iot.dimmer", "set_gentle_off_time", {"duration": test_time}
)
await dimmer.set_gentle_on_time(test_time)
query_helper.assert_called_with(
"smartlife.iot.dimmer", "set_gentle_on_time", {"duration": test_time}
)
test_rate = dimmer.RAMP_RATE_ABS_MAX
await dimmer.set_ramp_rate(test_rate)
query_helper.assert_called_with(
"smartlife.iot.dimmer", "set_button_ramp_rate", {"rampRate": test_rate}
)
@dimmer_iot
async def test_dimmer_setters_min_oob(dev: IotDimmer, mocker: MockerFixture):
dimmer: Dimmer = dev.modules[Module.IotDimmer]
query_helper = mocker.patch("kasa.iot.IotDimmer._query_helper")
test_threshold = dimmer.THRESHOLD_ABS_MIN - 1
with pytest.raises(KasaException):
await dimmer.set_threshold_min(test_threshold)
query_helper.assert_not_called()
test_time = dimmer.FADE_TIME_ABS_MIN - _TD_ONE_MS
with pytest.raises(KasaException):
await dimmer.set_fade_off_time(test_time)
query_helper.assert_not_called()
with pytest.raises(KasaException):
await dimmer.set_fade_on_time(test_time)
query_helper.assert_not_called()
test_time = dimmer.GENTLE_TIME_ABS_MIN - _TD_ONE_MS
with pytest.raises(KasaException):
await dimmer.set_gentle_off_time(test_time)
query_helper.assert_not_called()
with pytest.raises(KasaException):
await dimmer.set_gentle_on_time(test_time)
query_helper.assert_not_called()
test_rate = dimmer.RAMP_RATE_ABS_MIN - 1
with pytest.raises(KasaException):
await dimmer.set_ramp_rate(test_rate)
query_helper.assert_not_called()
@dimmer_iot
async def test_dimmer_setters_max_oob(dev: IotDimmer, mocker: MockerFixture):
dimmer: Dimmer = dev.modules[Module.IotDimmer]
query_helper = mocker.patch("kasa.iot.IotDimmer._query_helper")
test_threshold = dimmer.THRESHOLD_ABS_MAX + 1
with pytest.raises(KasaException):
await dimmer.set_threshold_min(test_threshold)
query_helper.assert_not_called()
test_time = dimmer.FADE_TIME_ABS_MAX + _TD_ONE_MS
with pytest.raises(KasaException):
await dimmer.set_fade_off_time(test_time)
query_helper.assert_not_called()
with pytest.raises(KasaException):
await dimmer.set_fade_on_time(test_time)
query_helper.assert_not_called()
test_time = dimmer.GENTLE_TIME_ABS_MAX + _TD_ONE_MS
with pytest.raises(KasaException):
await dimmer.set_gentle_off_time(test_time)
query_helper.assert_not_called()
with pytest.raises(KasaException):
await dimmer.set_gentle_on_time(test_time)
query_helper.assert_not_called()
test_rate = dimmer.RAMP_RATE_ABS_MAX + 1
with pytest.raises(KasaException):
await dimmer.set_ramp_rate(test_rate)
query_helper.assert_not_called()

View File

@ -277,12 +277,12 @@ async def test_get_modules():
# Modules on device # Modules on device
module = dummy_device.modules.get("cloud") module = dummy_device.modules.get("cloud")
assert module assert module
assert module._device == dummy_device assert module.device == dummy_device
assert isinstance(module, Cloud) assert isinstance(module, Cloud)
module = dummy_device.modules.get(Module.IotCloud) module = dummy_device.modules.get(Module.IotCloud)
assert module assert module
assert module._device == dummy_device assert module.device == dummy_device
assert isinstance(module, Cloud) assert isinstance(module, Cloud)
# Invalid modules # Invalid modules

View File

@ -60,6 +60,25 @@ async def test_dustbin_mode(dev: SmartDevice, mocker: MockerFixture):
await dustbin.set_mode("invalid") await dustbin.set_mode("invalid")
@dustbin
async def test_dustbin_mode_off(dev: SmartDevice, mocker: MockerFixture):
"""Test dustbin_mode == Off."""
dustbin = next(get_parent_and_child_modules(dev, Module.Dustbin))
call = mocker.spy(dustbin, "call")
auto_collection = dustbin._device.features["dustbin_mode"]
await auto_collection.set_value(Mode.Off.name)
params = dustbin._settings.copy()
params["auto_dust_collection"] = False
call.assert_called_with("setDustCollectionInfo", params)
await dev.update()
assert dustbin.auto_collection is False
assert dustbin.mode is Mode.Off.name
@dustbin @dustbin
async def test_autocollection(dev: SmartDevice, mocker: MockerFixture): async def test_autocollection(dev: SmartDevice, mocker: MockerFixture):
"""Test autocollection switch.""" """Test autocollection switch."""

View File

@ -58,7 +58,7 @@ async def test_fan_module(dev: SmartDevice, mocker: MockerFixture):
assert isinstance(dev, SmartDevice) assert isinstance(dev, SmartDevice)
fan = next(get_parent_and_child_modules(dev, Module.Fan)) fan = next(get_parent_and_child_modules(dev, Module.Fan))
assert fan assert fan
device = fan._device device = fan.device
await fan.set_fan_speed_level(1) await fan.set_fan_speed_level(1)
await dev.update() await dev.update()

View File

@ -604,7 +604,7 @@ async def test_get_modules():
# Modules on device # Modules on device
module = dummy_device.modules.get("Cloud") module = dummy_device.modules.get("Cloud")
assert module assert module
assert module._device == dummy_device assert module.device == dummy_device
assert isinstance(module, Cloud) assert isinstance(module, Cloud)
module = dummy_device.modules.get(Module.Cloud) module = dummy_device.modules.get(Module.Cloud)
@ -617,8 +617,8 @@ async def test_get_modules():
assert module is None assert module is None
module = next(get_parent_and_child_modules(dummy_device, "Fan")) module = next(get_parent_and_child_modules(dummy_device, "Fan"))
assert module assert module
assert module._device != dummy_device assert module.device != dummy_device
assert module._device._parent == dummy_device assert module.device.parent == dummy_device
# Invalid modules # Invalid modules
module = dummy_device.modules.get("DummyModule") module = dummy_device.modules.get("DummyModule")

View File

@ -1,10 +1,16 @@
import importlib
import inspect
import pkgutil
import sys
from datetime import datetime from datetime import datetime
from zoneinfo import ZoneInfo from zoneinfo import ZoneInfo
import pytest import pytest
from pytest_mock import MockerFixture from pytest_mock import MockerFixture
import kasa.interfaces
from kasa import Device, LightState, Module, ThermostatState from kasa import Device, LightState, Module, ThermostatState
from kasa.module import _get_feature_attribute
from .device_fixtures import ( from .device_fixtures import (
bulb_iot, bulb_iot,
@ -64,6 +70,57 @@ temp_control_smart = parametrize(
) )
interfaces = pytest.mark.parametrize("interface", kasa.interfaces.__all__)
def _get_subclasses(of_class, package):
"""Get all the subclasses of a given class."""
subclasses = set()
# iter_modules returns ModuleInfo: (module_finder, name, ispkg)
for _, modname, ispkg in pkgutil.iter_modules(package.__path__):
importlib.import_module("." + modname, package=package.__name__)
module = sys.modules[package.__name__ + "." + modname]
for _, obj in inspect.getmembers(module):
if (
inspect.isclass(obj)
and issubclass(obj, of_class)
and obj is not of_class
):
subclasses.add(obj)
if ispkg:
res = _get_subclasses(of_class, module)
subclasses.update(res)
return subclasses
@interfaces
def test_feature_attributes(interface):
"""Test that all common derived classes define the FeatureAttributes."""
klass = getattr(kasa.interfaces, interface)
package = sys.modules["kasa"]
sub_classes = _get_subclasses(klass, package)
feat_attributes: set[str] = set()
attribute_names = [
k
for k, v in vars(klass).items()
if (callable(v) and not inspect.isclass(v)) or isinstance(v, property)
]
for attr_name in attribute_names:
attribute = getattr(klass, attr_name)
if _get_feature_attribute(attribute):
feat_attributes.add(attr_name)
for sub_class in sub_classes:
for attr_name in feat_attributes:
attribute = getattr(sub_class, attr_name)
fa = _get_feature_attribute(attribute)
assert fa, f"{attr_name} is not a defined module feature for {sub_class}"
@led @led
async def test_led_module(dev: Device, mocker: MockerFixture): async def test_led_module(dev: Device, mocker: MockerFixture):
"""Test fan speed feature.""" """Test fan speed feature."""
@ -176,7 +233,7 @@ async def test_light_brightness(dev: Device):
assert light assert light
# Test getting the value # Test getting the value
feature = light._device.features["brightness"] feature = light.device.features["brightness"]
assert feature.minimum_value == 0 assert feature.minimum_value == 0
assert feature.maximum_value == 100 assert feature.maximum_value == 100
@ -205,7 +262,7 @@ async def test_light_color_temp(dev: Device):
) )
# Test getting the value # Test getting the value
feature = light._device.features["color_temperature"] feature = light.device.features["color_temperature"]
assert isinstance(feature.minimum_value, int) assert isinstance(feature.minimum_value, int)
assert isinstance(feature.maximum_value, int) assert isinstance(feature.maximum_value, int)
@ -237,7 +294,7 @@ async def test_light_set_state(dev: Device):
light = next(get_parent_and_child_modules(dev, Module.Light)) light = next(get_parent_and_child_modules(dev, Module.Light))
assert light assert light
# For fixtures that have a light effect active switch off # For fixtures that have a light effect active switch off
if light_effect := light._device.modules.get(Module.LightEffect): if light_effect := light.device.modules.get(Module.LightEffect):
await light_effect.set_effect(light_effect.LIGHT_EFFECTS_OFF) await light_effect.set_effect(light_effect.LIGHT_EFFECTS_OFF)
await light.set_state(LightState(light_on=False)) await light.set_state(LightState(light_on=False))
@ -264,7 +321,7 @@ async def test_light_preset_module(dev: Device, mocker: MockerFixture):
assert preset_mod assert preset_mod
light_mod = next(get_parent_and_child_modules(dev, Module.Light)) light_mod = next(get_parent_and_child_modules(dev, Module.Light))
assert light_mod assert light_mod
feat = preset_mod._device.features["light_preset"] feat = preset_mod.device.features["light_preset"]
preset_list = preset_mod.preset_list preset_list = preset_mod.preset_list
assert "Not set" in preset_list assert "Not set" in preset_list

360
uv.lock generated
View File

@ -3,16 +3,16 @@ requires-python = ">=3.11, <4.0"
[[package]] [[package]]
name = "aiohappyeyeballs" name = "aiohappyeyeballs"
version = "2.4.4" version = "2.4.6"
source = { registry = "https://pypi.org/simple" } source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/7f/55/e4373e888fdacb15563ef6fa9fa8c8252476ea071e96fb46defac9f18bf2/aiohappyeyeballs-2.4.4.tar.gz", hash = "sha256:5fdd7d87889c63183afc18ce9271f9b0a7d32c2303e394468dd45d514a757745", size = 21977 } sdist = { url = "https://files.pythonhosted.org/packages/08/07/508f9ebba367fc3370162e53a3cfd12f5652ad79f0e0bfdf9f9847c6f159/aiohappyeyeballs-2.4.6.tar.gz", hash = "sha256:9b05052f9042985d32ecbe4b59a77ae19c006a78f1344d7fdad69d28ded3d0b0", size = 21726 }
wheels = [ wheels = [
{ url = "https://files.pythonhosted.org/packages/b9/74/fbb6559de3607b3300b9be3cc64e97548d55678e44623db17820dbd20002/aiohappyeyeballs-2.4.4-py3-none-any.whl", hash = "sha256:a980909d50efcd44795c4afeca523296716d50cd756ddca6af8c65b996e27de8", size = 14756 }, { url = "https://files.pythonhosted.org/packages/44/4c/03fb05f56551828ec67ceb3665e5dc51638042d204983a03b0a1541475b6/aiohappyeyeballs-2.4.6-py3-none-any.whl", hash = "sha256:147ec992cf873d74f5062644332c539fcd42956dc69453fe5204195e560517e1", size = 14543 },
] ]
[[package]] [[package]]
name = "aiohttp" name = "aiohttp"
version = "3.11.11" version = "3.11.12"
source = { registry = "https://pypi.org/simple" } source = { registry = "https://pypi.org/simple" }
dependencies = [ dependencies = [
{ name = "aiohappyeyeballs" }, { name = "aiohappyeyeballs" },
@ -23,53 +23,56 @@ dependencies = [
{ name = "propcache" }, { name = "propcache" },
{ name = "yarl" }, { name = "yarl" },
] ]
sdist = { url = "https://files.pythonhosted.org/packages/fe/ed/f26db39d29cd3cb2f5a3374304c713fe5ab5a0e4c8ee25a0c45cc6adf844/aiohttp-3.11.11.tar.gz", hash = "sha256:bb49c7f1e6ebf3821a42d81d494f538107610c3a705987f53068546b0e90303e", size = 7669618 } sdist = { url = "https://files.pythonhosted.org/packages/37/4b/952d49c73084fb790cb5c6ead50848c8e96b4980ad806cf4d2ad341eaa03/aiohttp-3.11.12.tar.gz", hash = "sha256:7603ca26d75b1b86160ce1bbe2787a0b706e592af5b2504e12caa88a217767b0", size = 7673175 }
wheels = [ wheels = [
{ url = "https://files.pythonhosted.org/packages/34/ae/e8806a9f054e15f1d18b04db75c23ec38ec954a10c0a68d3bd275d7e8be3/aiohttp-3.11.11-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ba74ec819177af1ef7f59063c6d35a214a8fde6f987f7661f4f0eecc468a8f76", size = 708624 }, { url = "https://files.pythonhosted.org/packages/9c/38/35311e70196b6a63cfa033a7f741f800aa8a93f57442991cbe51da2394e7/aiohttp-3.11.12-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:87a2e00bf17da098d90d4145375f1d985a81605267e7f9377ff94e55c5d769eb", size = 708797 },
{ url = "https://files.pythonhosted.org/packages/c7/e0/313ef1a333fb4d58d0c55a6acb3cd772f5d7756604b455181049e222c020/aiohttp-3.11.11-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4af57160800b7a815f3fe0eba9b46bf28aafc195555f1824555fa2cfab6c1538", size = 468507 }, { url = "https://files.pythonhosted.org/packages/44/3e/46c656e68cbfc4f3fc7cb5d2ba4da6e91607fe83428208028156688f6201/aiohttp-3.11.12-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b34508f1cd928ce915ed09682d11307ba4b37d0708d1f28e5774c07a7674cac9", size = 468669 },
{ url = "https://files.pythonhosted.org/packages/a9/60/03455476bf1f467e5b4a32a465c450548b2ce724eec39d69f737191f936a/aiohttp-3.11.11-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ffa336210cf9cd8ed117011085817d00abe4c08f99968deef0013ea283547204", size = 455571 }, { url = "https://files.pythonhosted.org/packages/a0/d6/2088fb4fd1e3ac2bfb24bc172223babaa7cdbb2784d33c75ec09e66f62f8/aiohttp-3.11.12-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:936d8a4f0f7081327014742cd51d320296b56aa6d324461a13724ab05f4b2933", size = 455739 },
{ url = "https://files.pythonhosted.org/packages/be/f9/469588603bd75bf02c8ffb8c8a0d4b217eed446b49d4a767684685aa33fd/aiohttp-3.11.11-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:81b8fe282183e4a3c7a1b72f5ade1094ed1c6345a8f153506d114af5bf8accd9", size = 1685694 }, { url = "https://files.pythonhosted.org/packages/e7/dc/c443a6954a56f4a58b5efbfdf23cc6f3f0235e3424faf5a0c56264d5c7bb/aiohttp-3.11.12-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2de1378f72def7dfb5dbd73d86c19eda0ea7b0a6873910cc37d57e80f10d64e1", size = 1685858 },
{ url = "https://files.pythonhosted.org/packages/88/b9/1b7fa43faf6c8616fa94c568dc1309ffee2b6b68b04ac268e5d64b738688/aiohttp-3.11.11-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3af41686ccec6a0f2bdc66686dc0f403c41ac2089f80e2214a0f82d001052c03", size = 1743660 }, { url = "https://files.pythonhosted.org/packages/25/67/2d5b3aaade1d5d01c3b109aa76e3aa9630531252cda10aa02fb99b0b11a1/aiohttp-3.11.12-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b9d45dbb3aaec05cf01525ee1a7ac72de46a8c425cb75c003acd29f76b1ffe94", size = 1743829 },
{ url = "https://files.pythonhosted.org/packages/2a/8b/0248d19dbb16b67222e75f6aecedd014656225733157e5afaf6a6a07e2e8/aiohttp-3.11.11-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:70d1f9dde0e5dd9e292a6d4d00058737052b01f3532f69c0c65818dac26dc287", size = 1785421 }, { url = "https://files.pythonhosted.org/packages/90/9b/9728fe9a3e1b8521198455d027b0b4035522be18f504b24c5d38d59e7278/aiohttp-3.11.12-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:930ffa1925393381e1e0a9b82137fa7b34c92a019b521cf9f41263976666a0d6", size = 1785587 },
{ url = "https://files.pythonhosted.org/packages/c4/11/f478e071815a46ca0a5ae974651ff0c7a35898c55063305a896e58aa1247/aiohttp-3.11.11-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:249cc6912405917344192b9f9ea5cd5b139d49e0d2f5c7f70bdfaf6b4dbf3a2e", size = 1675145 }, { url = "https://files.pythonhosted.org/packages/ce/cf/28fbb43d4ebc1b4458374a3c7b6db3b556a90e358e9bbcfe6d9339c1e2b6/aiohttp-3.11.12-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8340def6737118f5429a5df4e88f440746b791f8f1c4ce4ad8a595f42c980bd5", size = 1675319 },
{ url = "https://files.pythonhosted.org/packages/26/5d/284d182fecbb5075ae10153ff7374f57314c93a8681666600e3a9e09c505/aiohttp-3.11.11-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0eb98d90b6690827dcc84c246811feeb4e1eea683c0eac6caed7549be9c84665", size = 1619804 }, { url = "https://files.pythonhosted.org/packages/e5/d2/006c459c11218cabaa7bca401f965c9cc828efbdea7e1615d4644eaf23f7/aiohttp-3.11.12-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4016e383f91f2814e48ed61e6bda7d24c4d7f2402c75dd28f7e1027ae44ea204", size = 1619982 },
{ url = "https://files.pythonhosted.org/packages/1b/78/980064c2ad685c64ce0e8aeeb7ef1e53f43c5b005edcd7d32e60809c4992/aiohttp-3.11.11-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:ec82bf1fda6cecce7f7b915f9196601a1bd1a3079796b76d16ae4cce6d0ef89b", size = 1654007 }, { url = "https://files.pythonhosted.org/packages/9d/83/ca425891ebd37bee5d837110f7fddc4d808a7c6c126a7d1b5c3ad72fc6ba/aiohttp-3.11.12-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:3c0600bcc1adfaaac321422d615939ef300df81e165f6522ad096b73439c0f58", size = 1654176 },
{ url = "https://files.pythonhosted.org/packages/21/8d/9e658d63b1438ad42b96f94da227f2e2c1d5c6001c9e8ffcc0bfb22e9105/aiohttp-3.11.11-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:9fd46ce0845cfe28f108888b3ab17abff84ff695e01e73657eec3f96d72eef34", size = 1650022 }, { url = "https://files.pythonhosted.org/packages/25/df/047b1ce88514a1b4915d252513640184b63624e7914e41d846668b8edbda/aiohttp-3.11.12-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:0450ada317a65383b7cce9576096150fdb97396dcfe559109b403c7242faffef", size = 1660198 },
{ url = "https://files.pythonhosted.org/packages/85/fd/a032bf7f2755c2df4f87f9effa34ccc1ef5cea465377dbaeef93bb56bbd6/aiohttp-3.11.11-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:bd176afcf8f5d2aed50c3647d4925d0db0579d96f75a31e77cbaf67d8a87742d", size = 1732899 }, { url = "https://files.pythonhosted.org/packages/d3/cc/6ecb8e343f0902528620b9dbd567028a936d5489bebd7dbb0dd0914f4fdb/aiohttp-3.11.12-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:850ff6155371fd802a280f8d369d4e15d69434651b844bde566ce97ee2277420", size = 1650186 },
{ url = "https://files.pythonhosted.org/packages/c5/0c/c2b85fde167dd440c7ba50af2aac20b5a5666392b174df54c00f888c5a75/aiohttp-3.11.11-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:ec2aa89305006fba9ffb98970db6c8221541be7bee4c1d027421d6f6df7d1ce2", size = 1755142 }, { url = "https://files.pythonhosted.org/packages/f8/f8/453df6dd69256ca8c06c53fc8803c9056e2b0b16509b070f9a3b4bdefd6c/aiohttp-3.11.12-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:8fd12d0f989c6099e7b0f30dc6e0d1e05499f3337461f0b2b0dadea6c64b89df", size = 1733063 },
{ url = "https://files.pythonhosted.org/packages/bc/78/91ae1a3b3b3bed8b893c5d69c07023e151b1c95d79544ad04cf68f596c2f/aiohttp-3.11.11-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:92cde43018a2e17d48bb09c79e4d4cb0e236de5063ce897a5e40ac7cb4878773", size = 1692736 }, { url = "https://files.pythonhosted.org/packages/55/f8/540160787ff3000391de0e5d0d1d33be4c7972f933c21991e2ea105b2d5e/aiohttp-3.11.12-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:76719dd521c20a58a6c256d058547b3a9595d1d885b830013366e27011ffe804", size = 1755306 },
{ url = "https://files.pythonhosted.org/packages/77/89/a7ef9c4b4cdb546fcc650ca7f7395aaffbd267f0e1f648a436bec33c9b95/aiohttp-3.11.11-cp311-cp311-win32.whl", hash = "sha256:aba807f9569455cba566882c8938f1a549f205ee43c27b126e5450dc9f83cc62", size = 416418 }, { url = "https://files.pythonhosted.org/packages/30/7d/49f3bfdfefd741576157f8f91caa9ff61a6f3d620ca6339268327518221b/aiohttp-3.11.12-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:97fe431f2ed646a3b56142fc81d238abcbaff08548d6912acb0b19a0cadc146b", size = 1692909 },
{ url = "https://files.pythonhosted.org/packages/fc/db/2192489a8a51b52e06627506f8ac8df69ee221de88ab9bdea77aa793aa6a/aiohttp-3.11.11-cp311-cp311-win_amd64.whl", hash = "sha256:ae545f31489548c87b0cced5755cfe5a5308d00407000e72c4fa30b19c3220ac", size = 442509 }, { url = "https://files.pythonhosted.org/packages/40/9c/8ce00afd6f6112ce9a2309dc490fea376ae824708b94b7b5ea9cba979d1d/aiohttp-3.11.12-cp311-cp311-win32.whl", hash = "sha256:e10c440d142fa8b32cfdb194caf60ceeceb3e49807072e0dc3a8887ea80e8c16", size = 416584 },
{ url = "https://files.pythonhosted.org/packages/69/cf/4bda538c502f9738d6b95ada11603c05ec260807246e15e869fc3ec5de97/aiohttp-3.11.11-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:e595c591a48bbc295ebf47cb91aebf9bd32f3ff76749ecf282ea7f9f6bb73886", size = 704666 }, { url = "https://files.pythonhosted.org/packages/35/97/4d3c5f562f15830de472eb10a7a222655d750839943e0e6d915ef7e26114/aiohttp-3.11.12-cp311-cp311-win_amd64.whl", hash = "sha256:246067ba0cf5560cf42e775069c5d80a8989d14a7ded21af529a4e10e3e0f0e6", size = 442674 },
{ url = "https://files.pythonhosted.org/packages/46/7b/87fcef2cad2fad420ca77bef981e815df6904047d0a1bd6aeded1b0d1d66/aiohttp-3.11.11-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:3ea1b59dc06396b0b424740a10a0a63974c725b1c64736ff788a3689d36c02d2", size = 464057 }, { url = "https://files.pythonhosted.org/packages/4d/d0/94346961acb476569fca9a644cc6f9a02f97ef75961a6b8d2b35279b8d1f/aiohttp-3.11.12-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:e392804a38353900c3fd8b7cacbea5132888f7129f8e241915e90b85f00e3250", size = 704837 },
{ url = "https://files.pythonhosted.org/packages/5a/a6/789e1f17a1b6f4a38939fbc39d29e1d960d5f89f73d0629a939410171bc0/aiohttp-3.11.11-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8811f3f098a78ffa16e0ea36dffd577eb031aea797cbdba81be039a4169e242c", size = 455996 }, { url = "https://files.pythonhosted.org/packages/a9/af/05c503f1cc8f97621f199ef4b8db65fb88b8bc74a26ab2adb74789507ad3/aiohttp-3.11.12-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:8fa1510b96c08aaad49303ab11f8803787c99222288f310a62f493faf883ede1", size = 464218 },
{ url = "https://files.pythonhosted.org/packages/b7/dd/485061fbfef33165ce7320db36e530cd7116ee1098e9c3774d15a732b3fd/aiohttp-3.11.11-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bd7227b87a355ce1f4bf83bfae4399b1f5bb42e0259cb9405824bd03d2f4336a", size = 1682367 }, { url = "https://files.pythonhosted.org/packages/f2/48/b9949eb645b9bd699153a2ec48751b985e352ab3fed9d98c8115de305508/aiohttp-3.11.12-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:dc065a4285307607df3f3686363e7f8bdd0d8ab35f12226362a847731516e42c", size = 456166 },
{ url = "https://files.pythonhosted.org/packages/e9/d7/9ec5b3ea9ae215c311d88b2093e8da17e67b8856673e4166c994e117ee3e/aiohttp-3.11.11-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d40f9da8cabbf295d3a9dae1295c69975b86d941bc20f0a087f0477fa0a66231", size = 1736989 }, { url = "https://files.pythonhosted.org/packages/14/fb/980981807baecb6f54bdd38beb1bd271d9a3a786e19a978871584d026dcf/aiohttp-3.11.12-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cddb31f8474695cd61fc9455c644fc1606c164b93bff2490390d90464b4655df", size = 1682528 },
{ url = "https://files.pythonhosted.org/packages/d6/fb/ea94927f7bfe1d86178c9d3e0a8c54f651a0a655214cce930b3c679b8f64/aiohttp-3.11.11-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ffb3dc385f6bb1568aa974fe65da84723210e5d9707e360e9ecb51f59406cd2e", size = 1793265 }, { url = "https://files.pythonhosted.org/packages/90/cb/77b1445e0a716914e6197b0698b7a3640590da6c692437920c586764d05b/aiohttp-3.11.12-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9dec0000d2d8621d8015c293e24589d46fa218637d820894cb7356c77eca3259", size = 1737154 },
{ url = "https://files.pythonhosted.org/packages/40/7f/6de218084f9b653026bd7063cd8045123a7ba90c25176465f266976d8c82/aiohttp-3.11.11-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a8f5f7515f3552d899c61202d99dcb17d6e3b0de777900405611cd747cecd1b8", size = 1691841 }, { url = "https://files.pythonhosted.org/packages/ff/24/d6fb1f4cede9ccbe98e4def6f3ed1e1efcb658871bbf29f4863ec646bf38/aiohttp-3.11.12-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e3552fe98e90fdf5918c04769f338a87fa4f00f3b28830ea9b78b1bdc6140e0d", size = 1793435 },
{ url = "https://files.pythonhosted.org/packages/77/e2/992f43d87831cbddb6b09c57ab55499332f60ad6fdbf438ff4419c2925fc/aiohttp-3.11.11-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3499c7ffbfd9c6a3d8d6a2b01c26639da7e43d47c7b4f788016226b1e711caa8", size = 1619317 }, { url = "https://files.pythonhosted.org/packages/17/e2/9f744cee0861af673dc271a3351f59ebd5415928e20080ab85be25641471/aiohttp-3.11.12-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6dfe7f984f28a8ae94ff3a7953cd9678550dbd2a1f9bda5dd9c5ae627744c78e", size = 1692010 },
{ url = "https://files.pythonhosted.org/packages/96/74/879b23cdd816db4133325a201287c95bef4ce669acde37f8f1b8669e1755/aiohttp-3.11.11-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8e2bf8029dbf0810c7bfbc3e594b51c4cc9101fbffb583a3923aea184724203c", size = 1641416 }, { url = "https://files.pythonhosted.org/packages/90/c4/4a1235c1df544223eb57ba553ce03bc706bdd065e53918767f7fa1ff99e0/aiohttp-3.11.12-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a481a574af914b6e84624412666cbfbe531a05667ca197804ecc19c97b8ab1b0", size = 1619481 },
{ url = "https://files.pythonhosted.org/packages/30/98/b123f6b15d87c54e58fd7ae3558ff594f898d7f30a90899718f3215ad328/aiohttp-3.11.11-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:b6212a60e5c482ef90f2d788835387070a88d52cf6241d3916733c9176d39eab", size = 1646514 }, { url = "https://files.pythonhosted.org/packages/60/70/cf12d402a94a33abda86dd136eb749b14c8eb9fec1e16adc310e25b20033/aiohttp-3.11.12-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1987770fb4887560363b0e1a9b75aa303e447433c41284d3af2840a2f226d6e0", size = 1641578 },
{ url = "https://files.pythonhosted.org/packages/d7/38/257fda3dc99d6978ab943141d5165ec74fd4b4164baa15e9c66fa21da86b/aiohttp-3.11.11-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:d119fafe7b634dbfa25a8c597718e69a930e4847f0b88e172744be24515140da", size = 1702095 }, { url = "https://files.pythonhosted.org/packages/1b/25/7211973fda1f5e833fcfd98ccb7f9ce4fbfc0074e3e70c0157a751d00db8/aiohttp-3.11.12-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:a4ac6a0f0f6402854adca4e3259a623f5c82ec3f0c049374133bcb243132baf9", size = 1684463 },
{ url = "https://files.pythonhosted.org/packages/0c/f4/ddab089053f9fb96654df5505c0a69bde093214b3c3454f6bfdb1845f558/aiohttp-3.11.11-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:6fba278063559acc730abf49845d0e9a9e1ba74f85f0ee6efd5803f08b285853", size = 1734611 }, { url = "https://files.pythonhosted.org/packages/93/60/b5905b4d0693f6018b26afa9f2221fefc0dcbd3773fe2dff1a20fb5727f1/aiohttp-3.11.12-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:c96a43822f1f9f69cc5c3706af33239489a6294be486a0447fb71380070d4d5f", size = 1646691 },
{ url = "https://files.pythonhosted.org/packages/c3/d6/f30b2bc520c38c8aa4657ed953186e535ae84abe55c08d0f70acd72ff577/aiohttp-3.11.11-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:92fc484e34b733704ad77210c7957679c5c3877bd1e6b6d74b185e9320cc716e", size = 1694576 }, { url = "https://files.pythonhosted.org/packages/b4/fc/ba1b14d6fdcd38df0b7c04640794b3683e949ea10937c8a58c14d697e93f/aiohttp-3.11.12-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:a5e69046f83c0d3cb8f0d5bd9b8838271b1bc898e01562a04398e160953e8eb9", size = 1702269 },
{ url = "https://files.pythonhosted.org/packages/bc/97/b0a88c3f4c6d0020b34045ee6d954058abc870814f6e310c4c9b74254116/aiohttp-3.11.11-cp312-cp312-win32.whl", hash = "sha256:9f5b3c1ed63c8fa937a920b6c1bec78b74ee09593b3f5b979ab2ae5ef60d7600", size = 411363 }, { url = "https://files.pythonhosted.org/packages/5e/39/18c13c6f658b2ba9cc1e0c6fb2d02f98fd653ad2addcdf938193d51a9c53/aiohttp-3.11.12-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:68d54234c8d76d8ef74744f9f9fc6324f1508129e23da8883771cdbb5818cbef", size = 1734782 },
{ url = "https://files.pythonhosted.org/packages/7f/23/cc36d9c398980acaeeb443100f0216f50a7cfe20c67a9fd0a2f1a5a846de/aiohttp-3.11.11-cp312-cp312-win_amd64.whl", hash = "sha256:1e69966ea6ef0c14ee53ef7a3d68b564cc408121ea56c0caa2dc918c1b2f553d", size = 437666 }, { url = "https://files.pythonhosted.org/packages/9f/d2/ccc190023020e342419b265861877cd8ffb75bec37b7ddd8521dd2c6deb8/aiohttp-3.11.12-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c9fd9dcf9c91affe71654ef77426f5cf8489305e1c66ed4816f5a21874b094b9", size = 1694740 },
{ url = "https://files.pythonhosted.org/packages/49/d1/d8af164f400bad432b63e1ac857d74a09311a8334b0481f2f64b158b50eb/aiohttp-3.11.11-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:541d823548ab69d13d23730a06f97460f4238ad2e5ed966aaf850d7c369782d9", size = 697982 }, { url = "https://files.pythonhosted.org/packages/3f/54/186805bcada64ea90ea909311ffedcd74369bfc6e880d39d2473314daa36/aiohttp-3.11.12-cp312-cp312-win32.whl", hash = "sha256:0ed49efcd0dc1611378beadbd97beb5d9ca8fe48579fc04a6ed0844072261b6a", size = 411530 },
{ url = "https://files.pythonhosted.org/packages/92/d1/faad3bf9fa4bfd26b95c69fc2e98937d52b1ff44f7e28131855a98d23a17/aiohttp-3.11.11-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:929f3ed33743a49ab127c58c3e0a827de0664bfcda566108989a14068f820194", size = 460662 }, { url = "https://files.pythonhosted.org/packages/3d/63/5eca549d34d141bcd9de50d4e59b913f3641559460c739d5e215693cb54a/aiohttp-3.11.12-cp312-cp312-win_amd64.whl", hash = "sha256:54775858c7f2f214476773ce785a19ee81d1294a6bedc5cc17225355aab74802", size = 437860 },
{ url = "https://files.pythonhosted.org/packages/db/61/0d71cc66d63909dabc4590f74eba71f91873a77ea52424401c2498d47536/aiohttp-3.11.11-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0882c2820fd0132240edbb4a51eb8ceb6eef8181db9ad5291ab3332e0d71df5f", size = 452950 }, { url = "https://files.pythonhosted.org/packages/c3/9b/cea185d4b543ae08ee478373e16653722c19fcda10d2d0646f300ce10791/aiohttp-3.11.12-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:413ad794dccb19453e2b97c2375f2ca3cdf34dc50d18cc2693bd5aed7d16f4b9", size = 698148 },
{ url = "https://files.pythonhosted.org/packages/07/db/6d04bc7fd92784900704e16b745484ef45b77bd04e25f58f6febaadf7983/aiohttp-3.11.11-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b63de12e44935d5aca7ed7ed98a255a11e5cb47f83a9fded7a5e41c40277d104", size = 1665178 }, { url = "https://files.pythonhosted.org/packages/91/5c/80d47fe7749fde584d1404a68ade29bcd7e58db8fa11fa38e8d90d77e447/aiohttp-3.11.12-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:4a93d28ed4b4b39e6f46fd240896c29b686b75e39cc6992692e3922ff6982b4c", size = 460831 },
{ url = "https://files.pythonhosted.org/packages/54/5c/e95ade9ae29f375411884d9fd98e50535bf9fe316c9feb0f30cd2ac8f508/aiohttp-3.11.11-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aa54f8ef31d23c506910c21163f22b124facb573bff73930735cf9fe38bf7dff", size = 1717939 }, { url = "https://files.pythonhosted.org/packages/8e/f9/de568f8a8ca6b061d157c50272620c53168d6e3eeddae78dbb0f7db981eb/aiohttp-3.11.12-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:d589264dbba3b16e8951b6f145d1e6b883094075283dafcab4cdd564a9e353a0", size = 453122 },
{ url = "https://files.pythonhosted.org/packages/6f/1c/1e7d5c5daea9e409ed70f7986001b8c9e3a49a50b28404498d30860edab6/aiohttp-3.11.11-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a344d5dc18074e3872777b62f5f7d584ae4344cd6006c17ba12103759d407af3", size = 1775125 }, { url = "https://files.pythonhosted.org/packages/8b/fd/b775970a047543bbc1d0f66725ba72acef788028fce215dc959fd15a8200/aiohttp-3.11.12-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e5148ca8955affdfeb864aca158ecae11030e952b25b3ae15d4e2b5ba299bad2", size = 1665336 },
{ url = "https://files.pythonhosted.org/packages/5d/66/890987e44f7d2f33a130e37e01a164168e6aff06fce15217b6eaf14df4f6/aiohttp-3.11.11-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b7fb429ab1aafa1f48578eb315ca45bd46e9c37de11fe45c7f5f4138091e2f1", size = 1677176 }, { url = "https://files.pythonhosted.org/packages/82/9b/aff01d4f9716245a1b2965f02044e4474fadd2bcfe63cf249ca788541886/aiohttp-3.11.12-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:525410e0790aab036492eeea913858989c4cb070ff373ec3bc322d700bdf47c1", size = 1718111 },
{ url = "https://files.pythonhosted.org/packages/8f/dc/e2ba57d7a52df6cdf1072fd5fa9c6301a68e1cd67415f189805d3eeb031d/aiohttp-3.11.11-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c341c7d868750e31961d6d8e60ff040fb9d3d3a46d77fd85e1ab8e76c3e9a5c4", size = 1603192 }, { url = "https://files.pythonhosted.org/packages/e0/a9/166fd2d8b2cc64f08104aa614fad30eee506b563154081bf88ce729bc665/aiohttp-3.11.12-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9bd8695be2c80b665ae3f05cb584093a1e59c35ecb7d794d1edd96e8cc9201d7", size = 1775293 },
{ url = "https://files.pythonhosted.org/packages/6c/9e/8d08a57de79ca3a358da449405555e668f2c8871a7777ecd2f0e3912c272/aiohttp-3.11.11-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ed9ee95614a71e87f1a70bc81603f6c6760128b140bc4030abe6abaa988f1c3d", size = 1618296 }, { url = "https://files.pythonhosted.org/packages/13/c5/0d3c89bd9e36288f10dc246f42518ce8e1c333f27636ac78df091c86bb4a/aiohttp-3.11.12-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f0203433121484b32646a5f5ea93ae86f3d9559d7243f07e8c0eab5ff8e3f70e", size = 1677338 },
{ url = "https://files.pythonhosted.org/packages/56/51/89822e3ec72db352c32e7fc1c690370e24e231837d9abd056490f3a49886/aiohttp-3.11.11-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:de8d38f1c2810fa2a4f1d995a2e9c70bb8737b18da04ac2afbf3971f65781d87", size = 1616524 }, { url = "https://files.pythonhosted.org/packages/72/b2/017db2833ef537be284f64ead78725984db8a39276c1a9a07c5c7526e238/aiohttp-3.11.12-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40cd36749a1035c34ba8d8aaf221b91ca3d111532e5ccb5fa8c3703ab1b967ed", size = 1603365 },
{ url = "https://files.pythonhosted.org/packages/2c/fa/e2e6d9398f462ffaa095e84717c1732916a57f1814502929ed67dd7568ef/aiohttp-3.11.11-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:a9b7371665d4f00deb8f32208c7c5e652059b0fda41cf6dbcac6114a041f1cc2", size = 1685471 }, { url = "https://files.pythonhosted.org/packages/fc/72/b66c96a106ec7e791e29988c222141dd1219d7793ffb01e72245399e08d2/aiohttp-3.11.12-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a7442662afebbf7b4c6d28cb7aab9e9ce3a5df055fc4116cc7228192ad6cb484", size = 1618464 },
{ url = "https://files.pythonhosted.org/packages/ae/5f/6bb976e619ca28a052e2c0ca7b0251ccd893f93d7c24a96abea38e332bf6/aiohttp-3.11.11-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:620598717fce1b3bd14dd09947ea53e1ad510317c85dda2c9c65b622edc96b12", size = 1715312 }, { url = "https://files.pythonhosted.org/packages/3f/50/e68a40f267b46a603bab569d48d57f23508801614e05b3369898c5b2910a/aiohttp-3.11.12-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:8a2fb742ef378284a50766e985804bd6adb5adb5aa781100b09befdbfa757b65", size = 1657827 },
{ url = "https://files.pythonhosted.org/packages/79/c1/756a7e65aa087c7fac724d6c4c038f2faaa2a42fe56dbc1dd62a33ca7213/aiohttp-3.11.11-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:bf8d9bfee991d8acc72d060d53860f356e07a50f0e0d09a8dfedea1c554dd0d5", size = 1672783 }, { url = "https://files.pythonhosted.org/packages/c5/1d/aafbcdb1773d0ba7c20793ebeedfaba1f3f7462f6fc251f24983ed738aa7/aiohttp-3.11.12-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:2cee3b117a8d13ab98b38d5b6bdcd040cfb4181068d05ce0c474ec9db5f3c5bb", size = 1616700 },
{ url = "https://files.pythonhosted.org/packages/73/ba/a6190ebb02176c7f75e6308da31f5d49f6477b651a3dcfaaaca865a298e2/aiohttp-3.11.11-cp313-cp313-win32.whl", hash = "sha256:9d73ee3725b7a737ad86c2eac5c57a4a97793d9f442599bea5ec67ac9f4bdc3d", size = 410229 }, { url = "https://files.pythonhosted.org/packages/b0/5e/6cd9724a2932f36e2a6b742436a36d64784322cfb3406ca773f903bb9a70/aiohttp-3.11.12-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:f6a19bcab7fbd8f8649d6595624856635159a6527861b9cdc3447af288a00c00", size = 1685643 },
{ url = "https://files.pythonhosted.org/packages/b8/62/c9fa5bafe03186a0e4699150a7fed9b1e73240996d0d2f0e5f70f3fdf471/aiohttp-3.11.11-cp313-cp313-win_amd64.whl", hash = "sha256:c7a06301c2fb096bdb0bd25fe2011531c1453b9f2c163c8031600ec73af1cc99", size = 436081 }, { url = "https://files.pythonhosted.org/packages/8b/38/ea6c91d5c767fd45a18151675a07c710ca018b30aa876a9f35b32fa59761/aiohttp-3.11.12-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:e4cecdb52aaa9994fbed6b81d4568427b6002f0a91c322697a4bfcc2b2363f5a", size = 1715487 },
{ url = "https://files.pythonhosted.org/packages/8e/24/e9edbcb7d1d93c02e055490348df6f955d675e85a028c33babdcaeda0853/aiohttp-3.11.12-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:30f546358dfa0953db92ba620101fefc81574f87b2346556b90b5f3ef16e55ce", size = 1672948 },
{ url = "https://files.pythonhosted.org/packages/25/be/0b1fb737268e003198f25c3a68c2135e76e4754bf399a879b27bd508a003/aiohttp-3.11.12-cp313-cp313-win32.whl", hash = "sha256:ce1bb21fc7d753b5f8a5d5a4bae99566386b15e716ebdb410154c16c91494d7f", size = 410396 },
{ url = "https://files.pythonhosted.org/packages/68/fd/677def96a75057b0a26446b62f8fbb084435b20a7d270c99539c26573bfd/aiohttp-3.11.12-cp313-cp313-win_amd64.whl", hash = "sha256:f7914ab70d2ee8ab91c13e5402122edbc77821c66d2758abb53aabe87f013287", size = 436234 },
] ]
[[package]] [[package]]
@ -132,29 +135,29 @@ wheels = [
[[package]] [[package]]
name = "attrs" name = "attrs"
version = "24.3.0" version = "25.1.0"
source = { registry = "https://pypi.org/simple" } source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/48/c8/6260f8ccc11f0917360fc0da435c5c9c7504e3db174d5a12a1494887b045/attrs-24.3.0.tar.gz", hash = "sha256:8f5c07333d543103541ba7be0e2ce16eeee8130cb0b3f9238ab904ce1e85baff", size = 805984 } sdist = { url = "https://files.pythonhosted.org/packages/49/7c/fdf464bcc51d23881d110abd74b512a42b3d5d376a55a831b44c603ae17f/attrs-25.1.0.tar.gz", hash = "sha256:1c97078a80c814273a76b2a298a932eb681c87415c11dee0a6921de7f1b02c3e", size = 810562 }
wheels = [ wheels = [
{ url = "https://files.pythonhosted.org/packages/89/aa/ab0f7891a01eeb2d2e338ae8fecbe57fcebea1a24dbb64d45801bfab481d/attrs-24.3.0-py3-none-any.whl", hash = "sha256:ac96cd038792094f438ad1f6ff80837353805ac950cd2aa0e0625ef19850c308", size = 63397 }, { url = "https://files.pythonhosted.org/packages/fc/30/d4986a882011f9df997a55e6becd864812ccfcd821d64aac8570ee39f719/attrs-25.1.0-py3-none-any.whl", hash = "sha256:c75a69e28a550a7e93789579c22aa26b0f5b83b75dc4e08fe092980051e1090a", size = 63152 },
] ]
[[package]] [[package]]
name = "babel" name = "babel"
version = "2.16.0" version = "2.17.0"
source = { registry = "https://pypi.org/simple" } source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/2a/74/f1bc80f23eeba13393b7222b11d95ca3af2c1e28edca18af487137eefed9/babel-2.16.0.tar.gz", hash = "sha256:d1f3554ca26605fe173f3de0c65f750f5a42f924499bf134de6423582298e316", size = 9348104 } sdist = { url = "https://files.pythonhosted.org/packages/7d/6b/d52e42361e1aa00709585ecc30b3f9684b3ab62530771402248b1b1d6240/babel-2.17.0.tar.gz", hash = "sha256:0c54cffb19f690cdcc52a3b50bcbf71e07a808d1c80d549f2459b9d2cf0afb9d", size = 9951852 }
wheels = [ wheels = [
{ url = "https://files.pythonhosted.org/packages/ed/20/bc79bc575ba2e2a7f70e8a1155618bb1301eaa5132a8271373a6903f73f8/babel-2.16.0-py3-none-any.whl", hash = "sha256:368b5b98b37c06b7daf6696391c3240c938b37767d4584413e8438c5c435fa8b", size = 9587599 }, { url = "https://files.pythonhosted.org/packages/b7/b8/3fe70c75fe32afc4bb507f75563d39bc5642255d1d94f1f23604725780bf/babel-2.17.0-py3-none-any.whl", hash = "sha256:4d0b53093fdfb4b21c92b5213dba5a1b23885afa8383709427046b21c366e5f2", size = 10182537 },
] ]
[[package]] [[package]]
name = "certifi" name = "certifi"
version = "2024.12.14" version = "2025.1.31"
source = { registry = "https://pypi.org/simple" } source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/0f/bd/1d41ee578ce09523c81a15426705dd20969f5abf006d1afe8aeff0dd776a/certifi-2024.12.14.tar.gz", hash = "sha256:b650d30f370c2b724812bee08008be0c4163b163ddaec3f2546c1caf65f191db", size = 166010 } sdist = { url = "https://files.pythonhosted.org/packages/1c/ab/c9f1e32b7b1bf505bf26f0ef697775960db7932abeb7b516de930ba2705f/certifi-2025.1.31.tar.gz", hash = "sha256:3d5da6925056f6f18f119200434a4780a94263f10d1c21d032a6f6b2baa20651", size = 167577 }
wheels = [ wheels = [
{ url = "https://files.pythonhosted.org/packages/a5/32/8f6669fc4798494966bf446c8c4a162e0b5d893dff088afddf76414f70e1/certifi-2024.12.14-py3-none-any.whl", hash = "sha256:1275f7a45be9464efc1173084eaa30f866fe2e47d389406136d332ed4967ec56", size = 164927 }, { url = "https://files.pythonhosted.org/packages/38/fc/bce832fd4fd99766c04d1ee0eead6b0ec6486fb100ae5e74c1d91292b982/certifi-2025.1.31-py3-none-any.whl", hash = "sha256:ca78db4565a652026a4db2bcdf68f2fb589ea80d0be70e03929ed730746b84fe", size = 166393 },
] ]
[[package]] [[package]]
@ -283,50 +286,51 @@ wheels = [
[[package]] [[package]]
name = "coverage" name = "coverage"
version = "7.6.10" version = "7.6.12"
source = { registry = "https://pypi.org/simple" } source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/84/ba/ac14d281f80aab516275012e8875991bb06203957aa1e19950139238d658/coverage-7.6.10.tar.gz", hash = "sha256:7fb105327c8f8f0682e29843e2ff96af9dcbe5bab8eeb4b398c6a33a16d80a23", size = 803868 } sdist = { url = "https://files.pythonhosted.org/packages/0c/d6/2b53ab3ee99f2262e6f0b8369a43f6d66658eab45510331c0b3d5c8c4272/coverage-7.6.12.tar.gz", hash = "sha256:48cfc4641d95d34766ad41d9573cc0f22a48aa88d22657a1fe01dca0dbae4de2", size = 805941 }
wheels = [ wheels = [
{ url = "https://files.pythonhosted.org/packages/85/d2/5e175fcf6766cf7501a8541d81778fd2f52f4870100e791f5327fd23270b/coverage-7.6.10-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ea3c8f04b3e4af80e17bab607c386a830ffc2fb88a5484e1df756478cf70d1d3", size = 208088 }, { url = "https://files.pythonhosted.org/packages/64/2d/da78abbfff98468c91fd63a73cccdfa0e99051676ded8dd36123e3a2d4d5/coverage-7.6.12-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:e18aafdfb3e9ec0d261c942d35bd7c28d031c5855dadb491d2723ba54f4c3015", size = 208464 },
{ url = "https://files.pythonhosted.org/packages/4b/6f/06db4dc8fca33c13b673986e20e466fd936235a6ec1f0045c3853ac1b593/coverage-7.6.10-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:507a20fc863cae1d5720797761b42d2d87a04b3e5aeb682ef3b7332e90598f43", size = 208536 }, { url = "https://files.pythonhosted.org/packages/31/f2/c269f46c470bdabe83a69e860c80a82e5e76840e9f4bbd7f38f8cebbee2f/coverage-7.6.12-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:66fe626fd7aa5982cdebad23e49e78ef7dbb3e3c2a5960a2b53632f1f703ea45", size = 208893 },
{ url = "https://files.pythonhosted.org/packages/0d/62/c6a0cf80318c1c1af376d52df444da3608eafc913b82c84a4600d8349472/coverage-7.6.10-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d37a84878285b903c0fe21ac8794c6dab58150e9359f1aaebbeddd6412d53132", size = 240474 }, { url = "https://files.pythonhosted.org/packages/47/63/5682bf14d2ce20819998a49c0deadb81e608a59eed64d6bc2191bc8046b9/coverage-7.6.12-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ef01d70198431719af0b1f5dcbefc557d44a190e749004042927b2a3fed0702", size = 241545 },
{ url = "https://files.pythonhosted.org/packages/a3/59/750adafc2e57786d2e8739a46b680d4fb0fbc2d57fbcb161290a9f1ecf23/coverage-7.6.10-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a534738b47b0de1995f85f582d983d94031dffb48ab86c95bdf88dc62212142f", size = 237880 }, { url = "https://files.pythonhosted.org/packages/6a/b6/6b6631f1172d437e11067e1c2edfdb7238b65dff965a12bce3b6d1bf2be2/coverage-7.6.12-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:07e92ae5a289a4bc4c0aae710c0948d3c7892e20fd3588224ebe242039573bf0", size = 239230 },
{ url = "https://files.pythonhosted.org/packages/2c/f8/ef009b3b98e9f7033c19deb40d629354aab1d8b2d7f9cfec284dbedf5096/coverage-7.6.10-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0d7a2bf79378d8fb8afaa994f91bfd8215134f8631d27eba3e0e2c13546ce994", size = 239750 }, { url = "https://files.pythonhosted.org/packages/c7/01/9cd06cbb1be53e837e16f1b4309f6357e2dfcbdab0dd7cd3b1a50589e4e1/coverage-7.6.12-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e695df2c58ce526eeab11a2e915448d3eb76f75dffe338ea613c1201b33bab2f", size = 241013 },
{ url = "https://files.pythonhosted.org/packages/a6/e2/6622f3b70f5f5b59f705e680dae6db64421af05a5d1e389afd24dae62e5b/coverage-7.6.10-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:6713ba4b4ebc330f3def51df1d5d38fad60b66720948112f114968feb52d3f99", size = 238642 }, { url = "https://files.pythonhosted.org/packages/4b/26/56afefc03c30871326e3d99709a70d327ac1f33da383cba108c79bd71563/coverage-7.6.12-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d74c08e9aaef995f8c4ef6d202dbd219c318450fe2a76da624f2ebb9c8ec5d9f", size = 239750 },
{ url = "https://files.pythonhosted.org/packages/2d/10/57ac3f191a3c95c67844099514ff44e6e19b2915cd1c22269fb27f9b17b6/coverage-7.6.10-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:ab32947f481f7e8c763fa2c92fd9f44eeb143e7610c4ca9ecd6a36adab4081bd", size = 237266 }, { url = "https://files.pythonhosted.org/packages/dd/ea/88a1ff951ed288f56aa561558ebe380107cf9132facd0b50bced63ba7238/coverage-7.6.12-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e995b3b76ccedc27fe4f477b349b7d64597e53a43fc2961db9d3fbace085d69d", size = 238462 },
{ url = "https://files.pythonhosted.org/packages/ee/2d/7016f4ad9d553cabcb7333ed78ff9d27248ec4eba8dd21fa488254dff894/coverage-7.6.10-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:7bbd8c8f1b115b892e34ba66a097b915d3871db7ce0e6b9901f462ff3a975377", size = 238045 }, { url = "https://files.pythonhosted.org/packages/6e/d4/1d9404566f553728889409eff82151d515fbb46dc92cbd13b5337fa0de8c/coverage-7.6.12-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b1f097878d74fe51e1ddd1be62d8e3682748875b461232cf4b52ddc6e6db0bba", size = 239307 },
{ url = "https://files.pythonhosted.org/packages/a7/fe/45af5c82389a71e0cae4546413266d2195c3744849669b0bab4b5f2c75da/coverage-7.6.10-cp311-cp311-win32.whl", hash = "sha256:299e91b274c5c9cdb64cbdf1b3e4a8fe538a7a86acdd08fae52301b28ba297f8", size = 210647 }, { url = "https://files.pythonhosted.org/packages/12/c1/e453d3b794cde1e232ee8ac1d194fde8e2ba329c18bbf1b93f6f5eef606b/coverage-7.6.12-cp311-cp311-win32.whl", hash = "sha256:1f7ffa05da41754e20512202c866d0ebfc440bba3b0ed15133070e20bf5aeb5f", size = 211117 },
{ url = "https://files.pythonhosted.org/packages/db/11/3f8e803a43b79bc534c6a506674da9d614e990e37118b4506faf70d46ed6/coverage-7.6.10-cp311-cp311-win_amd64.whl", hash = "sha256:489a01f94aa581dbd961f306e37d75d4ba16104bbfa2b0edb21d29b73be83609", size = 211508 }, { url = "https://files.pythonhosted.org/packages/d5/db/829185120c1686fa297294f8fcd23e0422f71070bf85ef1cc1a72ecb2930/coverage-7.6.12-cp311-cp311-win_amd64.whl", hash = "sha256:e216c5c45f89ef8971373fd1c5d8d1164b81f7f5f06bbf23c37e7908d19e8558", size = 212019 },
{ url = "https://files.pythonhosted.org/packages/86/77/19d09ea06f92fdf0487499283b1b7af06bc422ea94534c8fe3a4cd023641/coverage-7.6.10-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:27c6e64726b307782fa5cbe531e7647aee385a29b2107cd87ba7c0105a5d3853", size = 208281 }, { url = "https://files.pythonhosted.org/packages/e2/7f/4af2ed1d06ce6bee7eafc03b2ef748b14132b0bdae04388e451e4b2c529b/coverage-7.6.12-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b172f8e030e8ef247b3104902cc671e20df80163b60a203653150d2fc204d1ad", size = 208645 },
{ url = "https://files.pythonhosted.org/packages/b6/67/5479b9f2f99fcfb49c0d5cf61912a5255ef80b6e80a3cddba39c38146cf4/coverage-7.6.10-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c56e097019e72c373bae32d946ecf9858fda841e48d82df7e81c63ac25554078", size = 208514 }, { url = "https://files.pythonhosted.org/packages/dc/60/d19df912989117caa95123524d26fc973f56dc14aecdec5ccd7d0084e131/coverage-7.6.12-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:641dfe0ab73deb7069fb972d4d9725bf11c239c309ce694dd50b1473c0f641c3", size = 208898 },
{ url = "https://files.pythonhosted.org/packages/15/d1/febf59030ce1c83b7331c3546d7317e5120c5966471727aa7ac157729c4b/coverage-7.6.10-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c7827a5bc7bdb197b9e066cdf650b2887597ad124dd99777332776f7b7c7d0d0", size = 241537 }, { url = "https://files.pythonhosted.org/packages/bd/10/fecabcf438ba676f706bf90186ccf6ff9f6158cc494286965c76e58742fa/coverage-7.6.12-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0e549f54ac5f301e8e04c569dfdb907f7be71b06b88b5063ce9d6953d2d58574", size = 242987 },
{ url = "https://files.pythonhosted.org/packages/4b/7e/5ac4c90192130e7cf8b63153fe620c8bfd9068f89a6d9b5f26f1550f7a26/coverage-7.6.10-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:204a8238afe787323a8b47d8be4df89772d5c1e4651b9ffa808552bdf20e1d50", size = 238572 }, { url = "https://files.pythonhosted.org/packages/4c/53/4e208440389e8ea936f5f2b0762dcd4cb03281a7722def8e2bf9dc9c3d68/coverage-7.6.12-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:959244a17184515f8c52dcb65fb662808767c0bd233c1d8a166e7cf74c9ea985", size = 239881 },
{ url = "https://files.pythonhosted.org/packages/dc/03/0334a79b26ecf59958f2fe9dd1f5ab3e2f88db876f5071933de39af09647/coverage-7.6.10-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e67926f51821b8e9deb6426ff3164870976fe414d033ad90ea75e7ed0c2e5022", size = 240639 }, { url = "https://files.pythonhosted.org/packages/c4/47/2ba744af8d2f0caa1f17e7746147e34dfc5f811fb65fc153153722d58835/coverage-7.6.12-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bda1c5f347550c359f841d6614fb8ca42ae5cb0b74d39f8a1e204815ebe25750", size = 242142 },
{ url = "https://files.pythonhosted.org/packages/d7/45/8a707f23c202208d7b286d78ad6233f50dcf929319b664b6cc18a03c1aae/coverage-7.6.10-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e78b270eadb5702938c3dbe9367f878249b5ef9a2fcc5360ac7bff694310d17b", size = 240072 }, { url = "https://files.pythonhosted.org/packages/e9/90/df726af8ee74d92ee7e3bf113bf101ea4315d71508952bd21abc3fae471e/coverage-7.6.12-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1ceeb90c3eda1f2d8c4c578c14167dbd8c674ecd7d38e45647543f19839dd6ea", size = 241437 },
{ url = "https://files.pythonhosted.org/packages/66/02/603ce0ac2d02bc7b393279ef618940b4a0535b0868ee791140bda9ecfa40/coverage-7.6.10-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:714f942b9c15c3a7a5fe6876ce30af831c2ad4ce902410b7466b662358c852c0", size = 238386 }, { url = "https://files.pythonhosted.org/packages/f6/af/995263fd04ae5f9cf12521150295bf03b6ba940d0aea97953bb4a6db3e2b/coverage-7.6.12-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:0f16f44025c06792e0fb09571ae454bcc7a3ec75eeb3c36b025eccf501b1a4c3", size = 239724 },
{ url = "https://files.pythonhosted.org/packages/04/62/4e6887e9be060f5d18f1dd58c2838b2d9646faf353232dec4e2d4b1c8644/coverage-7.6.10-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:abb02e2f5a3187b2ac4cd46b8ced85a0858230b577ccb2c62c81482ca7d18852", size = 240054 }, { url = "https://files.pythonhosted.org/packages/1c/8e/5bb04f0318805e190984c6ce106b4c3968a9562a400180e549855d8211bd/coverage-7.6.12-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b076e625396e787448d27a411aefff867db2bffac8ed04e8f7056b07024eed5a", size = 241329 },
{ url = "https://files.pythonhosted.org/packages/5c/74/83ae4151c170d8bd071924f212add22a0e62a7fe2b149edf016aeecad17c/coverage-7.6.10-cp312-cp312-win32.whl", hash = "sha256:55b201b97286cf61f5e76063f9e2a1d8d2972fc2fcfd2c1272530172fd28c359", size = 210904 }, { url = "https://files.pythonhosted.org/packages/9e/9d/fa04d9e6c3f6459f4e0b231925277cfc33d72dfab7fa19c312c03e59da99/coverage-7.6.12-cp312-cp312-win32.whl", hash = "sha256:00b2086892cf06c7c2d74983c9595dc511acca00665480b3ddff749ec4fb2a95", size = 211289 },
{ url = "https://files.pythonhosted.org/packages/c3/54/de0893186a221478f5880283119fc40483bc460b27c4c71d1b8bba3474b9/coverage-7.6.10-cp312-cp312-win_amd64.whl", hash = "sha256:e4ae5ac5e0d1e4edfc9b4b57b4cbecd5bc266a6915c500f358817a8496739247", size = 211692 }, { url = "https://files.pythonhosted.org/packages/53/40/53c7ffe3c0c3fff4d708bc99e65f3d78c129110d6629736faf2dbd60ad57/coverage-7.6.12-cp312-cp312-win_amd64.whl", hash = "sha256:7ae6eabf519bc7871ce117fb18bf14e0e343eeb96c377667e3e5dd12095e0288", size = 212079 },
{ url = "https://files.pythonhosted.org/packages/25/6d/31883d78865529257bf847df5789e2ae80e99de8a460c3453dbfbe0db069/coverage-7.6.10-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:05fca8ba6a87aabdd2d30d0b6c838b50510b56cdcfc604d40760dae7153b73d9", size = 208308 }, { url = "https://files.pythonhosted.org/packages/76/89/1adf3e634753c0de3dad2f02aac1e73dba58bc5a3a914ac94a25b2ef418f/coverage-7.6.12-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:488c27b3db0ebee97a830e6b5a3ea930c4a6e2c07f27a5e67e1b3532e76b9ef1", size = 208673 },
{ url = "https://files.pythonhosted.org/packages/70/22/3f2b129cc08de00c83b0ad6252e034320946abfc3e4235c009e57cfeee05/coverage-7.6.10-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:9e80eba8801c386f72e0712a0453431259c45c3249f0009aff537a517b52942b", size = 208565 }, { url = "https://files.pythonhosted.org/packages/ce/64/92a4e239d64d798535c5b45baac6b891c205a8a2e7c9cc8590ad386693dc/coverage-7.6.12-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:5d1095bbee1851269f79fd8e0c9b5544e4c00c0c24965e66d8cba2eb5bb535fd", size = 208945 },
{ url = "https://files.pythonhosted.org/packages/97/0a/d89bc2d1cc61d3a8dfe9e9d75217b2be85f6c73ebf1b9e3c2f4e797f4531/coverage-7.6.10-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a372c89c939d57abe09e08c0578c1d212e7a678135d53aa16eec4430adc5e690", size = 241083 }, { url = "https://files.pythonhosted.org/packages/b4/d0/4596a3ef3bca20a94539c9b1e10fd250225d1dec57ea78b0867a1cf9742e/coverage-7.6.12-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0533adc29adf6a69c1baa88c3d7dbcaadcffa21afbed3ca7a225a440e4744bf9", size = 242484 },
{ url = "https://files.pythonhosted.org/packages/4c/81/6d64b88a00c7a7aaed3a657b8eaa0931f37a6395fcef61e53ff742b49c97/coverage-7.6.10-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ec22b5e7fe7a0fa8509181c4aac1db48f3dd4d3a566131b313d1efc102892c18", size = 238235 }, { url = "https://files.pythonhosted.org/packages/1c/ef/6fd0d344695af6718a38d0861408af48a709327335486a7ad7e85936dc6e/coverage-7.6.12-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:53c56358d470fa507a2b6e67a68fd002364d23c83741dbc4c2e0680d80ca227e", size = 239525 },
{ url = "https://files.pythonhosted.org/packages/9a/0b/7797d4193f5adb4b837207ed87fecf5fc38f7cc612b369a8e8e12d9fa114/coverage-7.6.10-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:26bcf5c4df41cad1b19c84af71c22cbc9ea9a547fc973f1f2cc9a290002c8b3c", size = 240220 }, { url = "https://files.pythonhosted.org/packages/0c/4b/373be2be7dd42f2bcd6964059fd8fa307d265a29d2b9bcf1d044bcc156ed/coverage-7.6.12-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:64cbb1a3027c79ca6310bf101014614f6e6e18c226474606cf725238cf5bc2d4", size = 241545 },
{ url = "https://files.pythonhosted.org/packages/65/4d/6f83ca1bddcf8e51bf8ff71572f39a1c73c34cf50e752a952c34f24d0a60/coverage-7.6.10-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4e4630c26b6084c9b3cb53b15bd488f30ceb50b73c35c5ad7871b869cb7365fd", size = 239847 }, { url = "https://files.pythonhosted.org/packages/a6/7d/0e83cc2673a7790650851ee92f72a343827ecaaea07960587c8f442b5cd3/coverage-7.6.12-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:79cac3390bfa9836bb795be377395f28410811c9066bc4eefd8015258a7578c6", size = 241179 },
{ url = "https://files.pythonhosted.org/packages/30/9d/2470df6aa146aff4c65fee0f87f58d2164a67533c771c9cc12ffcdb865d5/coverage-7.6.10-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:2396e8116db77789f819d2bc8a7e200232b7a282c66e0ae2d2cd84581a89757e", size = 237922 }, { url = "https://files.pythonhosted.org/packages/ff/8c/566ea92ce2bb7627b0900124e24a99f9244b6c8c92d09ff9f7633eb7c3c8/coverage-7.6.12-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:9b148068e881faa26d878ff63e79650e208e95cf1c22bd3f77c3ca7b1d9821a3", size = 239288 },
{ url = "https://files.pythonhosted.org/packages/08/dd/723fef5d901e6a89f2507094db66c091449c8ba03272861eaefa773ad95c/coverage-7.6.10-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:79109c70cc0882e4d2d002fe69a24aa504dec0cc17169b3c7f41a1d341a73694", size = 239783 }, { url = "https://files.pythonhosted.org/packages/7d/e4/869a138e50b622f796782d642c15fb5f25a5870c6d0059a663667a201638/coverage-7.6.12-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8bec2ac5da793c2685ce5319ca9bcf4eee683b8a1679051f8e6ec04c4f2fd7dc", size = 241032 },
{ url = "https://files.pythonhosted.org/packages/3d/f7/64d3298b2baf261cb35466000628706ce20a82d42faf9b771af447cd2b76/coverage-7.6.10-cp313-cp313-win32.whl", hash = "sha256:9e1747bab246d6ff2c4f28b4d186b205adced9f7bd9dc362051cc37c4a0c7bd6", size = 210965 }, { url = "https://files.pythonhosted.org/packages/ae/28/a52ff5d62a9f9e9fe9c4f17759b98632edd3a3489fce70154c7d66054dd3/coverage-7.6.12-cp313-cp313-win32.whl", hash = "sha256:200e10beb6ddd7c3ded322a4186313d5ca9e63e33d8fab4faa67ef46d3460af3", size = 211315 },
{ url = "https://files.pythonhosted.org/packages/d5/58/ec43499a7fc681212fe7742fe90b2bc361cdb72e3181ace1604247a5b24d/coverage-7.6.10-cp313-cp313-win_amd64.whl", hash = "sha256:254f1a3b1eef5f7ed23ef265eaa89c65c8c5b6b257327c149db1ca9d4a35f25e", size = 211719 }, { url = "https://files.pythonhosted.org/packages/bc/17/ab849b7429a639f9722fa5628364c28d675c7ff37ebc3268fe9840dda13c/coverage-7.6.12-cp313-cp313-win_amd64.whl", hash = "sha256:2b996819ced9f7dbb812c701485d58f261bef08f9b85304d41219b1496b591ef", size = 212099 },
{ url = "https://files.pythonhosted.org/packages/ab/c9/f2857a135bcff4330c1e90e7d03446b036b2363d4ad37eb5e3a47bbac8a6/coverage-7.6.10-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:2ccf240eb719789cedbb9fd1338055de2761088202a9a0b73032857e53f612fe", size = 209050 }, { url = "https://files.pythonhosted.org/packages/d2/1c/b9965bf23e171d98505eb5eb4fb4d05c44efd256f2e0f19ad1ba8c3f54b0/coverage-7.6.12-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:299cf973a7abff87a30609879c10df0b3bfc33d021e1adabc29138a48888841e", size = 209511 },
{ url = "https://files.pythonhosted.org/packages/aa/b3/f840e5bd777d8433caa9e4a1eb20503495709f697341ac1a8ee6a3c906ad/coverage-7.6.10-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:0c807ca74d5a5e64427c8805de15b9ca140bba13572d6d74e262f46f50b13273", size = 209321 }, { url = "https://files.pythonhosted.org/packages/57/b3/119c201d3b692d5e17784fee876a9a78e1b3051327de2709392962877ca8/coverage-7.6.12-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:4b467a8c56974bf06e543e69ad803c6865249d7a5ccf6980457ed2bc50312703", size = 209729 },
{ url = "https://files.pythonhosted.org/packages/85/7d/125a5362180fcc1c03d91850fc020f3831d5cda09319522bcfa6b2b70be7/coverage-7.6.10-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2bcfa46d7709b5a7ffe089075799b902020b62e7ee56ebaed2f4bdac04c508d8", size = 252039 }, { url = "https://files.pythonhosted.org/packages/52/4e/a7feb5a56b266304bc59f872ea07b728e14d5a64f1ad3a2cc01a3259c965/coverage-7.6.12-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2458f275944db8129f95d91aee32c828a408481ecde3b30af31d552c2ce284a0", size = 253988 },
{ url = "https://files.pythonhosted.org/packages/a9/9c/4358bf3c74baf1f9bddd2baf3756b54c07f2cfd2535f0a47f1e7757e54b3/coverage-7.6.10-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4e0de1e902669dccbf80b0415fb6b43d27edca2fbd48c74da378923b05316098", size = 247758 }, { url = "https://files.pythonhosted.org/packages/65/19/069fec4d6908d0dae98126aa7ad08ce5130a6decc8509da7740d36e8e8d2/coverage-7.6.12-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0a9d8be07fb0832636a0f72b80d2a652fe665e80e720301fb22b191c3434d924", size = 249697 },
{ url = "https://files.pythonhosted.org/packages/cf/c7/de3eb6fc5263b26fab5cda3de7a0f80e317597a4bad4781859f72885f300/coverage-7.6.10-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3f7b444c42bbc533aaae6b5a2166fd1a797cdb5eb58ee51a92bee1eb94a1e1cb", size = 250119 }, { url = "https://files.pythonhosted.org/packages/1c/da/5b19f09ba39df7c55f77820736bf17bbe2416bbf5216a3100ac019e15839/coverage-7.6.12-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:14d47376a4f445e9743f6c83291e60adb1b127607a3618e3185bbc8091f0467b", size = 252033 },
{ url = "https://files.pythonhosted.org/packages/3e/e6/43de91f8ba2ec9140c6a4af1102141712949903dc732cf739167cfa7a3bc/coverage-7.6.10-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:b330368cb99ef72fcd2dc3ed260adf67b31499584dc8a20225e85bfe6f6cfed0", size = 249597 }, { url = "https://files.pythonhosted.org/packages/1e/89/4c2750df7f80a7872267f7c5fe497c69d45f688f7b3afe1297e52e33f791/coverage-7.6.12-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:b95574d06aa9d2bd6e5cc35a5bbe35696342c96760b69dc4287dbd5abd4ad51d", size = 251535 },
{ url = "https://files.pythonhosted.org/packages/08/40/61158b5499aa2adf9e37bc6d0117e8f6788625b283d51e7e0c53cf340530/coverage-7.6.10-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:9a7cfb50515f87f7ed30bc882f68812fd98bc2852957df69f3003d22a2aa0abf", size = 247473 }, { url = "https://files.pythonhosted.org/packages/78/3b/6d3ae3c1cc05f1b0460c51e6f6dcf567598cbd7c6121e5ad06643974703c/coverage-7.6.12-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:ecea0c38c9079570163d663c0433a9af4094a60aafdca491c6a3d248c7432827", size = 249192 },
{ url = "https://files.pythonhosted.org/packages/50/69/b3f2416725621e9f112e74e8470793d5b5995f146f596f133678a633b77e/coverage-7.6.10-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:6f93531882a5f68c28090f901b1d135de61b56331bba82028489bc51bdd818d2", size = 248737 }, { url = "https://files.pythonhosted.org/packages/6e/8e/c14a79f535ce41af7d436bbad0d3d90c43d9e38ec409b4770c894031422e/coverage-7.6.12-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:2251fabcfee0a55a8578a9d29cecfee5f2de02f11530e7d5c5a05859aa85aee9", size = 250627 },
{ url = "https://files.pythonhosted.org/packages/3c/6e/fe899fb937657db6df31cc3e61c6968cb56d36d7326361847440a430152e/coverage-7.6.10-cp313-cp313t-win32.whl", hash = "sha256:89d76815a26197c858f53c7f6a656686ec392b25991f9e409bcef020cd532312", size = 211611 }, { url = "https://files.pythonhosted.org/packages/cb/79/b7cee656cfb17a7f2c1b9c3cee03dd5d8000ca299ad4038ba64b61a9b044/coverage-7.6.12-cp313-cp313t-win32.whl", hash = "sha256:eb5507795caabd9b2ae3f1adc95f67b1104971c22c624bb354232d65c4fc90b3", size = 212033 },
{ url = "https://files.pythonhosted.org/packages/1c/55/52f5e66142a9d7bc93a15192eba7a78513d2abf6b3558d77b4ca32f5f424/coverage-7.6.10-cp313-cp313t-win_amd64.whl", hash = "sha256:54a5f0f43950a36312155dae55c505a76cd7f2b12d26abeebbe7a0b36dbc868d", size = 212781 }, { url = "https://files.pythonhosted.org/packages/b6/c3/f7aaa3813f1fa9a4228175a7bd368199659d392897e184435a3b66408dd3/coverage-7.6.12-cp313-cp313t-win_amd64.whl", hash = "sha256:f60a297c3987c6c02ffb29effc70eadcbb412fe76947d394a1091a3615948e2f", size = 213240 },
{ url = "https://files.pythonhosted.org/packages/fb/b2/f655700e1024dec98b10ebaafd0cedbc25e40e4abe62a3c8e2ceef4f8f0a/coverage-7.6.12-py3-none-any.whl", hash = "sha256:eb8668cfbc279a536c633137deeb9435d2962caec279c3f8cf8b91fff6ff8953", size = 200552 },
] ]
[package.optional-dependencies] [package.optional-dependencies]
@ -336,33 +340,37 @@ toml = [
[[package]] [[package]]
name = "cryptography" name = "cryptography"
version = "44.0.0" version = "44.0.1"
source = { registry = "https://pypi.org/simple" } source = { registry = "https://pypi.org/simple" }
dependencies = [ dependencies = [
{ name = "cffi", marker = "platform_python_implementation != 'PyPy'" }, { name = "cffi", marker = "platform_python_implementation != 'PyPy'" },
] ]
sdist = { url = "https://files.pythonhosted.org/packages/91/4c/45dfa6829acffa344e3967d6006ee4ae8be57af746ae2eba1c431949b32c/cryptography-44.0.0.tar.gz", hash = "sha256:cd4e834f340b4293430701e772ec543b0fbe6c2dea510a5286fe0acabe153a02", size = 710657 } sdist = { url = "https://files.pythonhosted.org/packages/c7/67/545c79fe50f7af51dbad56d16b23fe33f63ee6a5d956b3cb68ea110cbe64/cryptography-44.0.1.tar.gz", hash = "sha256:f51f5705ab27898afda1aaa430f34ad90dc117421057782022edf0600bec5f14", size = 710819 }
wheels = [ wheels = [
{ url = "https://files.pythonhosted.org/packages/55/09/8cc67f9b84730ad330b3b72cf867150744bf07ff113cda21a15a1c6d2c7c/cryptography-44.0.0-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:84111ad4ff3f6253820e6d3e58be2cc2a00adb29335d4cacb5ab4d4d34f2a123", size = 6541833 }, { url = "https://files.pythonhosted.org/packages/72/27/5e3524053b4c8889da65cf7814a9d0d8514a05194a25e1e34f46852ee6eb/cryptography-44.0.1-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:bf688f615c29bfe9dfc44312ca470989279f0e94bb9f631f85e3459af8efc009", size = 6642022 },
{ url = "https://files.pythonhosted.org/packages/7e/5b/3759e30a103144e29632e7cb72aec28cedc79e514b2ea8896bb17163c19b/cryptography-44.0.0-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b15492a11f9e1b62ba9d73c210e2416724633167de94607ec6069ef724fad092", size = 3922710 }, { url = "https://files.pythonhosted.org/packages/34/b9/4d1fa8d73ae6ec350012f89c3abfbff19fc95fe5420cf972e12a8d182986/cryptography-44.0.1-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dd7c7e2d71d908dc0f8d2027e1604102140d84b155e658c20e8ad1304317691f", size = 3943865 },
{ url = "https://files.pythonhosted.org/packages/5f/58/3b14bf39f1a0cfd679e753e8647ada56cddbf5acebffe7db90e184c76168/cryptography-44.0.0-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:831c3c4d0774e488fdc83a1923b49b9957d33287de923d58ebd3cec47a0ae43f", size = 4137546 }, { url = "https://files.pythonhosted.org/packages/6e/57/371a9f3f3a4500807b5fcd29fec77f418ba27ffc629d88597d0d1049696e/cryptography-44.0.1-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:887143b9ff6bad2b7570da75a7fe8bbf5f65276365ac259a5d2d5147a73775f2", size = 4162562 },
{ url = "https://files.pythonhosted.org/packages/98/65/13d9e76ca19b0ba5603d71ac8424b5694415b348e719db277b5edc985ff5/cryptography-44.0.0-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:761817a3377ef15ac23cd7834715081791d4ec77f9297ee694ca1ee9c2c7e5eb", size = 3915420 }, { url = "https://files.pythonhosted.org/packages/c5/1d/5b77815e7d9cf1e3166988647f336f87d5634a5ccecec2ffbe08ef8dd481/cryptography-44.0.1-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:322eb03ecc62784536bc173f1483e76747aafeb69c8728df48537eb431cd1911", size = 3951923 },
{ url = "https://files.pythonhosted.org/packages/b1/07/40fe09ce96b91fc9276a9ad272832ead0fddedcba87f1190372af8e3039c/cryptography-44.0.0-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:3c672a53c0fb4725a29c303be906d3c1fa99c32f58abe008a82705f9ee96f40b", size = 4154498 }, { url = "https://files.pythonhosted.org/packages/28/01/604508cd34a4024467cd4105887cf27da128cba3edd435b54e2395064bfb/cryptography-44.0.1-cp37-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:21377472ca4ada2906bc313168c9dc7b1d7ca417b63c1c3011d0c74b7de9ae69", size = 3685194 },
{ url = "https://files.pythonhosted.org/packages/75/ea/af65619c800ec0a7e4034207aec543acdf248d9bffba0533342d1bd435e1/cryptography-44.0.0-cp37-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:4ac4c9f37eba52cb6fbeaf5b59c152ea976726b865bd4cf87883a7e7006cc543", size = 3932569 }, { url = "https://files.pythonhosted.org/packages/c6/3d/d3c55d4f1d24580a236a6753902ef6d8aafd04da942a1ee9efb9dc8fd0cb/cryptography-44.0.1-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:df978682c1504fc93b3209de21aeabf2375cb1571d4e61907b3e7a2540e83026", size = 4187790 },
{ url = "https://files.pythonhosted.org/packages/c7/af/d1deb0c04d59612e3d5e54203159e284d3e7a6921e565bb0eeb6269bdd8a/cryptography-44.0.0-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:ed3534eb1090483c96178fcb0f8893719d96d5274dfde98aa6add34614e97c8e", size = 4016721 }, { url = "https://files.pythonhosted.org/packages/ea/a6/44d63950c8588bfa8594fd234d3d46e93c3841b8e84a066649c566afb972/cryptography-44.0.1-cp37-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:eb3889330f2a4a148abead555399ec9a32b13b7c8ba969b72d8e500eb7ef84cd", size = 3951343 },
{ url = "https://files.pythonhosted.org/packages/bd/69/7ca326c55698d0688db867795134bdfac87136b80ef373aaa42b225d6dd5/cryptography-44.0.0-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:f3f6fdfa89ee2d9d496e2c087cebef9d4fcbb0ad63c40e821b39f74bf48d9c5e", size = 4240915 }, { url = "https://files.pythonhosted.org/packages/c1/17/f5282661b57301204cbf188254c1a0267dbd8b18f76337f0a7ce1038888c/cryptography-44.0.1-cp37-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:8e6a85a93d0642bd774460a86513c5d9d80b5c002ca9693e63f6e540f1815ed0", size = 4187127 },
{ url = "https://files.pythonhosted.org/packages/ef/d4/cae11bf68c0f981e0413906c6dd03ae7fa864347ed5fac40021df1ef467c/cryptography-44.0.0-cp37-abi3-win32.whl", hash = "sha256:eb33480f1bad5b78233b0ad3e1b0be21e8ef1da745d8d2aecbb20671658b9053", size = 2757925 }, { url = "https://files.pythonhosted.org/packages/f3/68/abbae29ed4f9d96596687f3ceea8e233f65c9645fbbec68adb7c756bb85a/cryptography-44.0.1-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:6f76fdd6fd048576a04c5210d53aa04ca34d2ed63336d4abd306d0cbe298fddf", size = 4070666 },
{ url = "https://files.pythonhosted.org/packages/64/b1/50d7739254d2002acae64eed4fc43b24ac0cc44bf0a0d388d1ca06ec5bb1/cryptography-44.0.0-cp37-abi3-win_amd64.whl", hash = "sha256:abc998e0c0eee3c8a1904221d3f67dcfa76422b23620173e28c11d3e626c21bd", size = 3202055 }, { url = "https://files.pythonhosted.org/packages/0f/10/cf91691064a9e0a88ae27e31779200b1505d3aee877dbe1e4e0d73b4f155/cryptography-44.0.1-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:6c8acf6f3d1f47acb2248ec3ea261171a671f3d9428e34ad0357148d492c7864", size = 4288811 },
{ url = "https://files.pythonhosted.org/packages/11/18/61e52a3d28fc1514a43b0ac291177acd1b4de00e9301aaf7ef867076ff8a/cryptography-44.0.0-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:660cb7312a08bc38be15b696462fa7cc7cd85c3ed9c576e81f4dc4d8b2b31591", size = 6542801 }, { url = "https://files.pythonhosted.org/packages/38/78/74ea9eb547d13c34e984e07ec8a473eb55b19c1451fe7fc8077c6a4b0548/cryptography-44.0.1-cp37-abi3-win32.whl", hash = "sha256:24979e9f2040c953a94bf3c6782e67795a4c260734e5264dceea65c8f4bae64a", size = 2771882 },
{ url = "https://files.pythonhosted.org/packages/1a/07/5f165b6c65696ef75601b781a280fc3b33f1e0cd6aa5a92d9fb96c410e97/cryptography-44.0.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1923cb251c04be85eec9fda837661c67c1049063305d6be5721643c22dd4e2b7", size = 3922613 }, { url = "https://files.pythonhosted.org/packages/cf/6c/3907271ee485679e15c9f5e93eac6aa318f859b0aed8d369afd636fafa87/cryptography-44.0.1-cp37-abi3-win_amd64.whl", hash = "sha256:fd0ee90072861e276b0ff08bd627abec29e32a53b2be44e41dbcdf87cbee2b00", size = 3206989 },
{ url = "https://files.pythonhosted.org/packages/28/34/6b3ac1d80fc174812486561cf25194338151780f27e438526f9c64e16869/cryptography-44.0.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:404fdc66ee5f83a1388be54300ae978b2efd538018de18556dde92575e05defc", size = 4137925 }, { url = "https://files.pythonhosted.org/packages/9f/f1/676e69c56a9be9fd1bffa9bc3492366901f6e1f8f4079428b05f1414e65c/cryptography-44.0.1-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:a2d8a7045e1ab9b9f803f0d9531ead85f90c5f2859e653b61497228b18452008", size = 6643714 },
{ url = "https://files.pythonhosted.org/packages/d0/c7/c656eb08fd22255d21bc3129625ed9cd5ee305f33752ef2278711b3fa98b/cryptography-44.0.0-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:c5eb858beed7835e5ad1faba59e865109f3e52b3783b9ac21e7e47dc5554e289", size = 3915417 }, { url = "https://files.pythonhosted.org/packages/ba/9f/1775600eb69e72d8f9931a104120f2667107a0ee478f6ad4fe4001559345/cryptography-44.0.1-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b8272f257cf1cbd3f2e120f14c68bff2b6bdfcc157fafdee84a1b795efd72862", size = 3943269 },
{ url = "https://files.pythonhosted.org/packages/ef/82/72403624f197af0db6bac4e58153bc9ac0e6020e57234115db9596eee85d/cryptography-44.0.0-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:f53c2c87e0fb4b0c00fa9571082a057e37690a8f12233306161c8f4b819960b7", size = 4155160 }, { url = "https://files.pythonhosted.org/packages/25/ba/e00d5ad6b58183829615be7f11f55a7b6baa5a06910faabdc9961527ba44/cryptography-44.0.1-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1e8d181e90a777b63f3f0caa836844a1182f1f265687fac2115fcf245f5fbec3", size = 4166461 },
{ url = "https://files.pythonhosted.org/packages/a2/cd/2f3c440913d4329ade49b146d74f2e9766422e1732613f57097fea61f344/cryptography-44.0.0-cp39-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:9e6fc8a08e116fb7c7dd1f040074c9d7b51d74a8ea40d4df2fc7aa08b76b9e6c", size = 3932331 }, { url = "https://files.pythonhosted.org/packages/b3/45/690a02c748d719a95ab08b6e4decb9d81e0ec1bac510358f61624c86e8a3/cryptography-44.0.1-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:436df4f203482f41aad60ed1813811ac4ab102765ecae7a2bbb1dbb66dcff5a7", size = 3950314 },
{ url = "https://files.pythonhosted.org/packages/7f/df/8be88797f0a1cca6e255189a57bb49237402b1880d6e8721690c5603ac23/cryptography-44.0.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:d2436114e46b36d00f8b72ff57e598978b37399d2786fd39793c36c6d5cb1c64", size = 4017372 }, { url = "https://files.pythonhosted.org/packages/e6/50/bf8d090911347f9b75adc20f6f6569ed6ca9b9bff552e6e390f53c2a1233/cryptography-44.0.1-cp39-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:4f422e8c6a28cf8b7f883eb790695d6d45b0c385a2583073f3cec434cc705e1a", size = 3686675 },
{ url = "https://files.pythonhosted.org/packages/af/36/5ccc376f025a834e72b8e52e18746b927f34e4520487098e283a719c205e/cryptography-44.0.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:a01956ddfa0a6790d594f5b34fc1bfa6098aca434696a03cfdbe469b8ed79285", size = 4239657 }, { url = "https://files.pythonhosted.org/packages/e1/e7/cfb18011821cc5f9b21efb3f94f3241e3a658d267a3bf3a0f45543858ed8/cryptography-44.0.1-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:72198e2b5925155497a5a3e8c216c7fb3e64c16ccee11f0e7da272fa93b35c4c", size = 4190429 },
{ url = "https://files.pythonhosted.org/packages/46/b0/f4f7d0d0bcfbc8dd6296c1449be326d04217c57afb8b2594f017eed95533/cryptography-44.0.0-cp39-abi3-win32.whl", hash = "sha256:eca27345e1214d1b9f9490d200f9db5a874479be914199194e746c893788d417", size = 2758672 }, { url = "https://files.pythonhosted.org/packages/07/ef/77c74d94a8bfc1a8a47b3cafe54af3db537f081742ee7a8a9bd982b62774/cryptography-44.0.1-cp39-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:2a46a89ad3e6176223b632056f321bc7de36b9f9b93b2cc1cccf935a3849dc62", size = 3950039 },
{ url = "https://files.pythonhosted.org/packages/97/9b/443270b9210f13f6ef240eff73fd32e02d381e7103969dc66ce8e89ee901/cryptography-44.0.0-cp39-abi3-win_amd64.whl", hash = "sha256:708ee5f1bafe76d041b53a4f95eb28cdeb8d18da17e597d46d7833ee59b97ede", size = 3202071 }, { url = "https://files.pythonhosted.org/packages/6d/b9/8be0ff57c4592382b77406269b1e15650c9f1a167f9e34941b8515b97159/cryptography-44.0.1-cp39-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:53f23339864b617a3dfc2b0ac8d5c432625c80014c25caac9082314e9de56f41", size = 4189713 },
{ url = "https://files.pythonhosted.org/packages/78/e1/4b6ac5f4100545513b0847a4d276fe3c7ce0eacfa73e3b5ebd31776816ee/cryptography-44.0.1-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:888fcc3fce0c888785a4876ca55f9f43787f4c5c1cc1e2e0da71ad481ff82c5b", size = 4071193 },
{ url = "https://files.pythonhosted.org/packages/3d/cb/afff48ceaed15531eab70445abe500f07f8f96af2bb35d98af6bfa89ebd4/cryptography-44.0.1-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:00918d859aa4e57db8299607086f793fa7813ae2ff5a4637e318a25ef82730f7", size = 4289566 },
{ url = "https://files.pythonhosted.org/packages/30/6f/4eca9e2e0f13ae459acd1ca7d9f0257ab86e68f44304847610afcb813dc9/cryptography-44.0.1-cp39-abi3-win32.whl", hash = "sha256:9b336599e2cb77b1008cb2ac264b290803ec5e8e89d618a5e978ff5eb6f715d9", size = 2772371 },
{ url = "https://files.pythonhosted.org/packages/d2/05/5533d30f53f10239616a357f080892026db2d550a40c393d0a8a7af834a9/cryptography-44.0.1-cp39-abi3-win_amd64.whl", hash = "sha256:e403f7f766ded778ecdb790da786b418a9f2394f36e8cc8b796cc056ab05f44f", size = 3207303 },
] ]
[[package]] [[package]]
@ -469,11 +477,11 @@ wheels = [
[[package]] [[package]]
name = "identify" name = "identify"
version = "2.6.6" version = "2.6.7"
source = { registry = "https://pypi.org/simple" } source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/82/bf/c68c46601bacd4c6fb4dd751a42b6e7087240eaabc6487f2ef7a48e0e8fc/identify-2.6.6.tar.gz", hash = "sha256:7bec12768ed44ea4761efb47806f0a41f86e7c0a5fdf5950d4648c90eca7e251", size = 99217 } sdist = { url = "https://files.pythonhosted.org/packages/83/d1/524aa3350f78bcd714d148ade6133d67d6b7de2cdbae7d99039c024c9a25/identify-2.6.7.tar.gz", hash = "sha256:3fa266b42eba321ee0b2bb0936a6a6b9e36a1351cbb69055b3082f4193035684", size = 99260 }
wheels = [ wheels = [
{ url = "https://files.pythonhosted.org/packages/74/a1/68a395c17eeefb04917034bd0a1bfa765e7654fa150cca473d669aa3afb5/identify-2.6.6-py2.py3-none-any.whl", hash = "sha256:cbd1810bce79f8b671ecb20f53ee0ae8e86ae84b557de31d89709dc2a48ba881", size = 99083 }, { url = "https://files.pythonhosted.org/packages/03/00/1fd4a117c6c93f2dcc5b7edaeaf53ea45332ef966429be566ca16c2beb94/identify-2.6.7-py2.py3-none-any.whl", hash = "sha256:155931cb617a401807b09ecec6635d6c692d180090a1cedca8ef7d58ba5b6aa0", size = 99097 },
] ]
[[package]] [[package]]
@ -711,33 +719,33 @@ wheels = [
[[package]] [[package]]
name = "mypy" name = "mypy"
version = "1.14.1" version = "1.15.0"
source = { registry = "https://pypi.org/simple" } source = { registry = "https://pypi.org/simple" }
dependencies = [ dependencies = [
{ name = "mypy-extensions" }, { name = "mypy-extensions" },
{ name = "typing-extensions" }, { name = "typing-extensions" },
] ]
sdist = { url = "https://files.pythonhosted.org/packages/b9/eb/2c92d8ea1e684440f54fa49ac5d9a5f19967b7b472a281f419e69a8d228e/mypy-1.14.1.tar.gz", hash = "sha256:7ec88144fe9b510e8475ec2f5f251992690fcf89ccb4500b214b4226abcd32d6", size = 3216051 } sdist = { url = "https://files.pythonhosted.org/packages/ce/43/d5e49a86afa64bd3839ea0d5b9c7103487007d728e1293f52525d6d5486a/mypy-1.15.0.tar.gz", hash = "sha256:404534629d51d3efea5c800ee7c42b72a6554d6c400e6a79eafe15d11341fd43", size = 3239717 }
wheels = [ wheels = [
{ url = "https://files.pythonhosted.org/packages/da/11/a9422850fd506edbcdc7f6090682ecceaf1f87b9dd847f9df79942da8506/mypy-1.14.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f995e511de847791c3b11ed90084a7a0aafdc074ab88c5a9711622fe4751138c", size = 11120432 }, { url = "https://files.pythonhosted.org/packages/03/bc/f6339726c627bd7ca1ce0fa56c9ae2d0144604a319e0e339bdadafbbb599/mypy-1.15.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2922d42e16d6de288022e5ca321cd0618b238cfc5570e0263e5ba0a77dbef56f", size = 10662338 },
{ url = "https://files.pythonhosted.org/packages/b6/9e/47e450fd39078d9c02d620545b2cb37993a8a8bdf7db3652ace2f80521ca/mypy-1.14.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d64169ec3b8461311f8ce2fd2eb5d33e2d0f2c7b49116259c51d0d96edee48d1", size = 10279515 }, { url = "https://files.pythonhosted.org/packages/e2/90/8dcf506ca1a09b0d17555cc00cd69aee402c203911410136cd716559efe7/mypy-1.15.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2ee2d57e01a7c35de00f4634ba1bbf015185b219e4dc5909e281016df43f5ee5", size = 9787540 },
{ url = "https://files.pythonhosted.org/packages/01/b5/6c8d33bd0f851a7692a8bfe4ee75eb82b6983a3cf39e5e32a5d2a723f0c1/mypy-1.14.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ba24549de7b89b6381b91fbc068d798192b1b5201987070319889e93038967a8", size = 12025791 }, { url = "https://files.pythonhosted.org/packages/05/05/a10f9479681e5da09ef2f9426f650d7b550d4bafbef683b69aad1ba87457/mypy-1.15.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:973500e0774b85d9689715feeffcc980193086551110fd678ebe1f4342fb7c5e", size = 11538051 },
{ url = "https://files.pythonhosted.org/packages/f0/4c/e10e2c46ea37cab5c471d0ddaaa9a434dc1d28650078ac1b56c2d7b9b2e4/mypy-1.14.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:183cf0a45457d28ff9d758730cd0210419ac27d4d3f285beda038c9083363b1f", size = 12749203 }, { url = "https://files.pythonhosted.org/packages/e9/9a/1f7d18b30edd57441a6411fcbc0c6869448d1a4bacbaee60656ac0fc29c8/mypy-1.15.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5a95fb17c13e29d2d5195869262f8125dfdb5c134dc8d9a9d0aecf7525b10c2c", size = 12286751 },
{ url = "https://files.pythonhosted.org/packages/88/55/beacb0c69beab2153a0f57671ec07861d27d735a0faff135a494cd4f5020/mypy-1.14.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f2a0ecc86378f45347f586e4163d1769dd81c5a223d577fe351f26b179e148b1", size = 12885900 }, { url = "https://files.pythonhosted.org/packages/72/af/19ff499b6f1dafcaf56f9881f7a965ac2f474f69f6f618b5175b044299f5/mypy-1.15.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1905f494bfd7d85a23a88c5d97840888a7bd516545fc5aaedff0267e0bb54e2f", size = 12421783 },
{ url = "https://files.pythonhosted.org/packages/a2/75/8c93ff7f315c4d086a2dfcde02f713004357d70a163eddb6c56a6a5eff40/mypy-1.14.1-cp311-cp311-win_amd64.whl", hash = "sha256:ad3301ebebec9e8ee7135d8e3109ca76c23752bac1e717bc84cd3836b4bf3eae", size = 9777869 }, { url = "https://files.pythonhosted.org/packages/96/39/11b57431a1f686c1aed54bf794870efe0f6aeca11aca281a0bd87a5ad42c/mypy-1.15.0-cp311-cp311-win_amd64.whl", hash = "sha256:c9817fa23833ff189db061e6d2eff49b2f3b6ed9856b4a0a73046e41932d744f", size = 9265618 },
{ url = "https://files.pythonhosted.org/packages/43/1b/b38c079609bb4627905b74fc6a49849835acf68547ac33d8ceb707de5f52/mypy-1.14.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:30ff5ef8519bbc2e18b3b54521ec319513a26f1bba19a7582e7b1f58a6e69f14", size = 11266668 }, { url = "https://files.pythonhosted.org/packages/98/3a/03c74331c5eb8bd025734e04c9840532226775c47a2c39b56a0c8d4f128d/mypy-1.15.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:aea39e0583d05124836ea645f412e88a5c7d0fd77a6d694b60d9b6b2d9f184fd", size = 10793981 },
{ url = "https://files.pythonhosted.org/packages/6b/75/2ed0d2964c1ffc9971c729f7a544e9cd34b2cdabbe2d11afd148d7838aa2/mypy-1.14.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:cb9f255c18052343c70234907e2e532bc7e55a62565d64536dbc7706a20b78b9", size = 10254060 }, { url = "https://files.pythonhosted.org/packages/f0/1a/41759b18f2cfd568848a37c89030aeb03534411eef981df621d8fad08a1d/mypy-1.15.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2f2147ab812b75e5b5499b01ade1f4a81489a147c01585cda36019102538615f", size = 9749175 },
{ url = "https://files.pythonhosted.org/packages/a1/5f/7b8051552d4da3c51bbe8fcafffd76a6823779101a2b198d80886cd8f08e/mypy-1.14.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8b4e3413e0bddea671012b063e27591b953d653209e7a4fa5e48759cda77ca11", size = 11933167 }, { url = "https://files.pythonhosted.org/packages/12/7e/873481abf1ef112c582db832740f4c11b2bfa510e829d6da29b0ab8c3f9c/mypy-1.15.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ce436f4c6d218a070048ed6a44c0bbb10cd2cc5e272b29e7845f6a2f57ee4464", size = 11455675 },
{ url = "https://files.pythonhosted.org/packages/04/90/f53971d3ac39d8b68bbaab9a4c6c58c8caa4d5fd3d587d16f5927eeeabe1/mypy-1.14.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:553c293b1fbdebb6c3c4030589dab9fafb6dfa768995a453d8a5d3b23784af2e", size = 12864341 }, { url = "https://files.pythonhosted.org/packages/b3/d0/92ae4cde706923a2d3f2d6c39629134063ff64b9dedca9c1388363da072d/mypy-1.15.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8023ff13985661b50a5928fc7a5ca15f3d1affb41e5f0a9952cb68ef090b31ee", size = 12410020 },
{ url = "https://files.pythonhosted.org/packages/03/d2/8bc0aeaaf2e88c977db41583559319f1821c069e943ada2701e86d0430b7/mypy-1.14.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fad79bfe3b65fe6a1efaed97b445c3d37f7be9fdc348bdb2d7cac75579607c89", size = 12972991 }, { url = "https://files.pythonhosted.org/packages/46/8b/df49974b337cce35f828ba6fda228152d6db45fed4c86ba56ffe442434fd/mypy-1.15.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1124a18bc11a6a62887e3e137f37f53fbae476dc36c185d549d4f837a2a6a14e", size = 12498582 },
{ url = "https://files.pythonhosted.org/packages/6f/17/07815114b903b49b0f2cf7499f1c130e5aa459411596668267535fe9243c/mypy-1.14.1-cp312-cp312-win_amd64.whl", hash = "sha256:8fa2220e54d2946e94ab6dbb3ba0a992795bd68b16dc852db33028df2b00191b", size = 9879016 }, { url = "https://files.pythonhosted.org/packages/13/50/da5203fcf6c53044a0b699939f31075c45ae8a4cadf538a9069b165c1050/mypy-1.15.0-cp312-cp312-win_amd64.whl", hash = "sha256:171a9ca9a40cd1843abeca0e405bc1940cd9b305eaeea2dda769ba096932bb22", size = 9366614 },
{ url = "https://files.pythonhosted.org/packages/9e/15/bb6a686901f59222275ab228453de741185f9d54fecbaacec041679496c6/mypy-1.14.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:92c3ed5afb06c3a8e188cb5da4984cab9ec9a77ba956ee419c68a388b4595255", size = 11252097 }, { url = "https://files.pythonhosted.org/packages/6a/9b/fd2e05d6ffff24d912f150b87db9e364fa8282045c875654ce7e32fffa66/mypy-1.15.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:93faf3fdb04768d44bf28693293f3904bbb555d076b781ad2530214ee53e3445", size = 10788592 },
{ url = "https://files.pythonhosted.org/packages/f8/b3/8b0f74dfd072c802b7fa368829defdf3ee1566ba74c32a2cb2403f68024c/mypy-1.14.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:dbec574648b3e25f43d23577309b16534431db4ddc09fda50841f1e34e64ed34", size = 10239728 }, { url = "https://files.pythonhosted.org/packages/74/37/b246d711c28a03ead1fd906bbc7106659aed7c089d55fe40dd58db812628/mypy-1.15.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:811aeccadfb730024c5d3e326b2fbe9249bb7413553f15499a4050f7c30e801d", size = 9753611 },
{ url = "https://files.pythonhosted.org/packages/c5/9b/4fd95ab20c52bb5b8c03cc49169be5905d931de17edfe4d9d2986800b52e/mypy-1.14.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8c6d94b16d62eb3e947281aa7347d78236688e21081f11de976376cf010eb31a", size = 11924965 }, { url = "https://files.pythonhosted.org/packages/a6/ac/395808a92e10cfdac8003c3de9a2ab6dc7cde6c0d2a4df3df1b815ffd067/mypy-1.15.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:98b7b9b9aedb65fe628c62a6dc57f6d5088ef2dfca37903a7d9ee374d03acca5", size = 11438443 },
{ url = "https://files.pythonhosted.org/packages/56/9d/4a236b9c57f5d8f08ed346914b3f091a62dd7e19336b2b2a0d85485f82ff/mypy-1.14.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d4b19b03fdf54f3c5b2fa474c56b4c13c9dbfb9a2db4370ede7ec11a2c5927d9", size = 12867660 }, { url = "https://files.pythonhosted.org/packages/d2/8b/801aa06445d2de3895f59e476f38f3f8d610ef5d6908245f07d002676cbf/mypy-1.15.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c43a7682e24b4f576d93072216bf56eeff70d9140241f9edec0c104d0c515036", size = 12402541 },
{ url = "https://files.pythonhosted.org/packages/40/88/a61a5497e2f68d9027de2bb139c7bb9abaeb1be1584649fa9d807f80a338/mypy-1.14.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:0c911fde686394753fff899c409fd4e16e9b294c24bfd5e1ea4675deae1ac6fd", size = 12969198 }, { url = "https://files.pythonhosted.org/packages/c7/67/5a4268782eb77344cc613a4cf23540928e41f018a9a1ec4c6882baf20ab8/mypy-1.15.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:baefc32840a9f00babd83251560e0ae1573e2f9d1b067719479bfb0e987c6357", size = 12494348 },
{ url = "https://files.pythonhosted.org/packages/54/da/3d6fc5d92d324701b0c23fb413c853892bfe0e1dbe06c9138037d459756b/mypy-1.14.1-cp313-cp313-win_amd64.whl", hash = "sha256:8b21525cb51671219f5307be85f7e646a153e5acc656e5cebf64bfa076c50107", size = 9885276 }, { url = "https://files.pythonhosted.org/packages/83/3e/57bb447f7bbbfaabf1712d96f9df142624a386d98fb026a761532526057e/mypy-1.15.0-cp313-cp313-win_amd64.whl", hash = "sha256:b9378e2c00146c44793c98b8d5a61039a048e31f429fb0eb546d93f4b000bedf", size = 9373648 },
{ url = "https://files.pythonhosted.org/packages/a0/b5/32dd67b69a16d088e533962e5044e51004176a9952419de0370cdaead0f8/mypy-1.14.1-py3-none-any.whl", hash = "sha256:b66a60cc4073aeb8ae00057f9c1f64d49e90f918fbcef9a977eb121da8b8f1d1", size = 2752905 }, { url = "https://files.pythonhosted.org/packages/09/4e/a7d65c7322c510de2c409ff3828b03354a7c43f5a8ed458a7a131b41c7b9/mypy-1.15.0-py3-none-any.whl", hash = "sha256:5469affef548bd1895d86d3bf10ce2b44e33d86923c29e4d675b3e323437ea3e", size = 2221777 },
] ]
[[package]] [[package]]
@ -751,7 +759,7 @@ wheels = [
[[package]] [[package]]
name = "myst-parser" name = "myst-parser"
version = "4.0.0" version = "4.0.1"
source = { registry = "https://pypi.org/simple" } source = { registry = "https://pypi.org/simple" }
dependencies = [ dependencies = [
{ name = "docutils" }, { name = "docutils" },
@ -761,9 +769,9 @@ dependencies = [
{ name = "pyyaml" }, { name = "pyyaml" },
{ name = "sphinx" }, { name = "sphinx" },
] ]
sdist = { url = "https://files.pythonhosted.org/packages/85/55/6d1741a1780e5e65038b74bce6689da15f620261c490c3511eb4c12bac4b/myst_parser-4.0.0.tar.gz", hash = "sha256:851c9dfb44e36e56d15d05e72f02b80da21a9e0d07cba96baf5e2d476bb91531", size = 93858 } sdist = { url = "https://files.pythonhosted.org/packages/66/a5/9626ba4f73555b3735ad86247a8077d4603aa8628537687c839ab08bfe44/myst_parser-4.0.1.tar.gz", hash = "sha256:5cfea715e4f3574138aecbf7d54132296bfd72bb614d31168f48c477a830a7c4", size = 93985 }
wheels = [ wheels = [
{ url = "https://files.pythonhosted.org/packages/ca/b4/b036f8fdb667587bb37df29dc6644681dd78b7a2a6321a34684b79412b28/myst_parser-4.0.0-py3-none-any.whl", hash = "sha256:b9317997552424448c6096c2558872fdb6f81d3ecb3a40ce84a7518798f3f28d", size = 84563 }, { url = "https://files.pythonhosted.org/packages/5f/df/76d0321c3797b54b60fef9ec3bd6f4cfd124b9e422182156a1dd418722cf/myst_parser-4.0.1-py3-none-any.whl", hash = "sha256:9134e88959ec3b5780aedf8a99680ea242869d012e8821db3126d427edc9c95d", size = 84579 },
] ]
[[package]] [[package]]
@ -993,14 +1001,14 @@ wheels = [
[[package]] [[package]]
name = "pytest-asyncio" name = "pytest-asyncio"
version = "0.25.2" version = "0.25.3"
source = { registry = "https://pypi.org/simple" } source = { registry = "https://pypi.org/simple" }
dependencies = [ dependencies = [
{ name = "pytest" }, { name = "pytest" },
] ]
sdist = { url = "https://files.pythonhosted.org/packages/72/df/adcc0d60f1053d74717d21d58c0048479e9cab51464ce0d2965b086bd0e2/pytest_asyncio-0.25.2.tar.gz", hash = "sha256:3f8ef9a98f45948ea91a0ed3dc4268b5326c0e7bce73892acc654df4262ad45f", size = 53950 } sdist = { url = "https://files.pythonhosted.org/packages/f2/a8/ecbc8ede70921dd2f544ab1cadd3ff3bf842af27f87bbdea774c7baa1d38/pytest_asyncio-0.25.3.tar.gz", hash = "sha256:fc1da2cf9f125ada7e710b4ddad05518d4cee187ae9412e9ac9271003497f07a", size = 54239 }
wheels = [ wheels = [
{ url = "https://files.pythonhosted.org/packages/61/d8/defa05ae50dcd6019a95527200d3b3980043df5aa445d40cb0ef9f7f98ab/pytest_asyncio-0.25.2-py3-none-any.whl", hash = "sha256:0d0bb693f7b99da304a0634afc0a4b19e49d5e0de2d670f38dc4bfa5727c5075", size = 19400 }, { url = "https://files.pythonhosted.org/packages/67/17/3493c5624e48fd97156ebaec380dcaafee9506d7e2c46218ceebbb57d7de/pytest_asyncio-0.25.3-py3-none-any.whl", hash = "sha256:9e89518e0f9bd08928f97a3482fdc4e244df17529460bc038291ccaf8f85c7c3", size = 19467 },
] ]
[[package]] [[package]]
@ -1106,7 +1114,7 @@ wheels = [
[[package]] [[package]]
name = "python-kasa" name = "python-kasa"
version = "0.10.0" version = "0.10.2"
source = { editable = "." } source = { editable = "." }
dependencies = [ dependencies = [
{ name = "aiohttp" }, { name = "aiohttp" },
@ -1258,27 +1266,27 @@ wheels = [
[[package]] [[package]]
name = "ruff" name = "ruff"
version = "0.9.3" version = "0.9.6"
source = { registry = "https://pypi.org/simple" } source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/1e/7f/60fda2eec81f23f8aa7cbbfdf6ec2ca11eb11c273827933fb2541c2ce9d8/ruff-0.9.3.tar.gz", hash = "sha256:8293f89985a090ebc3ed1064df31f3b4b56320cdfcec8b60d3295bddb955c22a", size = 3586740 } sdist = { url = "https://files.pythonhosted.org/packages/2a/e1/e265aba384343dd8ddd3083f5e33536cd17e1566c41453a5517b5dd443be/ruff-0.9.6.tar.gz", hash = "sha256:81761592f72b620ec8fa1068a6fd00e98a5ebee342a3642efd84454f3031dca9", size = 3639454 }
wheels = [ wheels = [
{ url = "https://files.pythonhosted.org/packages/f9/77/4fb790596d5d52c87fd55b7160c557c400e90f6116a56d82d76e95d9374a/ruff-0.9.3-py3-none-linux_armv6l.whl", hash = "sha256:7f39b879064c7d9670197d91124a75d118d00b0990586549949aae80cdc16624", size = 11656815 }, { url = "https://files.pythonhosted.org/packages/76/e3/3d2c022e687e18cf5d93d6bfa2722d46afc64eaa438c7fbbdd603b3597be/ruff-0.9.6-py3-none-linux_armv6l.whl", hash = "sha256:2f218f356dd2d995839f1941322ff021c72a492c470f0b26a34f844c29cdf5ba", size = 11714128 },
{ url = "https://files.pythonhosted.org/packages/a2/a8/3338ecb97573eafe74505f28431df3842c1933c5f8eae615427c1de32858/ruff-0.9.3-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:a187171e7c09efa4b4cc30ee5d0d55a8d6c5311b3e1b74ac5cb96cc89bafc43c", size = 11594821 }, { url = "https://files.pythonhosted.org/packages/e1/22/aff073b70f95c052e5c58153cba735748c9e70107a77d03420d7850710a0/ruff-0.9.6-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:b908ff4df65dad7b251c9968a2e4560836d8f5487c2f0cc238321ed951ea0504", size = 11682539 },
{ url = "https://files.pythonhosted.org/packages/8e/89/320223c3421962762531a6b2dd58579b858ca9916fb2674874df5e97d628/ruff-0.9.3-py3-none-macosx_11_0_arm64.whl", hash = "sha256:c59ab92f8e92d6725b7ded9d4a31be3ef42688a115c6d3da9457a5bda140e2b4", size = 11040475 }, { url = "https://files.pythonhosted.org/packages/75/a7/f5b7390afd98a7918582a3d256cd3e78ba0a26165a467c1820084587cbf9/ruff-0.9.6-py3-none-macosx_11_0_arm64.whl", hash = "sha256:b109c0ad2ececf42e75fa99dc4043ff72a357436bb171900714a9ea581ddef83", size = 11132512 },
{ url = "https://files.pythonhosted.org/packages/b2/bd/1d775eac5e51409535804a3a888a9623e87a8f4b53e2491580858a083692/ruff-0.9.3-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2dc153c25e715be41bb228bc651c1e9b1a88d5c6e5ed0194fa0dfea02b026439", size = 11856207 }, { url = "https://files.pythonhosted.org/packages/a6/e3/45de13ef65047fea2e33f7e573d848206e15c715e5cd56095589a7733d04/ruff-0.9.6-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1de4367cca3dac99bcbd15c161404e849bb0bfd543664db39232648dc00112dc", size = 11929275 },
{ url = "https://files.pythonhosted.org/packages/7f/c6/3e14e09be29587393d188454064a4aa85174910d16644051a80444e4fd88/ruff-0.9.3-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:646909a1e25e0dc28fbc529eab8eb7bb583079628e8cbe738192853dbbe43af5", size = 11420460 }, { url = "https://files.pythonhosted.org/packages/7d/f2/23d04cd6c43b2e641ab961ade8d0b5edb212ecebd112506188c91f2a6e6c/ruff-0.9.6-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ac3ee4d7c2c92ddfdaedf0bf31b2b176fa7aa8950efc454628d477394d35638b", size = 11466502 },
{ url = "https://files.pythonhosted.org/packages/ef/42/b7ca38ffd568ae9b128a2fa76353e9a9a3c80ef19746408d4ce99217ecc1/ruff-0.9.3-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5a5a46e09355695fbdbb30ed9889d6cf1c61b77b700a9fafc21b41f097bfbba4", size = 12605472 }, { url = "https://files.pythonhosted.org/packages/b5/6f/3a8cf166f2d7f1627dd2201e6cbc4cb81f8b7d58099348f0c1ff7b733792/ruff-0.9.6-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5dc1edd1775270e6aa2386119aea692039781429f0be1e0949ea5884e011aa8e", size = 12676364 },
{ url = "https://files.pythonhosted.org/packages/a6/a1/3167023f23e3530fde899497ccfe239e4523854cb874458ac082992d206c/ruff-0.9.3-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:c4bb09d2bbb394e3730d0918c00276e79b2de70ec2a5231cd4ebb51a57df9ba1", size = 13243123 }, { url = "https://files.pythonhosted.org/packages/f5/c4/db52e2189983c70114ff2b7e3997e48c8318af44fe83e1ce9517570a50c6/ruff-0.9.6-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:4a091729086dffa4bd070aa5dab7e39cc6b9d62eb2bef8f3d91172d30d599666", size = 13335518 },
{ url = "https://files.pythonhosted.org/packages/d0/b4/3c600758e320f5bf7de16858502e849f4216cb0151f819fa0d1154874802/ruff-0.9.3-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:96a87ec31dc1044d8c2da2ebbed1c456d9b561e7d087734336518181b26b3aa5", size = 12744650 }, { url = "https://files.pythonhosted.org/packages/66/44/545f8a4d136830f08f4d24324e7db957c5374bf3a3f7a6c0bc7be4623a37/ruff-0.9.6-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d1bbc6808bf7b15796cef0815e1dfb796fbd383e7dbd4334709642649625e7c5", size = 12823287 },
{ url = "https://files.pythonhosted.org/packages/be/38/266fbcbb3d0088862c9bafa8b1b99486691d2945a90b9a7316336a0d9a1b/ruff-0.9.3-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9bb7554aca6f842645022fe2d301c264e6925baa708b392867b7a62645304df4", size = 14458585 }, { url = "https://files.pythonhosted.org/packages/c5/26/8208ef9ee7431032c143649a9967c3ae1aae4257d95e6f8519f07309aa66/ruff-0.9.6-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:589d1d9f25b5754ff230dce914a174a7c951a85a4e9270613a2b74231fdac2f5", size = 14592374 },
{ url = "https://files.pythonhosted.org/packages/63/a6/47fd0e96990ee9b7a4abda62de26d291bd3f7647218d05b7d6d38af47c30/ruff-0.9.3-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cabc332b7075a914ecea912cd1f3d4370489c8018f2c945a30bcc934e3bc06a6", size = 12419624 }, { url = "https://files.pythonhosted.org/packages/31/70/e917781e55ff39c5b5208bda384fd397ffd76605e68544d71a7e40944945/ruff-0.9.6-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dc61dd5131742e21103fbbdcad683a8813be0e3c204472d520d9a5021ca8b217", size = 12500173 },
{ url = "https://files.pythonhosted.org/packages/84/5d/de0b7652e09f7dda49e1a3825a164a65f4998175b6486603c7601279baad/ruff-0.9.3-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:33866c3cc2a575cbd546f2cd02bdd466fed65118e4365ee538a3deffd6fcb730", size = 11843238 }, { url = "https://files.pythonhosted.org/packages/84/f5/e4ddee07660f5a9622a9c2b639afd8f3104988dc4f6ba0b73ffacffa9a8c/ruff-0.9.6-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:5e2d9126161d0357e5c8f30b0bd6168d2c3872372f14481136d13de9937f79b6", size = 11906555 },
{ url = "https://files.pythonhosted.org/packages/9e/be/3f341ceb1c62b565ec1fb6fd2139cc40b60ae6eff4b6fb8f94b1bb37c7a9/ruff-0.9.3-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:006e5de2621304c8810bcd2ee101587712fa93b4f955ed0985907a36c427e0c2", size = 11484012 }, { url = "https://files.pythonhosted.org/packages/f1/2b/6ff2fe383667075eef8656b9892e73dd9b119b5e3add51298628b87f6429/ruff-0.9.6-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:68660eab1a8e65babb5229a1f97b46e3120923757a68b5413d8561f8a85d4897", size = 11538958 },
{ url = "https://files.pythonhosted.org/packages/a3/c8/ff8acbd33addc7e797e702cf00bfde352ab469723720c5607b964491d5cf/ruff-0.9.3-py3-none-musllinux_1_2_i686.whl", hash = "sha256:ba6eea4459dbd6b1be4e6bfc766079fb9b8dd2e5a35aff6baee4d9b1514ea519", size = 12038494 }, { url = "https://files.pythonhosted.org/packages/3c/db/98e59e90de45d1eb46649151c10a062d5707b5b7f76f64eb1e29edf6ebb1/ruff-0.9.6-py3-none-musllinux_1_2_i686.whl", hash = "sha256:c4cae6c4cc7b9b4017c71114115db0445b00a16de3bcde0946273e8392856f08", size = 12117247 },
{ url = "https://files.pythonhosted.org/packages/73/b1/8d9a2c0efbbabe848b55f877bc10c5001a37ab10aca13c711431673414e5/ruff-0.9.3-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:90230a6b8055ad47d3325e9ee8f8a9ae7e273078a66401ac66df68943ced029b", size = 12473639 }, { url = "https://files.pythonhosted.org/packages/ec/bc/54e38f6d219013a9204a5a2015c09e7a8c36cedcd50a4b01ac69a550b9d9/ruff-0.9.6-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:19f505b643228b417c1111a2a536424ddde0db4ef9023b9e04a46ed8a1cb4656", size = 12554647 },
{ url = "https://files.pythonhosted.org/packages/cb/44/a673647105b1ba6da9824a928634fe23186ab19f9d526d7bdf278cd27bc3/ruff-0.9.3-py3-none-win32.whl", hash = "sha256:eabe5eb2c19a42f4808c03b82bd313fc84d4e395133fb3fc1b1516170a31213c", size = 9834353 }, { url = "https://files.pythonhosted.org/packages/a5/7d/7b461ab0e2404293c0627125bb70ac642c2e8d55bf590f6fce85f508f1b2/ruff-0.9.6-py3-none-win32.whl", hash = "sha256:194d8402bceef1b31164909540a597e0d913c0e4952015a5b40e28c146121b5d", size = 9949214 },
{ url = "https://files.pythonhosted.org/packages/c3/01/65cadb59bf8d4fbe33d1a750103e6883d9ef302f60c28b73b773092fbde5/ruff-0.9.3-py3-none-win_amd64.whl", hash = "sha256:040ceb7f20791dfa0e78b4230ee9dce23da3b64dd5848e40e3bf3ab76468dcf4", size = 10821444 }, { url = "https://files.pythonhosted.org/packages/ee/30/c3cee10f915ed75a5c29c1e57311282d1a15855551a64795c1b2bbe5cf37/ruff-0.9.6-py3-none-win_amd64.whl", hash = "sha256:03482d5c09d90d4ee3f40d97578423698ad895c87314c4de39ed2af945633caa", size = 10999914 },
{ url = "https://files.pythonhosted.org/packages/69/cb/b3fe58a136a27d981911cba2f18e4b29f15010623b79f0f2510fd0d31fd3/ruff-0.9.3-py3-none-win_arm64.whl", hash = "sha256:800d773f6d4d33b0a3c60e2c6ae8f4c202ea2de056365acfa519aa48acf28e0b", size = 10038168 }, { url = "https://files.pythonhosted.org/packages/e8/a8/d71f44b93e3aa86ae232af1f2126ca7b95c0f515ec135462b3e1f351441c/ruff-0.9.6-py3-none-win_arm64.whl", hash = "sha256:0e2bb706a2be7ddfea4a4af918562fdc1bcb16df255e5fa595bbd800ce322a5a", size = 10177499 },
] ]
[[package]] [[package]]
@ -1513,16 +1521,16 @@ wheels = [
[[package]] [[package]]
name = "virtualenv" name = "virtualenv"
version = "20.29.1" version = "20.29.2"
source = { registry = "https://pypi.org/simple" } source = { registry = "https://pypi.org/simple" }
dependencies = [ dependencies = [
{ name = "distlib" }, { name = "distlib" },
{ name = "filelock" }, { name = "filelock" },
{ name = "platformdirs" }, { name = "platformdirs" },
] ]
sdist = { url = "https://files.pythonhosted.org/packages/a7/ca/f23dcb02e161a9bba141b1c08aa50e8da6ea25e6d780528f1d385a3efe25/virtualenv-20.29.1.tar.gz", hash = "sha256:b8b8970138d32fb606192cb97f6cd4bb644fa486be9308fb9b63f81091b5dc35", size = 7658028 } sdist = { url = "https://files.pythonhosted.org/packages/f1/88/dacc875dd54a8acadb4bcbfd4e3e86df8be75527116c91d8f9784f5e9cab/virtualenv-20.29.2.tar.gz", hash = "sha256:fdaabebf6d03b5ba83ae0a02cfe96f48a716f4fae556461d180825866f75b728", size = 4320272 }
wheels = [ wheels = [
{ url = "https://files.pythonhosted.org/packages/89/9b/599bcfc7064fbe5740919e78c5df18e5dceb0887e676256a1061bb5ae232/virtualenv-20.29.1-py3-none-any.whl", hash = "sha256:4e4cb403c0b0da39e13b46b1b2476e505cb0046b25f242bee80f62bf990b2779", size = 4282379 }, { url = "https://files.pythonhosted.org/packages/93/fa/849483d56773ae29740ae70043ad88e068f98a6401aa819b5d6bee604683/virtualenv-20.29.2-py3-none-any.whl", hash = "sha256:febddfc3d1ea571bdb1dc0f98d7b45d24def7428214d4fb73cc486c9568cce6a", size = 4301478 },
] ]
[[package]] [[package]]