Library Design & Modules

This page aims to provide some details on the design and internals of this library. You might be interested in this if you want to improve this library, or if you are just looking to access some information that is not currently exposed.

Initialization

Use discover() to perform udp-based broadcast discovery on the network. This will return you a list of device instances based on the discovery replies.

If the device’s host is already known, you can use to construct a device instance with connect().

The connect() also enables support for connecting to new KASA SMART protocol and TAPO devices directly using the parameter DeviceConfig. Simply serialize the config property via to_dict() and then deserialize it later with from_dict() and then pass it into connect().

Update Cycle

When update() is called, the library constructs a query to send to the device based on supported modules. Internally, each module defines query() to describe what they want query during the update.

The returned data is cached internally to avoid I/O on property accesses. All properties defined both in the device class and in the module classes follow this principle.

While the properties are designed to provide a nice API to use for common use cases, you may sometimes want to access the raw, cached data as returned by the device. This can be done using the internal_state property.

Modules

The functionality provided by all Device instances is (mostly) done inside separate modules. While the individual device-type specific classes provide an easy access for the most import features, you can also access individual modules through kasa.SmartDevice.modules. You can get the list of supported modules for a given device instance using supported_modules.

Note

If you only need some module-specific information, you can call the wanted method on the module to avoid using update().

Protocols and Transports

The library supports two different TP-Link protocols, IOT and SMART. IOT is the original Kasa protocol and SMART is the newer protocol supported by TAPO devices and newer KASA devices. The original protocol has a target, command, args interface whereas the new protocol uses a different set of commands and has a method, parameters interface. Confusingly TP-Link originally called the Kasa line “Kasa Smart” and hence this library used “Smart” in a lot of the module and class names but actually they were built to work with the IOT protocol.

In 2021 TP-Link started updating the underlying communication transport used by Kasa devices to make them more secure. It switched from a TCP connection with static XOR type of encryption to a transport called KLAP which communicates over http and uses handshakes to negotiate a dynamic encryption cipher. This automatic update was put on hold and only seemed to affect UK HS100 models.

In 2023 TP-Link started updating the underlying communication transport used by Tapo devices to make them more secure. It switched from AES encryption via public key exchange to use KLAP encryption and negotiation due to concerns around impersonation with AES. The encryption cipher is the same as for Kasa KLAP but the handshake seeds are slightly different. Also in 2023 TP-Link started releasing newer Kasa branded devices using the SMART protocol. This appears to be driven by hardware version rather than firmware.

In order to support these different configurations the library migrated from a single protocol class TPLinkSmartHomeProtocol to support pluggable transports and protocols. The classes providing this functionality are:

Errors and Exceptions

The base exception for all library errors is KasaException.

  • If the device returns an error the library raises a DeviceError which will usually contain an error_code with the detail.

  • If the device fails to authenticate the library raises an AuthenticationError which is derived from DeviceError and could contain an error_code depending on the type of failure.

  • If the library encounters and unsupported deviceit raises an UnsupportedDeviceError.

  • If the device fails to respond within a timeout the library raises a TimeoutError.

  • All other failures will raise the base KasaException class.

API documentation for modules and features

class kasa.Module(device: Device, module: str)[source]

Base class implemention for all modules.

The base classes should implement query to return the query they want to be executed during the regular update cycle.

Alarm: Final[ModuleName[smart.Alarm]] = 'Alarm'
AutoOff: Final[ModuleName[smart.AutoOff]] = 'AutoOff'
BatterySensor: Final[ModuleName[smart.BatterySensor]] = 'BatterySensor'
Brightness: Final[ModuleName[smart.Brightness]] = 'Brightness'
ChildDevice: Final[ModuleName[smart.ChildDevice]] = 'ChildDevice'
Cloud: Final[ModuleName[smart.Cloud]] = 'Cloud'
Color: Final[ModuleName[smart.Color]] = 'Color'
ColorTemperature: Final[ModuleName[smart.ColorTemperature]] = 'ColorTemperature'
ContactSensor: Final[ModuleName[smart.ContactSensor]] = 'ContactSensor'
DeviceModule: Final[ModuleName[smart.DeviceModule]] = 'DeviceModule'
Energy: Final[ModuleName[smart.Energy]] = 'Energy'
Fan: Final[ModuleName[smart.Fan]] = 'Fan'
Firmware: Final[ModuleName[smart.Firmware]] = 'Firmware'
FrostProtection: Final[ModuleName[smart.FrostProtection]] = 'FrostProtection'
HumiditySensor: Final[ModuleName[smart.HumiditySensor]] = 'HumiditySensor'
IotAmbientLight: Final[ModuleName[iot.AmbientLight]] = 'ambient'
IotAntitheft: Final[ModuleName[iot.Antitheft]] = 'anti_theft'
IotCloud: Final[ModuleName[iot.Cloud]] = 'cloud'
IotCountdown: Final[ModuleName[iot.Countdown]] = 'countdown'
IotEmeter: Final[ModuleName[iot.Emeter]] = 'emeter'
IotMotion: Final[ModuleName[iot.Motion]] = 'motion'
IotSchedule: Final[ModuleName[iot.Schedule]] = 'schedule'
IotTime: Final[ModuleName[iot.Time]] = 'time'
IotUsage: Final[ModuleName[iot.Usage]] = 'usage'
Led: Final[ModuleName[interfaces.Led]] = 'Led'
Light: Final[ModuleName[interfaces.Light]] = 'Light'
LightEffect: Final[ModuleName[interfaces.LightEffect]] = 'LightEffect'
LightTransition: Final[ModuleName[smart.LightTransition]] = 'LightTransition'
ReportMode: Final[ModuleName[smart.ReportMode]] = 'ReportMode'
TemperatureControl: Final[ModuleName[smart.TemperatureControl]] = 'TemperatureControl'
TemperatureSensor: Final[ModuleName[smart.TemperatureSensor]] = 'TemperatureSensor'
Time: Final[ModuleName[smart.Time]] = 'Time'
WaterleakSensor: Final[ModuleName[smart.WaterleakSensor]] = 'WaterleakSensor'
abstract property data

Return the module specific raw data from the last update.

abstract query()[source]

Query to execute during the update cycle.

The inheriting modules implement this to include their wanted queries to the query that gets executed when Device.update() gets called.

Package for interfaces.

class kasa.interfaces.Fan(device: Device, module: str)[source]

Interface for a Fan.

Alarm: Final[ModuleName[smart.Alarm]] = 'Alarm'
AutoOff: Final[ModuleName[smart.AutoOff]] = 'AutoOff'
BatterySensor: Final[ModuleName[smart.BatterySensor]] = 'BatterySensor'
Brightness: Final[ModuleName[smart.Brightness]] = 'Brightness'
ChildDevice: Final[ModuleName[smart.ChildDevice]] = 'ChildDevice'
Cloud: Final[ModuleName[smart.Cloud]] = 'Cloud'
Color: Final[ModuleName[smart.Color]] = 'Color'
ColorTemperature: Final[ModuleName[smart.ColorTemperature]] = 'ColorTemperature'
ContactSensor: Final[ModuleName[smart.ContactSensor]] = 'ContactSensor'
DeviceModule: Final[ModuleName[smart.DeviceModule]] = 'DeviceModule'
Energy: Final[ModuleName[smart.Energy]] = 'Energy'
Fan: Final[ModuleName[smart.Fan]] = 'Fan'
Firmware: Final[ModuleName[smart.Firmware]] = 'Firmware'
FrostProtection: Final[ModuleName[smart.FrostProtection]] = 'FrostProtection'
HumiditySensor: Final[ModuleName[smart.HumiditySensor]] = 'HumiditySensor'
IotAmbientLight: Final[ModuleName[iot.AmbientLight]] = 'ambient'
IotAntitheft: Final[ModuleName[iot.Antitheft]] = 'anti_theft'
IotCloud: Final[ModuleName[iot.Cloud]] = 'cloud'
IotCountdown: Final[ModuleName[iot.Countdown]] = 'countdown'
IotEmeter: Final[ModuleName[iot.Emeter]] = 'emeter'
IotMotion: Final[ModuleName[iot.Motion]] = 'motion'
IotSchedule: Final[ModuleName[iot.Schedule]] = 'schedule'
IotTime: Final[ModuleName[iot.Time]] = 'time'
IotUsage: Final[ModuleName[iot.Usage]] = 'usage'
Led: Final[ModuleName[interfaces.Led]] = 'Led'
Light: Final[ModuleName[interfaces.Light]] = 'Light'
LightEffect: Final[ModuleName[interfaces.LightEffect]] = 'LightEffect'
LightTransition: Final[ModuleName[smart.LightTransition]] = 'LightTransition'
ReportMode: Final[ModuleName[smart.ReportMode]] = 'ReportMode'
TemperatureControl: Final[ModuleName[smart.TemperatureControl]] = 'TemperatureControl'
TemperatureSensor: Final[ModuleName[smart.TemperatureSensor]] = 'TemperatureSensor'
Time: Final[ModuleName[smart.Time]] = 'Time'
WaterleakSensor: Final[ModuleName[smart.WaterleakSensor]] = 'WaterleakSensor'
abstract property data

Return the module specific raw data from the last update.

abstract property fan_speed_level: int

Return fan speed level.

abstract query()

Query to execute during the update cycle.

The inheriting modules implement this to include their wanted queries to the query that gets executed when Device.update() gets called.

abstract async set_fan_speed_level(level: int)[source]

Set fan speed level.

class kasa.interfaces.Led(device: Device, module: str)[source]

Base interface to represent a LED module.

Alarm: Final[ModuleName[smart.Alarm]] = 'Alarm'
AutoOff: Final[ModuleName[smart.AutoOff]] = 'AutoOff'
BatterySensor: Final[ModuleName[smart.BatterySensor]] = 'BatterySensor'
Brightness: Final[ModuleName[smart.Brightness]] = 'Brightness'
ChildDevice: Final[ModuleName[smart.ChildDevice]] = 'ChildDevice'
Cloud: Final[ModuleName[smart.Cloud]] = 'Cloud'
Color: Final[ModuleName[smart.Color]] = 'Color'
ColorTemperature: Final[ModuleName[smart.ColorTemperature]] = 'ColorTemperature'
ContactSensor: Final[ModuleName[smart.ContactSensor]] = 'ContactSensor'
DeviceModule: Final[ModuleName[smart.DeviceModule]] = 'DeviceModule'
Energy: Final[ModuleName[smart.Energy]] = 'Energy'
Fan: Final[ModuleName[smart.Fan]] = 'Fan'
Firmware: Final[ModuleName[smart.Firmware]] = 'Firmware'
FrostProtection: Final[ModuleName[smart.FrostProtection]] = 'FrostProtection'
HumiditySensor: Final[ModuleName[smart.HumiditySensor]] = 'HumiditySensor'
IotAmbientLight: Final[ModuleName[iot.AmbientLight]] = 'ambient'
IotAntitheft: Final[ModuleName[iot.Antitheft]] = 'anti_theft'
IotCloud: Final[ModuleName[iot.Cloud]] = 'cloud'
IotCountdown: Final[ModuleName[iot.Countdown]] = 'countdown'
IotEmeter: Final[ModuleName[iot.Emeter]] = 'emeter'
IotMotion: Final[ModuleName[iot.Motion]] = 'motion'
IotSchedule: Final[ModuleName[iot.Schedule]] = 'schedule'
IotTime: Final[ModuleName[iot.Time]] = 'time'
IotUsage: Final[ModuleName[iot.Usage]] = 'usage'
Led: Final[ModuleName[interfaces.Led]] = 'Led'
Light: Final[ModuleName[interfaces.Light]] = 'Light'
LightEffect: Final[ModuleName[interfaces.LightEffect]] = 'LightEffect'
LightTransition: Final[ModuleName[smart.LightTransition]] = 'LightTransition'
ReportMode: Final[ModuleName[smart.ReportMode]] = 'ReportMode'
TemperatureControl: Final[ModuleName[smart.TemperatureControl]] = 'TemperatureControl'
TemperatureSensor: Final[ModuleName[smart.TemperatureSensor]] = 'TemperatureSensor'
Time: Final[ModuleName[smart.Time]] = 'Time'
WaterleakSensor: Final[ModuleName[smart.WaterleakSensor]] = 'WaterleakSensor'
abstract property data

Return the module specific raw data from the last update.

abstract property led: bool

Return current led status.

abstract query()

Query to execute during the update cycle.

The inheriting modules implement this to include their wanted queries to the query that gets executed when Device.update() gets called.

abstract async set_led(enable: bool) None[source]

Set led.

class kasa.interfaces.Light(device: Device, module: str)[source]

Base class for TP-Link Light.

Alarm: Final[ModuleName[smart.Alarm]] = 'Alarm'
AutoOff: Final[ModuleName[smart.AutoOff]] = 'AutoOff'
BatterySensor: Final[ModuleName[smart.BatterySensor]] = 'BatterySensor'
Brightness: Final[ModuleName[smart.Brightness]] = 'Brightness'
ChildDevice: Final[ModuleName[smart.ChildDevice]] = 'ChildDevice'
Cloud: Final[ModuleName[smart.Cloud]] = 'Cloud'
Color: Final[ModuleName[smart.Color]] = 'Color'
ColorTemperature: Final[ModuleName[smart.ColorTemperature]] = 'ColorTemperature'
ContactSensor: Final[ModuleName[smart.ContactSensor]] = 'ContactSensor'
DeviceModule: Final[ModuleName[smart.DeviceModule]] = 'DeviceModule'
Energy: Final[ModuleName[smart.Energy]] = 'Energy'
Fan: Final[ModuleName[smart.Fan]] = 'Fan'
Firmware: Final[ModuleName[smart.Firmware]] = 'Firmware'
FrostProtection: Final[ModuleName[smart.FrostProtection]] = 'FrostProtection'
HumiditySensor: Final[ModuleName[smart.HumiditySensor]] = 'HumiditySensor'
IotAmbientLight: Final[ModuleName[iot.AmbientLight]] = 'ambient'
IotAntitheft: Final[ModuleName[iot.Antitheft]] = 'anti_theft'
IotCloud: Final[ModuleName[iot.Cloud]] = 'cloud'
IotCountdown: Final[ModuleName[iot.Countdown]] = 'countdown'
IotEmeter: Final[ModuleName[iot.Emeter]] = 'emeter'
IotMotion: Final[ModuleName[iot.Motion]] = 'motion'
IotSchedule: Final[ModuleName[iot.Schedule]] = 'schedule'
IotTime: Final[ModuleName[iot.Time]] = 'time'
IotUsage: Final[ModuleName[iot.Usage]] = 'usage'
Led: Final[ModuleName[interfaces.Led]] = 'Led'
Light: Final[ModuleName[interfaces.Light]] = 'Light'
LightEffect: Final[ModuleName[interfaces.LightEffect]] = 'LightEffect'
LightTransition: Final[ModuleName[smart.LightTransition]] = 'LightTransition'
ReportMode: Final[ModuleName[smart.ReportMode]] = 'ReportMode'
TemperatureControl: Final[ModuleName[smart.TemperatureControl]] = 'TemperatureControl'
TemperatureSensor: Final[ModuleName[smart.TemperatureSensor]] = 'TemperatureSensor'
Time: Final[ModuleName[smart.Time]] = 'Time'
WaterleakSensor: Final[ModuleName[smart.WaterleakSensor]] = 'WaterleakSensor'
abstract property brightness: int

Return the current brightness in percentage.

abstract property color_temp: int

Whether the bulb supports color temperature changes.

abstract property data

Return the module specific raw data from the last update.

abstract property has_effects: bool

Return True if the device supports effects.

abstract property hsv: HSV

Return the current HSV state of the bulb.

Returns:

hue, saturation and value (degrees, %, %)

abstract property is_color: bool

Whether the bulb supports color changes.

abstract property is_dimmable: bool

Whether the light supports brightness changes.

abstract property is_variable_color_temp: bool

Whether the bulb supports color temperature changes.

abstract query()

Query to execute during the update cycle.

The inheriting modules implement this to include their wanted queries to the query that gets executed when Device.update() gets called.

abstract async set_brightness(brightness: int, *, transition: int | None = None) dict[source]

Set the brightness in percentage.

Note, transition is not supported and will be ignored.

Parameters:
  • brightness (int) – brightness in percent

  • transition (int) – transition in milliseconds.

abstract async set_color_temp(temp: int, *, brightness=None, transition: int | None = None) dict[source]

Set the color temperature of the device in kelvin.

Note, transition is not supported and will be ignored.

Parameters:
  • temp (int) – The new color temperature, in Kelvin

  • transition (int) – transition in milliseconds.

abstract async set_hsv(hue: int, saturation: int, value: int | None = None, *, transition: int | None = None) dict[source]

Set new HSV.

Note, transition is not supported and will be ignored.

Parameters:
  • hue (int) – hue in degrees

  • saturation (int) – saturation in percentage [0,100]

  • value (int) – value in percentage [0, 100]

  • transition (int) – transition in milliseconds.

abstract property valid_temperature_range: ColorTempRange

Return the device-specific white temperature range (in Kelvin).

Returns:

White temperature range in Kelvin (minimum, maximum)

class kasa.interfaces.LightEffect(device: Device, module: str)[source]

Interface to represent a light effect module.

Alarm: Final[ModuleName[smart.Alarm]] = 'Alarm'
AutoOff: Final[ModuleName[smart.AutoOff]] = 'AutoOff'
BatterySensor: Final[ModuleName[smart.BatterySensor]] = 'BatterySensor'
Brightness: Final[ModuleName[smart.Brightness]] = 'Brightness'
ChildDevice: Final[ModuleName[smart.ChildDevice]] = 'ChildDevice'
Cloud: Final[ModuleName[smart.Cloud]] = 'Cloud'
Color: Final[ModuleName[smart.Color]] = 'Color'
ColorTemperature: Final[ModuleName[smart.ColorTemperature]] = 'ColorTemperature'
ContactSensor: Final[ModuleName[smart.ContactSensor]] = 'ContactSensor'
DeviceModule: Final[ModuleName[smart.DeviceModule]] = 'DeviceModule'
Energy: Final[ModuleName[smart.Energy]] = 'Energy'
Fan: Final[ModuleName[smart.Fan]] = 'Fan'
Firmware: Final[ModuleName[smart.Firmware]] = 'Firmware'
FrostProtection: Final[ModuleName[smart.FrostProtection]] = 'FrostProtection'
HumiditySensor: Final[ModuleName[smart.HumiditySensor]] = 'HumiditySensor'
IotAmbientLight: Final[ModuleName[iot.AmbientLight]] = 'ambient'
IotAntitheft: Final[ModuleName[iot.Antitheft]] = 'anti_theft'
IotCloud: Final[ModuleName[iot.Cloud]] = 'cloud'
IotCountdown: Final[ModuleName[iot.Countdown]] = 'countdown'
IotEmeter: Final[ModuleName[iot.Emeter]] = 'emeter'
IotMotion: Final[ModuleName[iot.Motion]] = 'motion'
IotSchedule: Final[ModuleName[iot.Schedule]] = 'schedule'
IotTime: Final[ModuleName[iot.Time]] = 'time'
IotUsage: Final[ModuleName[iot.Usage]] = 'usage'
LIGHT_EFFECTS_OFF = 'Off'
Led: Final[ModuleName[interfaces.Led]] = 'Led'
Light: Final[ModuleName[interfaces.Light]] = 'Light'
LightEffect: Final[ModuleName[interfaces.LightEffect]] = 'LightEffect'
LightTransition: Final[ModuleName[smart.LightTransition]] = 'LightTransition'
ReportMode: Final[ModuleName[smart.ReportMode]] = 'ReportMode'
TemperatureControl: Final[ModuleName[smart.TemperatureControl]] = 'TemperatureControl'
TemperatureSensor: Final[ModuleName[smart.TemperatureSensor]] = 'TemperatureSensor'
Time: Final[ModuleName[smart.Time]] = 'Time'
WaterleakSensor: Final[ModuleName[smart.WaterleakSensor]] = 'WaterleakSensor'
abstract property data

Return the module specific raw data from the last update.

abstract property effect: str

Return effect state or name.

abstract property effect_list: list[str]

Return built-in effects list.

Example:

[‘Aurora’, ‘Bubbling Cauldron’, …]

abstract property has_custom_effects: bool

Return True if the device supports setting custom effects.

abstract query()

Query to execute during the update cycle.

The inheriting modules implement this to include their wanted queries to the query that gets executed when Device.update() gets called.

async set_custom_effect(effect_dict: dict) None[source]

Set a custom effect on the device.

Parameters:

effect_dict (str) – The custom effect dict to set

abstract async set_effect(effect: str, *, brightness: int | None = None, transition: int | None = None) None[source]

Set an effect on the device.

If brightness or transition is defined, its value will be used instead of the effect-specific default.

See effect_list() for available effects, or use set_custom_effect() for custom effects.

Parameters:
  • effect (str) – The effect to set

  • brightness (int) – The wanted brightness

  • transition (int) – The wanted transition time

class kasa.interfaces.LightPreset(*, index: int, brightness: int, hue: Optional[int] = None, saturation: Optional[int] = None, color_temp: Optional[int] = None, custom: Optional[int] = None, id: Optional[str] = None, mode: Optional[int] = None)[source]

Light configuration preset.

Config

alias of BaseConfig

brightness: int
color_temp: Optional[int]
classmethod construct(_fields_set: Optional[SetStr] = None, **values: Any) Model

Creates a new model setting __dict__ and __fields_set__ from trusted or pre-validated data. Default values are respected, but no other validation is performed. Behaves as if Config.extra = ‘allow’ was set since it adds all passed values

copy(*, include: Optional[Union[AbstractSetIntStr, MappingIntStrAny]] = None, exclude: Optional[Union[AbstractSetIntStr, MappingIntStrAny]] = None, update: Optional[DictStrAny] = None, deep: bool = False) Model

Duplicate a model, optionally choose which fields to include, exclude and change.

Parameters:
  • include – fields to include in new model

  • exclude – fields to exclude from new model, as with values this takes precedence over include

  • update – values to change/add in the new model. Note: the data is not validated before creating the new model: you should trust this data

  • deep – set to True to make a deep copy of the model

Returns:

new model instance

custom: Optional[int]
dict(*, include: Optional[Union[AbstractSetIntStr, MappingIntStrAny]] = None, exclude: Optional[Union[AbstractSetIntStr, MappingIntStrAny]] = None, by_alias: bool = False, skip_defaults: Optional[bool] = None, exclude_unset: bool = False, exclude_defaults: bool = False, exclude_none: bool = False) DictStrAny

Generate a dictionary representation of the model, optionally specifying which fields to include or exclude.

classmethod from_orm(obj: Any) Model
hue: Optional[int]
id: Optional[str]
index: int
json(*, include: Optional[Union[AbstractSetIntStr, MappingIntStrAny]] = None, exclude: Optional[Union[AbstractSetIntStr, MappingIntStrAny]] = None, by_alias: bool = False, skip_defaults: Optional[bool] = None, exclude_unset: bool = False, exclude_defaults: bool = False, exclude_none: bool = False, encoder: Optional[Callable[[Any], Any]] = None, models_as_dict: bool = True, **dumps_kwargs: Any) str

Generate a JSON representation of the model, include and exclude arguments as per dict().

encoder is an optional function to supply as default to json.dumps(), other arguments as per json.dumps().

mode: Optional[int]
classmethod parse_file(path: Union[str, Path], *, content_type: str = None, encoding: str = 'utf8', proto: Protocol = None, allow_pickle: bool = False) Model
classmethod parse_obj(obj: Any) Model
classmethod parse_raw(b: Union[str, bytes], *, content_type: str = None, encoding: str = 'utf8', proto: Protocol = None, allow_pickle: bool = False) Model
saturation: Optional[int]
classmethod schema(by_alias: bool = True, ref_template: str = '#/definitions/{model}') DictStrAny
classmethod schema_json(*, by_alias: bool = True, ref_template: str = '#/definitions/{model}', **dumps_kwargs: Any) str
classmethod update_forward_refs(**localns: Any) None

Try to update ForwardRefs on fields based on this Model, globalns and localns.

classmethod validate(value: Any) Model
class kasa.Feature(device: Device, id: str, name: str, attribute_getter: str | Callable | None = None, attribute_setter: str | None = None, container: Any = None, icon: str | None = None, unit: str | None = None, category: Feature.Category = Category.Unset, type: Feature.Type = Type.Sensor, precision_hint: int | None = None, minimum_value: int = 0, maximum_value: int = 65536, range_getter: str | None = None, choices: list[str] | None = None, choices_getter: str | None = None)[source]

Feature defines a generic interface for device features.

Action = 4
BinarySensor = 2
class Category(value, names=None, *values, module=None, qualname=None, type=None, start=1, boundary=None)[source]

Category hint to allow feature grouping.

Config = 2

Config features change device behavior without immediate state changes.

Debug = 4

Debug features deliver more verbose information then informative features. You may want to hide these per default to avoid cluttering your UI.

Info = 3

Informative/sensor features deliver some potentially interesting information.

Primary = 1

Primary features control the device state directly. Examples include turning the device on/off, or adjusting its brightness.

Unset = -1

The default category if none is specified.

Choice = 6
Number = 5
Sensor = 1
Switch = 3
class Type(value, names=None, *values, module=None, qualname=None, type=None, start=1, boundary=None)[source]

Type to help decide how to present the feature.

Action = 4

Action triggers some action on device

BinarySensor = 2

BinarySensor is a read-only boolean

Choice = 6

Choice defines a setting with pre-defined values

Number = 5

Number defines a numeric setting See range_getter, minimum_value, and maximum_value

Sensor = 1

Sensor is an informative read-only value

Switch = 3

Switch is a boolean setting

Unknown = -1
attribute_getter: str | Callable | None = None

Name of the property that allows accessing the value

attribute_setter: str | None = None

Name of the method that allows changing the value

category: Feature.Category = -1

Category hint for downstreams

choices: list[str] | None = None

List of choices as enum

choices_getter: str | None = None

Attribute name of the choices getter property. If set, this property will be used to set choices.

container: Any = None

Container storing the data, this overrides ‘device’ for getters

device: Device

Device instance required for getting and setting values

icon: str | None = None

Icon suggestion

id: str

Identifier

maximum_value: int = 65536

Maximum value

minimum_value: int = 0

Minimum value

name: str

User-friendly short description

precision_hint: int | None = None

Hint to help rounding the sensor values to given after-comma digits

range_getter: str | None = None

Attribute containing the name of the range getter property. If set, this property will be used to set minimum_value and maximum_value.

async set_value(value)[source]

Set the value.

type: Feature.Type = 1

Type of the feature

unit: str | None = None

Unit, if applicable

property value

Return the current value.

API documentation for protocols and transports

class kasa.protocol.BaseProtocol(*, transport: BaseTransport)[source]

Base class for all TP-Link Smart Home communication.

abstract async close() None[source]

Close the protocol. Abstract method to be overriden.

property config: DeviceConfig

Return the connection parameters the device is using.

abstract async query(request: str | dict, retry_count: int = 3) dict[source]

Query the device for the protocol. Abstract method to be overriden.

class kasa.iotprotocol.IotProtocol(*, transport: BaseTransport)[source]

Class for the legacy TPLink IOT KASA Protocol.

BACKOFF_SECONDS_AFTER_TIMEOUT = 1
async close() None[source]

Close the underlying transport.

property config: DeviceConfig

Return the connection parameters the device is using.

async query(request: str | dict, retry_count: int = 3) dict[source]

Query the device retrying for retry_count on failure.

class kasa.smartprotocol.SmartProtocol(*, transport: BaseTransport)[source]

Class for the new TPLink SMART protocol.

BACKOFF_SECONDS_AFTER_TIMEOUT = 1
DEFAULT_MULTI_REQUEST_BATCH_SIZE = 5
async close() None[source]

Close the underlying transport.

property config: DeviceConfig

Return the connection parameters the device is using.

get_smart_request(method, params=None) str[source]

Get a request message as a string.

async query(request: str | dict, retry_count: int = 3) dict[source]

Query the device retrying for retry_count on failure.

class kasa.protocol.BaseTransport(*, config: DeviceConfig)[source]

Base class for all TP-Link protocol transports.

DEFAULT_TIMEOUT = 5
abstract async close() None[source]

Close the transport. Abstract method to be overriden.

abstract property credentials_hash: str

The hashed credentials used by the transport.

abstract property default_port: int

The default port for the transport.

abstract async reset() None[source]

Reset internal state.

abstract async send(request: str) dict[source]

Send a message to the device and return a response.

class kasa.xortransport.XorTransport(*, config: DeviceConfig)[source]

XorTransport class.

BLOCK_SIZE = 4
DEFAULT_PORT: int = 9999
DEFAULT_TIMEOUT = 5
async close() None[source]

Close the connection.

close_without_wait() None[source]

Close the connection without waiting for the connection to close.

property credentials_hash: str

The hashed credentials used by the transport.

property default_port

Default port for the transport.

async reset() None[source]

Reset the transport.

The transport cannot be reset so we must close instead.

async send(request: str) dict[source]

Send a message to the device and return a response.

class kasa.klaptransport.KlapTransport(*, config: DeviceConfig)[source]

Implementation of the KLAP encryption protocol.

KLAP is the name used in device discovery for TP-Link’s new encryption protocol, used by newer firmware versions.

DEFAULT_PORT: int = 80
DEFAULT_TIMEOUT = 5
DISCOVERY_QUERY = {'system': {'get_sysinfo': None}}
async close() None[source]

Close the http client and reset internal state.

property credentials_hash: str

The hashed credentials used by the transport.

property default_port

Default port for the transport.

static generate_auth_hash(creds: Credentials)[source]

Generate an md5 auth hash for the protocol on the supplied credentials.

static generate_owner_hash(creds: Credentials)[source]

Return the MD5 hash of the username in this object.

static handshake1_seed_auth_hash(local_seed: bytes, remote_seed: bytes, auth_hash: bytes)[source]

Generate an md5 auth hash for the protocol on the supplied credentials.

static handshake2_seed_auth_hash(local_seed: bytes, remote_seed: bytes, auth_hash: bytes)[source]

Generate an md5 auth hash for the protocol on the supplied credentials.

async perform_handshake() Any[source]

Perform handshake1 and handshake2.

Sets the encryption_session if successful.

async perform_handshake1() tuple[bytes, bytes, bytes][source]

Perform handshake1.

async perform_handshake2(local_seed, remote_seed, auth_hash) KlapEncryptionSession[source]

Perform handshake2.

async reset() None[source]

Reset internal handshake state.

async send(request: str)[source]

Send the request.

class kasa.klaptransport.KlapTransportV2(*, config: DeviceConfig)[source]

Implementation of the KLAP encryption protocol with v2 hanshake hashes.

DEFAULT_PORT: int = 80
DEFAULT_TIMEOUT = 5
DISCOVERY_QUERY = {'system': {'get_sysinfo': None}}
async close() None

Close the http client and reset internal state.

property credentials_hash: str

The hashed credentials used by the transport.

property default_port

Default port for the transport.

static generate_auth_hash(creds: Credentials)[source]

Generate an md5 auth hash for the protocol on the supplied credentials.

static generate_owner_hash(creds: Credentials)

Return the MD5 hash of the username in this object.

static handshake1_seed_auth_hash(local_seed: bytes, remote_seed: bytes, auth_hash: bytes)[source]

Generate an md5 auth hash for the protocol on the supplied credentials.

static handshake2_seed_auth_hash(local_seed: bytes, remote_seed: bytes, auth_hash: bytes)[source]

Generate an md5 auth hash for the protocol on the supplied credentials.

async perform_handshake() Any

Perform handshake1 and handshake2.

Sets the encryption_session if successful.

async perform_handshake1() tuple[bytes, bytes, bytes]

Perform handshake1.

async perform_handshake2(local_seed, remote_seed, auth_hash) KlapEncryptionSession

Perform handshake2.

async reset() None

Reset internal handshake state.

async send(request: str)

Send the request.

class kasa.aestransport.AesTransport(*, config: DeviceConfig)[source]

Implementation of the AES encryption protocol.

AES is the name used in device discovery for TP-Link’s TAPO encryption protocol, sometimes used by newer firmware versions on kasa devices.

BACKOFF_SECONDS_AFTER_LOGIN_ERROR = 1
COMMON_HEADERS = {'Accept': 'application/json', 'Content-Type': 'application/json', 'requestByApp': 'true'}
CONTENT_LENGTH = 'Content-Length'
DEFAULT_PORT: int = 80
DEFAULT_TIMEOUT = 5
KEY_PAIR_CONTENT_LENGTH = 314
async close() None[source]

Close the http client and reset internal state.

property credentials_hash: str

The hashed credentials used by the transport.

property default_port: int

Default port for the transport.

static hash_credentials(login_v2: bool, credentials: Credentials) tuple[str, str][source]

Hash the credentials.

async perform_handshake() None[source]

Perform the handshake.

async perform_login()[source]

Login to the device.

async reset() None[source]

Reset internal handshake and login state.

async send(request: str) dict[str, Any][source]

Send the request.

async send_secure_passthrough(request: str) dict[str, Any][source]

Send encrypted message as passthrough.

async try_login(login_params: dict[str, Any]) None[source]

Try to login with supplied login_params.

API documentation for errors and exceptions

class kasa.exceptions.KasaException[source]

Base exception for library errors.

class kasa.exceptions.DeviceError(*args: Any, **kwargs: Any)[source]

Base exception for device errors.

class kasa.exceptions.AuthenticationError(*args: Any, **kwargs: Any)[source]

Base exception for device authentication errors.

class kasa.exceptions.UnsupportedDeviceError(*args: Any, **kwargs: Any)[source]

Exception for trying to connect to unsupported devices.

class kasa.exceptions.TimeoutError[source]

Timeout exception for device errors.