mirror of
https://github.com/python-kasa/python-kasa.git
synced 2025-04-26 16:46:23 +00:00
Update docs with more howto examples (#968)
Co-authored-by: Teemu R. <tpr@iki.fi>
This commit is contained in:
parent
6b46773609
commit
0d84d8785e
11
README.md
11
README.md
@ -173,16 +173,9 @@ Current state: {'total': 133.105, 'power': 108.223577, 'current': 0.54463, 'volt
|
|||||||
|
|
||||||
If you want to use this library in your own project, a good starting point is [the tutorial in the documentation](https://python-kasa.readthedocs.io/en/latest/tutorial.html).
|
If you want to use this library in your own project, a good starting point is [the tutorial in the documentation](https://python-kasa.readthedocs.io/en/latest/tutorial.html).
|
||||||
|
|
||||||
You can find several code examples in the API documentation of each of the implementation base classes, check out the [documentation for the base class shared by all supported devices](https://python-kasa.readthedocs.io/en/latest/smartdevice.html).
|
You can find several code examples in the API documentation [How to guides](https://python-kasa.readthedocs.io/en/latest/guides.html).
|
||||||
|
|
||||||
[The library design and module structure is described in a separate page](https://python-kasa.readthedocs.io/en/latest/design.html).
|
Information about the library design and the way the devices work can be found in the [topics section](https://python-kasa.readthedocs.io/en/latest/topics.html).
|
||||||
|
|
||||||
The device type specific documentation can be found in their separate pages:
|
|
||||||
* [Plugs](https://python-kasa.readthedocs.io/en/latest/smartplug.html)
|
|
||||||
* [Bulbs](https://python-kasa.readthedocs.io/en/latest/smartbulb.html)
|
|
||||||
* [Dimmers](https://python-kasa.readthedocs.io/en/latest/smartdimmer.html)
|
|
||||||
* [Power strips](https://python-kasa.readthedocs.io/en/latest/smartstrip.html)
|
|
||||||
* [Light strips](https://python-kasa.readthedocs.io/en/latest/smartlightstrip.html)
|
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
|
26
docs/source/codeinfo.md
Normal file
26
docs/source/codeinfo.md
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
|
||||||
|
:::{note}
|
||||||
|
The library is fully async and methods that perform IO need to be run inside an async coroutine.
|
||||||
|
Code examples assume you are following them inside `asyncio REPL`:
|
||||||
|
```
|
||||||
|
$ python -m asyncio
|
||||||
|
```
|
||||||
|
Or the code is running inside an async function:
|
||||||
|
```py
|
||||||
|
import asyncio
|
||||||
|
from kasa import Discover
|
||||||
|
|
||||||
|
async def main():
|
||||||
|
dev = await Discover.discover_single("127.0.0.1",username="un@example.com",password="pw")
|
||||||
|
await dev.turn_on()
|
||||||
|
await dev.update()
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
asyncio.run(main())
|
||||||
|
```
|
||||||
|
**All of your code needs to run inside the same event loop so only call `asyncio.run` once.**
|
||||||
|
|
||||||
|
*The main entry point for the API is {meth}`~kasa.Discover.discover` and
|
||||||
|
{meth}`~kasa.Discover.discover_single` which return Device objects.
|
||||||
|
Most newer devices require your TP-Link cloud username and password, but this can be omitted for older devices.*
|
||||||
|
:::
|
@ -1,44 +1,16 @@
|
|||||||
# How-to Guides
|
# How-to Guides
|
||||||
|
|
||||||
This page contains guides of how to perform common actions using the library.
|
Guides of how to perform common actions using the library.
|
||||||
|
|
||||||
## Discover devices
|
```{toctree}
|
||||||
|
:maxdepth: 2
|
||||||
|
|
||||||
```{eval-rst}
|
guides/discover
|
||||||
.. automodule:: kasa.discover
|
guides/connect
|
||||||
:noindex:
|
guides/device
|
||||||
```
|
guides/module
|
||||||
|
guides/feature
|
||||||
## Connect without discovery
|
guides/light
|
||||||
|
guides/strip
|
||||||
```{eval-rst}
|
guides/energy
|
||||||
.. automodule:: kasa.deviceconfig
|
|
||||||
:noindex:
|
|
||||||
```
|
|
||||||
|
|
||||||
## Get Energy Consumption and Usage Statistics
|
|
||||||
|
|
||||||
:::{note}
|
|
||||||
In order to use the helper methods to calculate the statistics correctly, your devices need to have correct time set.
|
|
||||||
The devices use NTP and public servers from [NTP Pool Project](https://www.ntppool.org/) to synchronize their time.
|
|
||||||
:::
|
|
||||||
|
|
||||||
### Energy Consumption
|
|
||||||
|
|
||||||
The availability of energy consumption sensors depend on the device.
|
|
||||||
While most of the bulbs support it, only specific switches (e.g., HS110) or strips (e.g., HS300) support it.
|
|
||||||
You can use {attr}`~Device.has_emeter` to check for the availability.
|
|
||||||
|
|
||||||
|
|
||||||
### Usage statistics
|
|
||||||
|
|
||||||
You can use {attr}`~Device.on_since` to query for the time the device has been turned on.
|
|
||||||
Some devices also support reporting the usage statistics on daily or monthly basis.
|
|
||||||
You can access this information using through the usage module ({class}`kasa.modules.Usage`):
|
|
||||||
|
|
||||||
```py
|
|
||||||
dev = SmartPlug("127.0.0.1")
|
|
||||||
usage = dev.modules["usage"]
|
|
||||||
print(f"Minutes on this month: {usage.usage_this_month}")
|
|
||||||
print(f"Minutes on today: {usage.usage_today}")
|
|
||||||
```
|
```
|
||||||
|
10
docs/source/guides/connect.md
Normal file
10
docs/source/guides/connect.md
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
(connect_target)=
|
||||||
|
# Connect without discovery
|
||||||
|
|
||||||
|
:::{include} ../codeinfo.md
|
||||||
|
:::
|
||||||
|
|
||||||
|
```{eval-rst}
|
||||||
|
.. automodule:: kasa.deviceconfig
|
||||||
|
:noindex:
|
||||||
|
```
|
10
docs/source/guides/device.md
Normal file
10
docs/source/guides/device.md
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
(device_target)=
|
||||||
|
# Interact with devices
|
||||||
|
|
||||||
|
:::{include} ../codeinfo.md
|
||||||
|
:::
|
||||||
|
|
||||||
|
```{eval-rst}
|
||||||
|
.. automodule:: kasa.device
|
||||||
|
:noindex:
|
||||||
|
```
|
11
docs/source/guides/discover.md
Normal file
11
docs/source/guides/discover.md
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
(discover_target)=
|
||||||
|
# Discover devices
|
||||||
|
|
||||||
|
:::{include} ../codeinfo.md
|
||||||
|
:::
|
||||||
|
|
||||||
|
|
||||||
|
```{eval-rst}
|
||||||
|
.. automodule:: kasa.discover
|
||||||
|
:noindex:
|
||||||
|
```
|
27
docs/source/guides/energy.md
Normal file
27
docs/source/guides/energy.md
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
|
||||||
|
# Get Energy Consumption and Usage Statistics
|
||||||
|
|
||||||
|
:::{note}
|
||||||
|
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.
|
||||||
|
:::
|
||||||
|
|
||||||
|
## Energy Consumption
|
||||||
|
|
||||||
|
The availability of energy consumption sensors depend on the device.
|
||||||
|
While most of the bulbs support it, only specific switches (e.g., HS110) or strips (e.g., HS300) support it.
|
||||||
|
You can use {attr}`~Device.has_emeter` to check for the availability.
|
||||||
|
|
||||||
|
|
||||||
|
## Usage statistics
|
||||||
|
|
||||||
|
You can use {attr}`~Device.on_since` to query for the time the device has been turned on.
|
||||||
|
Some devices also support reporting the usage statistics on daily or monthly basis.
|
||||||
|
You can access this information using through the usage module ({class}`kasa.modules.Usage`):
|
||||||
|
|
||||||
|
```py
|
||||||
|
dev = SmartPlug("127.0.0.1")
|
||||||
|
usage = dev.modules["usage"]
|
||||||
|
print(f"Minutes on this month: {usage.usage_this_month}")
|
||||||
|
print(f"Minutes on today: {usage.usage_today}")
|
||||||
|
```
|
10
docs/source/guides/feature.md
Normal file
10
docs/source/guides/feature.md
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
(feature_target)=
|
||||||
|
# Interact with features
|
||||||
|
|
||||||
|
:::{include} ../codeinfo.md
|
||||||
|
:::
|
||||||
|
|
||||||
|
```{eval-rst}
|
||||||
|
.. automodule:: kasa.feature
|
||||||
|
:noindex:
|
||||||
|
```
|
26
docs/source/guides/light.md
Normal file
26
docs/source/guides/light.md
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
(light_target)=
|
||||||
|
# Interact with lights
|
||||||
|
|
||||||
|
:::{include} ../codeinfo.md
|
||||||
|
:::
|
||||||
|
|
||||||
|
```{eval-rst}
|
||||||
|
.. automodule:: kasa.interfaces.light
|
||||||
|
:noindex:
|
||||||
|
```
|
||||||
|
|
||||||
|
(lightpreset_target)=
|
||||||
|
## Presets
|
||||||
|
|
||||||
|
```{eval-rst}
|
||||||
|
.. automodule:: kasa.interfaces.lightpreset
|
||||||
|
:noindex:
|
||||||
|
```
|
||||||
|
|
||||||
|
(lighteffect_target)=
|
||||||
|
## Effects
|
||||||
|
|
||||||
|
```{eval-rst}
|
||||||
|
.. automodule:: kasa.interfaces.lighteffect
|
||||||
|
:noindex:
|
||||||
|
```
|
10
docs/source/guides/module.md
Normal file
10
docs/source/guides/module.md
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
(module_target)=
|
||||||
|
# Interact with modules
|
||||||
|
|
||||||
|
:::{include} ../codeinfo.md
|
||||||
|
:::
|
||||||
|
|
||||||
|
```{eval-rst}
|
||||||
|
.. automodule:: kasa.module
|
||||||
|
:noindex:
|
||||||
|
```
|
10
docs/source/guides/strip.md
Normal file
10
docs/source/guides/strip.md
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
(child_target)=
|
||||||
|
# Interact with child devices
|
||||||
|
|
||||||
|
:::{include} ../codeinfo.md
|
||||||
|
:::
|
||||||
|
|
||||||
|
```{eval-rst}
|
||||||
|
.. automodule:: kasa.smart.modules.childdevice
|
||||||
|
:noindex:
|
||||||
|
```
|
@ -3,18 +3,16 @@
|
|||||||
## Discover
|
## Discover
|
||||||
|
|
||||||
|
|
||||||
```{module} kasa.discover
|
```{module} kasa
|
||||||
```
|
```
|
||||||
|
|
||||||
```{eval-rst}
|
```{eval-rst}
|
||||||
.. autoclass:: kasa.Discover
|
.. autoclass:: Discover
|
||||||
:members:
|
:members:
|
||||||
```
|
```
|
||||||
|
|
||||||
## Device
|
## Device
|
||||||
|
|
||||||
```{module} kasa.device
|
|
||||||
```
|
|
||||||
|
|
||||||
```{eval-rst}
|
```{eval-rst}
|
||||||
.. autoclass:: Device
|
.. autoclass:: Device
|
||||||
@ -25,17 +23,14 @@
|
|||||||
|
|
||||||
## Device Config
|
## Device Config
|
||||||
|
|
||||||
```{module} kasa.credentials
|
|
||||||
```
|
|
||||||
|
|
||||||
```{eval-rst}
|
```{eval-rst}
|
||||||
.. autoclass:: Credentials
|
.. autoclass:: Credentials
|
||||||
:members:
|
:members:
|
||||||
:undoc-members:
|
:undoc-members:
|
||||||
|
:noindex:
|
||||||
```
|
```
|
||||||
|
|
||||||
```{module} kasa.deviceconfig
|
|
||||||
```
|
|
||||||
|
|
||||||
```{eval-rst}
|
```{eval-rst}
|
||||||
.. autoclass:: DeviceConfig
|
.. autoclass:: DeviceConfig
|
||||||
@ -45,19 +40,19 @@
|
|||||||
|
|
||||||
|
|
||||||
```{eval-rst}
|
```{eval-rst}
|
||||||
.. autoclass:: kasa.DeviceFamily
|
.. autoclass:: DeviceFamily
|
||||||
:members:
|
:members:
|
||||||
:undoc-members:
|
:undoc-members:
|
||||||
```
|
```
|
||||||
|
|
||||||
```{eval-rst}
|
```{eval-rst}
|
||||||
.. autoclass:: kasa.DeviceConnection
|
.. autoclass:: DeviceConnectionParameters
|
||||||
:members:
|
:members:
|
||||||
:undoc-members:
|
:undoc-members:
|
||||||
```
|
```
|
||||||
|
|
||||||
```{eval-rst}
|
```{eval-rst}
|
||||||
.. autoclass:: kasa.DeviceEncryption
|
.. autoclass:: DeviceEncryptionType
|
||||||
:members:
|
:members:
|
||||||
:undoc-members:
|
:undoc-members:
|
||||||
```
|
```
|
||||||
@ -65,7 +60,15 @@
|
|||||||
## Modules and Features
|
## Modules and Features
|
||||||
|
|
||||||
```{eval-rst}
|
```{eval-rst}
|
||||||
.. autoclass:: kasa.Module
|
.. autoclass:: Module
|
||||||
|
:noindex:
|
||||||
|
:members:
|
||||||
|
:inherited-members:
|
||||||
|
:undoc-members:
|
||||||
|
```
|
||||||
|
|
||||||
|
```{eval-rst}
|
||||||
|
.. autoclass:: Feature
|
||||||
:noindex:
|
:noindex:
|
||||||
:members:
|
:members:
|
||||||
:inherited-members:
|
:inherited-members:
|
||||||
@ -80,14 +83,6 @@
|
|||||||
:undoc-members:
|
:undoc-members:
|
||||||
```
|
```
|
||||||
|
|
||||||
```{eval-rst}
|
|
||||||
.. autoclass:: kasa.Feature
|
|
||||||
:noindex:
|
|
||||||
:members:
|
|
||||||
:inherited-members:
|
|
||||||
:undoc-members:
|
|
||||||
```
|
|
||||||
|
|
||||||
## Protocols and transports
|
## Protocols and transports
|
||||||
|
|
||||||
```{eval-rst}
|
```{eval-rst}
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
# Getting started
|
# Getting started
|
||||||
|
|
||||||
|
:::{include} codeinfo.md
|
||||||
|
:::
|
||||||
|
|
||||||
```{eval-rst}
|
```{eval-rst}
|
||||||
.. automodule:: tutorial
|
.. automodule:: tutorial
|
||||||
:members:
|
:members:
|
||||||
|
@ -1,16 +1,5 @@
|
|||||||
# ruff: noqa
|
# ruff: noqa
|
||||||
"""
|
"""
|
||||||
The kasa library is fully async and methods that perform IO need to be run inside an async couroutine.
|
|
||||||
|
|
||||||
These examples assume you are following the tutorial inside `asyncio REPL` (python -m asyncio) or the code
|
|
||||||
is running inside an async function (`async def`).
|
|
||||||
|
|
||||||
|
|
||||||
The main entry point for the API is :meth:`~kasa.Discover.discover` and
|
|
||||||
:meth:`~kasa.Discover.discover_single` which return Device objects.
|
|
||||||
|
|
||||||
Most newer devices require your TP-Link cloud username and password, but this can be omitted for older devices.
|
|
||||||
|
|
||||||
>>> from kasa import Discover
|
>>> from kasa import Discover
|
||||||
|
|
||||||
:func:`~kasa.Discover.discover` returns a dict[str,Device] of devices on your network:
|
:func:`~kasa.Discover.discover` returns a dict[str,Device] of devices on your network:
|
||||||
|
104
kasa/device.py
104
kasa/device.py
@ -1,4 +1,106 @@
|
|||||||
"""Module for Device base class."""
|
"""Interact with TPLink Smart Home devices.
|
||||||
|
|
||||||
|
Once you have a device via :ref:`Discovery <discover_target>` or
|
||||||
|
:ref:`Connect <connect_target>` you can start interacting with a device.
|
||||||
|
|
||||||
|
>>> from kasa import Discover
|
||||||
|
>>>
|
||||||
|
>>> dev = await Discover.discover_single(
|
||||||
|
>>> "127.0.0.2",
|
||||||
|
>>> username="user@example.com",
|
||||||
|
>>> password="great_password"
|
||||||
|
>>> )
|
||||||
|
>>>
|
||||||
|
|
||||||
|
Most devices can be turned on and off
|
||||||
|
|
||||||
|
>>> await dev.turn_on()
|
||||||
|
>>> await dev.update()
|
||||||
|
>>> print(dev.is_on)
|
||||||
|
True
|
||||||
|
|
||||||
|
>>> await dev.turn_off()
|
||||||
|
>>> await dev.update()
|
||||||
|
>>> print(dev.is_on)
|
||||||
|
False
|
||||||
|
|
||||||
|
All devices provide several informational properties:
|
||||||
|
|
||||||
|
>>> dev.alias
|
||||||
|
Bedroom Lamp Plug
|
||||||
|
>>> dev.model
|
||||||
|
HS110(EU)
|
||||||
|
>>> dev.rssi
|
||||||
|
-71
|
||||||
|
>>> dev.mac
|
||||||
|
50:C7:BF:00:00:00
|
||||||
|
|
||||||
|
Some information can also be changed programmatically:
|
||||||
|
|
||||||
|
>>> await dev.set_alias("new alias")
|
||||||
|
>>> await dev.update()
|
||||||
|
>>> dev.alias
|
||||||
|
new alias
|
||||||
|
|
||||||
|
Devices support different functionality that are exposed via
|
||||||
|
:ref:`modules <module_target>` that you can access via :attr:`~kasa.Device.modules`:
|
||||||
|
|
||||||
|
>>> for module_name in dev.modules:
|
||||||
|
>>> print(module_name)
|
||||||
|
Energy
|
||||||
|
schedule
|
||||||
|
usage
|
||||||
|
anti_theft
|
||||||
|
time
|
||||||
|
cloud
|
||||||
|
Led
|
||||||
|
|
||||||
|
>>> led_module = dev.modules["Led"]
|
||||||
|
>>> print(led_module.led)
|
||||||
|
False
|
||||||
|
>>> await led_module.set_led(True)
|
||||||
|
>>> await dev.update()
|
||||||
|
>>> print(led_module.led)
|
||||||
|
True
|
||||||
|
|
||||||
|
Individual pieces of functionality are also exposed via :ref:`features <feature_target>`
|
||||||
|
which you can access via :attr:`~kasa.Device.features` and will only be present if
|
||||||
|
they are supported.
|
||||||
|
|
||||||
|
Features are similar to modules in that they provide functionality that may or may
|
||||||
|
not be present.
|
||||||
|
|
||||||
|
Whereas modules group functionality into a common interface, features expose a single
|
||||||
|
function that may or may not be part of a module.
|
||||||
|
|
||||||
|
The advantage of features is that they have a simple common interface of `id`, `name`,
|
||||||
|
`value` and `set_value` so no need to learn the module API.
|
||||||
|
|
||||||
|
They are useful if you want write code that dynamically adapts as new features are
|
||||||
|
added to the API.
|
||||||
|
|
||||||
|
>>> for feature_name in dev.features:
|
||||||
|
>>> print(feature_name)
|
||||||
|
state
|
||||||
|
rssi
|
||||||
|
on_since
|
||||||
|
current_consumption
|
||||||
|
consumption_today
|
||||||
|
consumption_this_month
|
||||||
|
consumption_total
|
||||||
|
voltage
|
||||||
|
current
|
||||||
|
cloud_connection
|
||||||
|
led
|
||||||
|
|
||||||
|
>>> led_feature = dev.features["led"]
|
||||||
|
>>> print(led_feature.value)
|
||||||
|
True
|
||||||
|
>>> await led_feature.set_value(False)
|
||||||
|
>>> await dev.update()
|
||||||
|
>>> print(led_feature.value)
|
||||||
|
False
|
||||||
|
"""
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
@ -1,4 +1,67 @@
|
|||||||
"""Generic interface for defining device features."""
|
"""Interact with feature.
|
||||||
|
|
||||||
|
Features are implemented by devices to represent individual pieces of functionality like
|
||||||
|
state, time, firmware.
|
||||||
|
|
||||||
|
>>> from kasa import Discover, Module
|
||||||
|
>>>
|
||||||
|
>>> dev = await Discover.discover_single(
|
||||||
|
>>> "127.0.0.3",
|
||||||
|
>>> username="user@example.com",
|
||||||
|
>>> password="great_password"
|
||||||
|
>>> )
|
||||||
|
>>> await dev.update()
|
||||||
|
>>> print(dev.alias)
|
||||||
|
Living Room Bulb
|
||||||
|
|
||||||
|
Features allow for instrospection and can be interacted with as new features are added
|
||||||
|
to the API:
|
||||||
|
|
||||||
|
>>> for feature_id, feature in dev.features.items():
|
||||||
|
>>> print(f"{feature.name} ({feature_id}): {feature.value}")
|
||||||
|
Device ID (device_id): 0000000000000000000000000000000000000000
|
||||||
|
State (state): True
|
||||||
|
Signal Level (signal_level): 2
|
||||||
|
RSSI (rssi): -52
|
||||||
|
SSID (ssid): #MASKED_SSID#
|
||||||
|
Overheated (overheated): False
|
||||||
|
Brightness (brightness): 100
|
||||||
|
Cloud connection (cloud_connection): True
|
||||||
|
HSV (hsv): HSV(hue=0, saturation=100, value=100)
|
||||||
|
Color temperature (color_temperature): 2700
|
||||||
|
Auto update enabled (auto_update_enabled): False
|
||||||
|
Update available (update_available): False
|
||||||
|
Current firmware version (current_firmware_version): 1.1.6 Build 240130 Rel.173828
|
||||||
|
Available firmware version (available_firmware_version): 1.1.6 Build 240130 Rel.173828
|
||||||
|
Light effect (light_effect): Off
|
||||||
|
Light preset (light_preset): Not set
|
||||||
|
Smooth transition on (smooth_transition_on): 2
|
||||||
|
Smooth transition off (smooth_transition_off): 2
|
||||||
|
Time (time): 2024-02-23 02:40:15+01:00
|
||||||
|
|
||||||
|
To see whether a device supports a feature, check for the existence of it:
|
||||||
|
|
||||||
|
>>> if feature := dev.features.get("brightness"):
|
||||||
|
>>> print(feature.value)
|
||||||
|
100
|
||||||
|
|
||||||
|
You can update the value of a feature
|
||||||
|
|
||||||
|
>>> await feature.set_value(50)
|
||||||
|
>>> await dev.update()
|
||||||
|
>>> print(feature.value)
|
||||||
|
50
|
||||||
|
|
||||||
|
Features have types that can be used for introspection:
|
||||||
|
|
||||||
|
>>> feature = dev.features["light_preset"]
|
||||||
|
>>> print(feature.type)
|
||||||
|
Type.Choice
|
||||||
|
|
||||||
|
>>> print(feature.choices)
|
||||||
|
['Not set', 'Light preset 1', 'Light preset 2', 'Light preset 3',\
|
||||||
|
'Light preset 4', 'Light preset 5', 'Light preset 6', 'Light preset 7']
|
||||||
|
"""
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
@ -1,4 +1,64 @@
|
|||||||
"""Module for Device base class."""
|
"""Interact with a TPLink Light.
|
||||||
|
|
||||||
|
>>> from kasa import Discover, Module
|
||||||
|
>>>
|
||||||
|
>>> dev = await Discover.discover_single(
|
||||||
|
>>> "127.0.0.3",
|
||||||
|
>>> username="user@example.com",
|
||||||
|
>>> password="great_password"
|
||||||
|
>>> )
|
||||||
|
>>> await dev.update()
|
||||||
|
>>> print(dev.alias)
|
||||||
|
Living Room Bulb
|
||||||
|
|
||||||
|
Lights, like any other supported devices, can be turned on and off:
|
||||||
|
|
||||||
|
>>> print(dev.is_on)
|
||||||
|
>>> await dev.turn_on()
|
||||||
|
>>> await dev.update()
|
||||||
|
>>> print(dev.is_on)
|
||||||
|
True
|
||||||
|
|
||||||
|
Get the light module to interact:
|
||||||
|
|
||||||
|
>>> light = dev.modules[Module.Light]
|
||||||
|
|
||||||
|
You can use the ``is_``-prefixed properties to check for supported features:
|
||||||
|
|
||||||
|
>>> light.is_dimmable
|
||||||
|
True
|
||||||
|
>>> light.is_color
|
||||||
|
True
|
||||||
|
>>> light.is_variable_color_temp
|
||||||
|
True
|
||||||
|
|
||||||
|
All known bulbs support changing the brightness:
|
||||||
|
|
||||||
|
>>> light.brightness
|
||||||
|
100
|
||||||
|
>>> await light.set_brightness(50)
|
||||||
|
>>> await dev.update()
|
||||||
|
>>> light.brightness
|
||||||
|
50
|
||||||
|
|
||||||
|
Bulbs supporting color temperature can be queried for the supported range:
|
||||||
|
|
||||||
|
>>> light.valid_temperature_range
|
||||||
|
ColorTempRange(min=2500, max=6500)
|
||||||
|
>>> await light.set_color_temp(3000)
|
||||||
|
>>> await dev.update()
|
||||||
|
>>> light.color_temp
|
||||||
|
3000
|
||||||
|
|
||||||
|
Color bulbs can be adjusted by passing hue, saturation and value:
|
||||||
|
|
||||||
|
>>> await light.set_hsv(180, 100, 80)
|
||||||
|
>>> await dev.update()
|
||||||
|
>>> light.hsv
|
||||||
|
HSV(hue=180, saturation=100, value=80)
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
@ -1,4 +1,44 @@
|
|||||||
"""Module for base light effect module."""
|
"""Interact with a TPLink Light Effect.
|
||||||
|
|
||||||
|
>>> from kasa import Discover, Module, LightState
|
||||||
|
>>>
|
||||||
|
>>> dev = await Discover.discover_single(
|
||||||
|
>>> "127.0.0.3",
|
||||||
|
>>> username="user@example.com",
|
||||||
|
>>> password="great_password"
|
||||||
|
>>> )
|
||||||
|
>>> await dev.update()
|
||||||
|
>>> print(dev.alias)
|
||||||
|
Living Room Bulb
|
||||||
|
|
||||||
|
Light effects are accessed via the LightPreset module. To list available presets
|
||||||
|
|
||||||
|
>>> if dev.modules[Module.Light].has_effects:
|
||||||
|
>>> light_effect = dev.modules[Module.LightEffect]
|
||||||
|
>>> light_effect.effect_list
|
||||||
|
['Off', 'Party', 'Relax']
|
||||||
|
|
||||||
|
To view the currently selected effect:
|
||||||
|
|
||||||
|
>>> light_effect.effect
|
||||||
|
Off
|
||||||
|
|
||||||
|
To activate a light effect:
|
||||||
|
|
||||||
|
>>> await light_effect.set_effect("Party")
|
||||||
|
>>> await dev.update()
|
||||||
|
>>> light_effect.effect
|
||||||
|
Party
|
||||||
|
|
||||||
|
If the device supports it you can set custom effects:
|
||||||
|
|
||||||
|
>>> if light_effect.has_custom_effects:
|
||||||
|
>>> effect_list = { "brightness", 50 }
|
||||||
|
>>> await light_effect.set_custom_effect(effect_list)
|
||||||
|
>>> light_effect.has_custom_effects # The device in this examples does not support \
|
||||||
|
custom effects
|
||||||
|
False
|
||||||
|
"""
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
@ -1,4 +1,72 @@
|
|||||||
"""Module for LightPreset base class."""
|
"""Interact with TPLink Light Presets.
|
||||||
|
|
||||||
|
>>> from kasa import Discover, Module, LightState
|
||||||
|
>>>
|
||||||
|
>>> dev = await Discover.discover_single(
|
||||||
|
>>> "127.0.0.3",
|
||||||
|
>>> username="user@example.com",
|
||||||
|
>>> password="great_password"
|
||||||
|
>>> )
|
||||||
|
>>> await dev.update()
|
||||||
|
>>> print(dev.alias)
|
||||||
|
Living Room Bulb
|
||||||
|
|
||||||
|
Light presets are accessed via the LightPreset module. To list available presets
|
||||||
|
|
||||||
|
>>> light_preset = dev.modules[Module.LightPreset]
|
||||||
|
>>> light_preset.preset_list
|
||||||
|
['Not set', 'Light preset 1', 'Light preset 2', 'Light preset 3',\
|
||||||
|
'Light preset 4', 'Light preset 5', 'Light preset 6', 'Light preset 7']
|
||||||
|
|
||||||
|
To view the currently selected preset:
|
||||||
|
|
||||||
|
>>> light_preset.preset
|
||||||
|
Not set
|
||||||
|
|
||||||
|
To view the actual light state for the presets:
|
||||||
|
|
||||||
|
>>> len(light_preset.preset_states_list)
|
||||||
|
7
|
||||||
|
|
||||||
|
>>> light_preset.preset_states_list[0]
|
||||||
|
LightState(light_on=None, brightness=50, hue=0,\
|
||||||
|
saturation=100, color_temp=2700, transition=None)
|
||||||
|
|
||||||
|
To set a preset as active:
|
||||||
|
|
||||||
|
>>> dev.modules[Module.Light].state # This is only needed to show the example working
|
||||||
|
LightState(light_on=True, brightness=100, hue=0,\
|
||||||
|
saturation=100, color_temp=2700, transition=None)
|
||||||
|
>>> await light_preset.set_preset("Light preset 1")
|
||||||
|
>>> await dev.update()
|
||||||
|
>>> light_preset.preset
|
||||||
|
Light preset 1
|
||||||
|
>>> dev.modules[Module.Light].state # This is only needed to show the example working
|
||||||
|
LightState(light_on=True, brightness=50, hue=0,\
|
||||||
|
saturation=100, color_temp=2700, transition=None)
|
||||||
|
|
||||||
|
You can save a new preset state if the device supports it:
|
||||||
|
|
||||||
|
>>> if light_preset.has_save_preset:
|
||||||
|
>>> new_preset_state = LightState(light_on=True, brightness=75, hue=0,\
|
||||||
|
saturation=100, color_temp=2700, transition=None)
|
||||||
|
>>> await light_preset.save_preset("Light preset 1", new_preset_state)
|
||||||
|
>>> await dev.update()
|
||||||
|
>>> light_preset.preset # Saving updates the preset state for the preset, it does not \
|
||||||
|
set the preset
|
||||||
|
Not set
|
||||||
|
>>> light_preset.preset_states_list[0]
|
||||||
|
LightState(light_on=None, brightness=75, hue=0,\
|
||||||
|
saturation=100, color_temp=2700, transition=None)
|
||||||
|
|
||||||
|
If you manually set the light state to a preset state it will show that preset as \
|
||||||
|
active:
|
||||||
|
|
||||||
|
>>> await dev.modules[Module.Light].set_brightness(75)
|
||||||
|
>>> await dev.update()
|
||||||
|
>>> light_preset.preset
|
||||||
|
Light preset 1
|
||||||
|
"""
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
@ -1,4 +1,42 @@
|
|||||||
"""Base class for all module implementations."""
|
"""Interact with modules.
|
||||||
|
|
||||||
|
Modules are implemented by devices to encapsulate sets of functionality like
|
||||||
|
Light, AutoOff, Firmware etc.
|
||||||
|
|
||||||
|
>>> from kasa import Discover, Module
|
||||||
|
>>>
|
||||||
|
>>> dev = await Discover.discover_single(
|
||||||
|
>>> "127.0.0.3",
|
||||||
|
>>> username="user@example.com",
|
||||||
|
>>> password="great_password"
|
||||||
|
>>> )
|
||||||
|
>>> await dev.update()
|
||||||
|
>>> print(dev.alias)
|
||||||
|
Living Room Bulb
|
||||||
|
|
||||||
|
To see whether a device supports functionality check for the existence of the module:
|
||||||
|
|
||||||
|
>>> if light := dev.modules.get("Light"):
|
||||||
|
>>> print(light.hsv)
|
||||||
|
HSV(hue=0, saturation=100, value=100)
|
||||||
|
|
||||||
|
If you know or expect the module to exist you can access by index:
|
||||||
|
|
||||||
|
>>> light_preset = dev.modules["LightPreset"]
|
||||||
|
>>> print(light_preset.preset_list)
|
||||||
|
['Not set', 'Light preset 1', 'Light preset 2', 'Light preset 3',\
|
||||||
|
'Light preset 4', 'Light preset 5', 'Light preset 6', 'Light preset 7']
|
||||||
|
|
||||||
|
Modules support typing via the Module names in Module:
|
||||||
|
|
||||||
|
>>> from typing_extensions import reveal_type, TYPE_CHECKING
|
||||||
|
>>> light_effect = dev.modules.get("LightEffect")
|
||||||
|
>>> light_effect_typed = dev.modules.get(Module.LightEffect)
|
||||||
|
>>> if TYPE_CHECKING:
|
||||||
|
>>> reveal_type(light_effect) # Static checker will reveal: str
|
||||||
|
>>> reveal_type(light_effect_typed) # Static checker will reveal: LightEffect
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
@ -1,4 +1,42 @@
|
|||||||
"""Implementation for child devices."""
|
"""Interact with child devices.
|
||||||
|
|
||||||
|
>>> from kasa import Discover
|
||||||
|
>>>
|
||||||
|
>>> dev = await Discover.discover_single(
|
||||||
|
>>> "127.0.0.1",
|
||||||
|
>>> username="user@example.com",
|
||||||
|
>>> password="great_password"
|
||||||
|
>>> )
|
||||||
|
>>> await dev.update()
|
||||||
|
>>> print(dev.alias)
|
||||||
|
Bedroom Power Strip
|
||||||
|
|
||||||
|
All methods act on the whole strip:
|
||||||
|
|
||||||
|
>>> for plug in dev.children:
|
||||||
|
>>> print(f"{plug.alias}: {plug.is_on}")
|
||||||
|
Plug 1: True
|
||||||
|
Plug 2: False
|
||||||
|
Plug 3: False
|
||||||
|
>>> dev.is_on
|
||||||
|
True
|
||||||
|
>>> await dev.turn_off()
|
||||||
|
>>> await dev.update()
|
||||||
|
|
||||||
|
Accessing individual plugs can be done using the `children` property:
|
||||||
|
|
||||||
|
>>> len(dev.children)
|
||||||
|
3
|
||||||
|
>>> for plug in dev.children:
|
||||||
|
>>> print(f"{plug.alias}: {plug.is_on}")
|
||||||
|
Plug 1: False
|
||||||
|
Plug 2: False
|
||||||
|
Plug 3: False
|
||||||
|
>>> await dev.children[1].turn_on()
|
||||||
|
>>> await dev.update()
|
||||||
|
>>> dev.is_on
|
||||||
|
True
|
||||||
|
"""
|
||||||
|
|
||||||
from ..smartmodule import SmartModule
|
from ..smartmodule import SmartModule
|
||||||
|
|
||||||
|
@ -69,6 +69,7 @@ def test_discovery_examples(readmes_mock):
|
|||||||
"""Test discovery examples."""
|
"""Test discovery examples."""
|
||||||
res = xdoctest.doctest_module("kasa.discover", "all")
|
res = xdoctest.doctest_module("kasa.discover", "all")
|
||||||
assert res["n_passed"] > 0
|
assert res["n_passed"] > 0
|
||||||
|
assert res["n_warned"] == 0
|
||||||
assert not res["failed"]
|
assert not res["failed"]
|
||||||
|
|
||||||
|
|
||||||
@ -76,6 +77,63 @@ def test_deviceconfig_examples(readmes_mock):
|
|||||||
"""Test discovery examples."""
|
"""Test discovery examples."""
|
||||||
res = xdoctest.doctest_module("kasa.deviceconfig", "all")
|
res = xdoctest.doctest_module("kasa.deviceconfig", "all")
|
||||||
assert res["n_passed"] > 0
|
assert res["n_passed"] > 0
|
||||||
|
assert res["n_warned"] == 0
|
||||||
|
assert not res["failed"]
|
||||||
|
|
||||||
|
|
||||||
|
def test_device_examples(readmes_mock):
|
||||||
|
"""Test device examples."""
|
||||||
|
res = xdoctest.doctest_module("kasa.device", "all")
|
||||||
|
assert res["n_passed"] > 0
|
||||||
|
assert res["n_warned"] == 0
|
||||||
|
assert not res["failed"]
|
||||||
|
|
||||||
|
|
||||||
|
def test_light_examples(readmes_mock):
|
||||||
|
"""Test device examples."""
|
||||||
|
res = xdoctest.doctest_module("kasa.interfaces.light", "all")
|
||||||
|
assert res["n_passed"] > 0
|
||||||
|
assert res["n_warned"] == 0
|
||||||
|
assert not res["failed"]
|
||||||
|
|
||||||
|
|
||||||
|
def test_light_preset_examples(readmes_mock):
|
||||||
|
"""Test device examples."""
|
||||||
|
res = xdoctest.doctest_module("kasa.interfaces.lightpreset", "all")
|
||||||
|
assert res["n_passed"] > 0
|
||||||
|
assert res["n_warned"] == 0
|
||||||
|
assert not res["failed"]
|
||||||
|
|
||||||
|
|
||||||
|
def test_light_effect_examples(readmes_mock):
|
||||||
|
"""Test device examples."""
|
||||||
|
res = xdoctest.doctest_module("kasa.interfaces.lighteffect", "all")
|
||||||
|
assert res["n_passed"] > 0
|
||||||
|
assert res["n_warned"] == 0
|
||||||
|
assert not res["failed"]
|
||||||
|
|
||||||
|
|
||||||
|
def test_child_examples(readmes_mock):
|
||||||
|
"""Test device examples."""
|
||||||
|
res = xdoctest.doctest_module("kasa.smart.modules.childdevice", "all")
|
||||||
|
assert res["n_passed"] > 0
|
||||||
|
assert res["n_warned"] == 0
|
||||||
|
assert not res["failed"]
|
||||||
|
|
||||||
|
|
||||||
|
def test_module_examples(readmes_mock):
|
||||||
|
"""Test device examples."""
|
||||||
|
res = xdoctest.doctest_module("kasa.module", "all")
|
||||||
|
assert res["n_passed"] > 0
|
||||||
|
assert res["n_warned"] == 0
|
||||||
|
assert not res["failed"]
|
||||||
|
|
||||||
|
|
||||||
|
def test_feature_examples(readmes_mock):
|
||||||
|
"""Test device examples."""
|
||||||
|
res = xdoctest.doctest_module("kasa.feature", "all")
|
||||||
|
assert res["n_passed"] > 0
|
||||||
|
assert res["n_warned"] == 0
|
||||||
assert not res["failed"]
|
assert not res["failed"]
|
||||||
|
|
||||||
|
|
||||||
@ -83,6 +141,7 @@ def test_tutorial_examples(readmes_mock):
|
|||||||
"""Test discovery examples."""
|
"""Test discovery examples."""
|
||||||
res = xdoctest.doctest_module("docs/tutorial.py", "all")
|
res = xdoctest.doctest_module("docs/tutorial.py", "all")
|
||||||
assert res["n_passed"] > 0
|
assert res["n_passed"] > 0
|
||||||
|
assert res["n_warned"] == 0
|
||||||
assert not res["failed"]
|
assert not res["failed"]
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user