Interact with modules

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:

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 discover() and 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.

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 a group of functionality check for the existence of the module:

>>> if light := dev.modules.get("Light"):
>>>     print(light.brightness)
100

Some modules have attributes that may not be supported by the device. These attributes will be annotated with a FeatureAttribute return type. For example:

    @property
    def hsv(self) -> Annotated[HSV, FeatureAttribute()]:
        """Return the current HSV state of the bulb."""

You can test whether a FeatureAttribute is supported by the device with kasa.Module.has_feature() or kasa.Module.get_feature() which will return None if not supported. Calling these methods on attributes not annotated with a FeatureAttribute return type will return an error.

To see whether a device supports specific functionality, you can check whether the module has that feature:

>>> if light.has_feature("hsv"):
>>>     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 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