diff --git a/CHANGELOG.md b/CHANGELOG.md index 776173e..d0b9c9c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,10 @@ file. This change log follows the conventions of - Added support for the L530, L630, and L900 color light bulbs. +### Fixed + +- Fixed a misconfiguration that was preventing the sdist package from working properly. + ## [Rust v0.7.8][v0.7.8] - 2024-01-22 ### Added diff --git a/tapo-py/CHANGELOG.md b/tapo-py/CHANGELOG.md new file mode 120000 index 0000000..83b6947 --- /dev/null +++ b/tapo-py/CHANGELOG.md @@ -0,0 +1 @@ +CHANGELOG.md \ No newline at end of file diff --git a/tapo-py/py.typed b/tapo-py/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/tapo-py/pyproject.toml b/tapo-py/pyproject.toml index 3c707ee..5891053 100644 --- a/tapo-py/pyproject.toml +++ b/tapo-py/pyproject.toml @@ -50,6 +50,7 @@ requires = ["maturin>=1.0,<2.0"] build-backend = "maturin" [tool.maturin] +python-source = "tapo-py" bindings = 'pyo3' features = ["pyo3/extension-module"] -sdist-include = ["README.md", "CHANGELOG.md", "LICENSE"] +include = ["README.md", "CHANGELOG.md", "LICENSE", "tapo-py/tapo-py/tapo/*"] diff --git a/tapo-py/tapo-py/tapo/__init__.py b/tapo-py/tapo-py/tapo/__init__.py new file mode 100644 index 0000000..1f10229 --- /dev/null +++ b/tapo-py/tapo-py/tapo/__init__.py @@ -0,0 +1,5 @@ +from .tapo import * + +__doc__ = tapo.__doc__ +if hasattr(tapo, "__all__"): + __all__ = tapo.__all__ diff --git a/tapo-py/tapo-py/tapo/__init__.pyi b/tapo-py/tapo-py/tapo/__init__.pyi new file mode 100644 index 0000000..03ab94b --- /dev/null +++ b/tapo-py/tapo-py/tapo/__init__.pyi @@ -0,0 +1,7 @@ +from .api_client import * +from .color_light_handler import * +from .generic_device_handler import * +from .light_handler import * +from .plug_energy_monitoring_handler import * +from .plug_handler import * +from .types import * diff --git a/tapo-py/tapo-py/tapo/api_client.pyi b/tapo-py/tapo-py/tapo/api_client.pyi new file mode 100644 index 0000000..7af22fb --- /dev/null +++ b/tapo-py/tapo-py/tapo/api_client.pyi @@ -0,0 +1,269 @@ +"""Tapo API Client. + +Tested with light bulbs (L510, L520, L610) and plugs (P100, P105, P110, P115). + +Example: + ```python + import asyncio + from tapo import ApiClient + + + async def main(): + client = ApiClient("tapo-username@example.com", "tapo-password") + device = await client.l530("192.168.1.100") + + await device.on() + + if __name__ == "__main__": + asyncio.run(main()) + ``` + +See [more examples](https://github.com/mihai-dinculescu/tapo/tree/main/tapo-py/examples). +""" + +from .generic_device_handler import GenericDeviceHandler +from .light_handler import LightHandler +from .color_light_handler import ColorLightHandler +from .plug_handler import PlugHandler +from .plug_energy_monitoring_handler import PlugEnergyMonitoringHandler + +class ApiClient: + """Tapo API Client. + + Tested with light bulbs (L510, L520, L610) and plugs (P100, P105, P110, P115). + + Example: + ```python + import asyncio + from tapo import ApiClient + + + async def main(): + client = ApiClient("tapo-username@example.com", "tapo-password") + device = await client.l530("192.168.1.100") + + await device.on() + + if __name__ == "__main__": + asyncio.run(main()) + ``` + + See [more examples](https://github.com/mihai-dinculescu/tapo/tree/main/tapo-py/examples). + """ + + def __init__(self, tapo_username: str, tapo_password: str) -> None: + """Returns a new instance of `ApiClient`. + + Args: + tapo_username (str): The Tapo username + tapo_password (str): The Tapo password + + Returns: + ApiClient: Tapo API Client. + + Example: + ```python + import asyncio + from tapo import ApiClient + + + async def main(): + client = ApiClient("tapo-username@example.com", "tapo-password") + device = await client.l530("192.168.1.100") + + await device.on() + + if __name__ == "__main__": + asyncio.run(main()) + ``` + + See [more examples](https://github.com/mihai-dinculescu/tapo/tree/main/tapo-py/examples). + """ + async def generic_device(self, ip_address: str) -> GenericDeviceHandler: + """Specializes the given `ApiClient` into an authenticated `GenericDeviceHandler`. + + Args: + ip_address (str): The IP address of the device + + Returns: + GenericDeviceHandler: Handler for generic devices. It provides the + functionality common to all Tapo [devices](https://www.tapo.com/en/). + + Example: + ```python + client = ApiClient("tapo-username@example.com", "tapo-password") + device = await client.generic_device("192.168.1.100") + + await device.on() + ``` + """ + async def l510(self, ip_address: str) -> LightHandler: + """Specializes the given `ApiClient` into an authenticated `LightHandler`. + + Args: + ip_address (str): The IP address of the device + + Returns: + LightHandler: Handler for the [L510](https://www.tapo.com/en/search/?q=L510), [L520](https://www.tapo.com/en/search/?q=L520) and [L610](https://www.tapo.com/en/search/?q=L610) devices. + + Example: + ```python + client = ApiClient("tapo-username@example.com", "tapo-password") + device = await client.l510("192.168.1.100") + + await device.on() + ``` + """ + async def l520(self, ip_address: str) -> LightHandler: + """Specializes the given `ApiClient` into an authenticated `LightHandler`. + + Args: + ip_address (str): The IP address of the device + + Returns: + LightHandler: Handler for the [L510](https://www.tapo.com/en/search/?q=L510), [L520](https://www.tapo.com/en/search/?q=L520) and [L610](https://www.tapo.com/en/search/?q=L610) devices. + + Example: + ```python + client = ApiClient("tapo-username@example.com", "tapo-password") + device = await client.l520("192.168.1.100") + + await device.on() + ``` + """ + async def l530(self, ip_address: str) -> ColorLightHandler: + """Specializes the given `ApiClient` into an authenticated `ColorLightHandler`. + + Args: + ip_address (str): The IP address of the device + + Returns: + ColorLightHandler: Handler for the [L530](https://www.tapo.com/en/search/?q=L530), [L630](https://www.tapo.com/en/search/?q=L630) and [L900](https://www.tapo.com/en/search/?q=L900) devices. + + Example: + ```python + client = ApiClient("tapo-username@example.com", "tapo-password") + device = await client.l530("192.168.1.100") + + await device.on() + ``` + """ + async def l610(self, ip_address: str) -> LightHandler: + """Specializes the given `ApiClient` into an authenticated `LightHandler`. + + Args: + ip_address (str): The IP address of the device + + Returns: + LightHandler: Handler for the [L510](https://www.tapo.com/en/search/?q=L510), [L520](https://www.tapo.com/en/search/?q=L520) and [L610](https://www.tapo.com/en/search/?q=L610) devices. + + Example: + ```python + client = ApiClient("tapo-username@example.com", "tapo-password") + device = await client.l610("192.168.1.100") + + await device.on() + ``` + """ + async def l630(self, ip_address: str) -> ColorLightHandler: + """Specializes the given `ApiClient` into an authenticated `ColorLightHandler`. + + Args: + ip_address (str): The IP address of the device + + Returns: + ColorLightHandler: Handler for the [L530](https://www.tapo.com/en/search/?q=L530), [L630](https://www.tapo.com/en/search/?q=L630) and [L900](https://www.tapo.com/en/search/?q=L900) devices. + + Example: + ```python + client = ApiClient("tapo-username@example.com", "tapo-password") + device = await client.l630("192.168.1.100") + + await device.on() + ``` + """ + async def l900(self, ip_address: str) -> ColorLightHandler: + """Specializes the given `ApiClient` into an authenticated `ColorLightHandler`. + + Args: + ip_address (str): The IP address of the device + + Returns: + ColorLightHandler: Handler for the [L530](https://www.tapo.com/en/search/?q=L530), [L630](https://www.tapo.com/en/search/?q=L630) and [L900](https://www.tapo.com/en/search/?q=L900) devices. + + Example: + ```python + client = ApiClient("tapo-username@example.com", "tapo-password") + device = await client.l900("192.168.1.100") + + await device.on() + ``` + """ + async def p100(self, ip_address: str) -> PlugHandler: + """Specializes the given `ApiClient` into an authenticated `PlugHandler`. + + Args: + ip_address (str): The IP address of the device + + Returns: + PlugHandler: Handler for the [P100](https://www.tapo.com/en/search/?q=P100) & [P105](https://www.tapo.com/en/search/?q=P105) devices. + + Example: + ```python + client = ApiClient("tapo-username@example.com", "tapo-password") + device = await client.p100("192.168.1.100") + + await device.on() + ``` + """ + async def p105(self, ip_address: str) -> PlugHandler: + """Specializes the given `ApiClient` into an authenticated `PlugHandler`. + + Args: + ip_address (str): The IP address of the device + + Returns: + PlugHandler: Handler for the [P100](https://www.tapo.com/en/search/?q=P100) & [P105](https://www.tapo.com/en/search/?q=P105) devices. + + Example: + ```python + client = ApiClient("tapo-username@example.com", "tapo-password") + device = await client.p105("192.168.1.100") + + await device.on() + ``` + """ + async def p110(self, ip_address: str) -> PlugEnergyMonitoringHandler: + """Specializes the given `ApiClient` into an authenticated `PlugEnergyMonitoringHandler`. + + Args: + ip_address (str): The IP address of the device + + Returns: + PlugEnergyMonitoringHandler: Handler for the [P110](https://www.tapo.com/en/search/?q=P110) & [P115](https://www.tapo.com/en/search/?q=P115) devices. + + Example: + ```python + client = ApiClient("tapo-username@example.com", "tapo-password") + device = await client.p110("192.168.1.100") + + await device.on() + ``` + """ + async def p115(self, ip_address: str) -> PlugEnergyMonitoringHandler: + """Specializes the given `ApiClient` into an authenticated `PlugEnergyMonitoringHandler`. + + Args: + ip_address (str): The IP address of the device + + Returns: + PlugEnergyMonitoringHandler: Handler for the [P110](https://www.tapo.com/en/search/?q=P110) & [P115](https://www.tapo.com/en/search/?q=P115) devices. + + Example: + ```python + client = ApiClient("tapo-username@example.com", "tapo-password") + device = await client.p115("192.168.1.100") + + await device.on() + ``` + """ diff --git a/tapo-py/tapo-py/tapo/color_light_handler.pyi b/tapo-py/tapo-py/tapo/color_light_handler.pyi new file mode 100644 index 0000000..2f69fdc --- /dev/null +++ b/tapo-py/tapo-py/tapo/color_light_handler.pyi @@ -0,0 +1,200 @@ +from typing import Optional + +from .types import Color, DefaultStateType, DefaultStateType, DeviceUsageResult + +class ColorLightHandler: + """Handler for the [L530](https://www.tapo.com/en/search/?q=L530), [L630](https://www.tapo.com/en/search/?q=L630) and [L900](https://www.tapo.com/en/search/?q=L900) devices.""" + + def __init__(self, handler: object): + """Private constructor. + It should not be called from outside the tapo library. + """ + async def refresh_session(self) -> None: + """Refreshes the authentication session.""" + async def on(self) -> None: + """Turns *on* the device.""" + async def off(self) -> None: + """Turns *off* the device.""" + async def device_reset(self) -> None: + """*Hardware resets* the device. + + Warning: + This action will reset the device to its factory settings. + The connection to the Wi-Fi network and the Tapo app will be lost, + and the device will need to be reconfigured. + + This feature is especially useful when the device is difficult to access + and requires reconfiguration. + """ + async def get_device_info(self) -> DeviceInfoColorLightResult: + """Returns *device info* as `DeviceInfoColorLightResult`. + It is not guaranteed to contain all the properties returned from the Tapo API. + If the deserialization fails, or if a property that you care about it's not present, + try `ColorLightHandler.get_device_info_json`. + + Returns: + DeviceInfoColorLightResult: Device info of Tapo L530, L630 and L900. + Superset of `GenericDeviceInfoResult`. + """ + async def get_device_info_json(self) -> dict: + """Returns *device info* as json. + It contains all the properties returned from the Tapo API. + + Returns: + dict: Device info as a dictionary. + """ + async def get_device_usage(self) -> DeviceUsageResult: + """Returns *device usage* as `DeviceUsageResult`. + + Returns: + DeviceUsageResult: Contains the time usage. + """ + def set(self) -> ColorLightSetDeviceInfoParams: + """Returns a `ColorLightSetDeviceInfoParams` builder that allows + multiple properties to be set in a single request. + `ColorLightSetDeviceInfoParams.send` must be called at the end to apply the changes. + + Returns: + ColorLightSetDeviceInfoParams: Builder that is used by the + `ColorLightHandler.set` API to set multiple properties in a single request. + """ + async def set_brightness(self, brightness: int) -> None: + """Sets the *brightness* and turns *on* the device. + + Args: + brightness (int): between 1 and 100 + """ + async def set_color(self, color: Color) -> None: + """Sets the *color* and turns *on* the device. + + Args: + color (Color): one of `tapo.Color` as defined in the Google Home app. + """ + async def set_hue_saturation(self, hue: int, saturation: int) -> None: + """Sets the *hue*, *saturation* and turns *on* the device. + + Args: + hue (int): between 1 and 360 + saturation (int): between 1 and 100 + """ + async def set_color_temperature(self, color_temperature: int) -> None: + """Sets the *color temperature* and turns *on* the device. + + Args: + color_temperature (int): between 2500 and 6500 + """ + +class DeviceInfoColorLightResult: + """Device info of Tapo L530, L630 and L900. Superset of `GenericDeviceInfoResult`.""" + + device_id: str + type: str + model: str + hw_id: str + hw_ver: str + fw_id: str + fw_ver: str + oem_id: str + mac: str + ip: str + ssid: str + signal_level: int + rssi: int + specs: str + lang: str + device_on: bool + on_time: int + """The time in seconds this device has been ON since the last state change (ON/OFF).""" + overheated: bool + nickname: str + avatar: str + has_set_location_info: bool + region: Optional[str] + latitude: Optional[float] + longitude: Optional[float] + time_diff: Optional[int] + + # Unique to this device + brightness: int + dynamic_light_effect_enable: bool + dynamic_light_effect_id: Optional[str] + hue: Optional[int] + saturation: Optional[int] + color_temp: int + default_states: DefaultColorLightState + """The default state of a device to be used when internet connectivity is lost after a power cut.""" + + def to_dict(self) -> dict: + """Gets all the properties of this result as a dictionary. + + Returns: + dict: The result as a dictionary. + """ + +class DefaultColorLightState: + """Color Light Default State.""" + + type: DefaultStateType + state: ColorLightState + +class ColorLightState: + """Color Light State.""" + + brightness: int + hue: Optional[int] + saturation: Optional[int] + color_temp: int + +class ColorLightSetDeviceInfoParams: + """Builder that is used by the `ColorLightHandler.set` API to set + multiple properties in a single request. + """ + + def on(self) -> ColorLightSetDeviceInfoParams: + """Turns *on* the device. + `ColorLightSetDeviceInfoParams.send` must be called at the end to apply the changes. + """ + def off(self) -> ColorLightSetDeviceInfoParams: + """Turns *off* the device. + `ColorLightSetDeviceInfoParams.send` must be called at the end to apply the changes. + """ + def brightness(self, brightness: int) -> ColorLightSetDeviceInfoParams: + """Sets the *brightness*. + `ColorLightSetDeviceInfoParams.send` must be called at the end to apply the changes. + The device will also be turned *on*, unless `ColorLightSetDeviceInfoParams.off` is called. + + Args: + brightness (int): between 1 and 100 + """ + def color(self, color: Color) -> ColorLightSetDeviceInfoParams: + """Sets the *color*. + `ColorLightSetDeviceInfoParams.send` must be called at the end to apply the changes. + The device will also be turned *on*, unless `ColorLightSetDeviceInfoParams.off` is called. + + Args: + color (Color): one of `tapo.Color` as defined in the Google Home app. + """ + def hue_saturation( + self, hue: int, saturation: int + ) -> ColorLightSetDeviceInfoParams: + """Sets the *hue* and *saturation*. + `ColorLightSetDeviceInfoParams.send` must be called at the end to apply the changes. + The device will also be turned *on*, unless `ColorLightSetDeviceInfoParams.off` is called. + + Args: + hue (int): between 1 and 360 + saturation (int): between 1 and 100 + """ + def color_temperature( + self, color_temperature: int + ) -> ColorLightSetDeviceInfoParams: + """ + Sets the *color temperature*. + `ColorLightSetDeviceInfoParams.send` must be called at the end to apply the changes. + The device will also be turned *on*, unless `ColorLightSetDeviceInfoParams.off` is called. + + Args: + color_temperature (int): between 2500 and 6500 + """ + async def send(self) -> None: + """Performs a request to apply the changes to the device.""" diff --git a/tapo-py/tapo-py/tapo/generic_device_handler.pyi b/tapo-py/tapo-py/tapo/generic_device_handler.pyi new file mode 100644 index 0000000..fc6b646 --- /dev/null +++ b/tapo-py/tapo-py/tapo/generic_device_handler.pyi @@ -0,0 +1,70 @@ +from typing import Optional + +class GenericDeviceHandler: + """Handler for generic devices. It provides the functionality common to + all Tapo [devices](https://www.tapo.com/en/). + """ + + def __init__(self, handler: object): + """Private constructor. + It should not be called from outside the tapo library. + """ + async def refresh_session(self) -> None: + """Refreshes the authentication session.""" + async def on(self) -> None: + """Turns *on* the device.""" + async def off(self) -> None: + """Turns *off* the device.""" + async def get_device_info(self) -> DeviceInfoGenericResult: + """Returns *device info* as `DeviceInfoGenericResult`. + It is not guaranteed to contain all the properties returned from the Tapo API. + If the deserialization fails, or if a property that you care about it's not present, + try `GenericDeviceHandler.get_device_info_json`. + + Returns: + DeviceInfoGenericResult: Device info of a Generic Tapo device. + """ + async def get_device_info_json(self) -> dict: + """Returns *device info* as json. + It contains all the properties returned from the Tapo API. + + Returns: + dict: Device info as a dictionary. + """ + +class DeviceInfoGenericResult: + """Device info of a Generic Tapo device.""" + + device_id: str + type: str + model: str + hw_id: str + hw_ver: str + fw_id: str + fw_ver: str + oem_id: str + mac: str + ip: str + ssid: str + signal_level: int + rssi: int + specs: str + lang: str + device_on: Optional[bool] + on_time: Optional[int] + """The time in seconds this device has been ON since the last state change (ON/OFF).""" + overheated: bool + nickname: str + avatar: str + has_set_location_info: bool + region: Optional[str] + latitude: Optional[float] + longitude: Optional[float] + time_diff: Optional[int] + + def to_dict(self) -> dict: + """Gets all the properties of this result as a dictionary. + + Returns: + dict: The result as a dictionary. + """ diff --git a/tapo-py/tapo-py/tapo/light_handler.pyi b/tapo-py/tapo-py/tapo/light_handler.pyi new file mode 100644 index 0000000..34bd52f --- /dev/null +++ b/tapo-py/tapo-py/tapo/light_handler.pyi @@ -0,0 +1,115 @@ +from enum import StrEnum +from typing import Optional + +from .types import ( + DefaultBrightnessState, + DefaultPowerType, + DeviceUsageResult, +) + +class LightHandler: + """Handler for the [L510](https://www.tapo.com/en/search/?q=L510), [L520](https://www.tapo.com/en/search/?q=L520) and [L610](https://www.tapo.com/en/search/?q=L610) devices.""" + + def __init__(self, handler: object): + """Private constructor. + It should not be called from outside the tapo library. + """ + async def refresh_session(self) -> None: + """Refreshes the authentication session.""" + async def on(self) -> None: + """Turns *on* the device.""" + async def off(self) -> None: + """Turns *off* the device.""" + async def device_reset(self) -> None: + """*Hardware resets* the device. + + Warning: + This action will reset the device to its factory settings. + The connection to the Wi-Fi network and the Tapo app will be lost, + and the device will need to be reconfigured. + + This feature is especially useful when the device is difficult to access + and requires reconfiguration. + """ + async def get_device_info(self) -> DeviceInfoLightResult: + """Returns *device info* as `DeviceInfoLightResult`. + It is not guaranteed to contain all the properties returned from the Tapo API. + If the deserialization fails, or if a property that you care about it's not present, + try `LightHandler.get_device_info_json`. + + Returns: + DeviceInfoLightResult: Device info of Tapo L510, L520 and L610. + Superset of `GenericDeviceInfoResult`. + """ + async def get_device_info_json(self) -> dict: + """Returns *device info* as json. + It contains all the properties returned from the Tapo API. + + Returns: + dict: Device info as a dictionary. + """ + async def get_device_usage(self) -> DeviceUsageResult: + """Returns *device usage* as `DeviceUsageResult`. + + Returns: + DeviceUsageResult: Contains the time usage. + """ + async def set_brightness(self, brightness: int) -> None: + """Sets the *brightness* and turns *on* the device. + + Args: + brightness (int): between 1 and 100 + """ + +class DeviceInfoLightResult: + """Device info of Tapo L510, L520 and L610. Superset of `GenericDeviceInfoResult`.""" + + device_id: str + type: str + model: str + hw_id: str + hw_ver: str + fw_id: str + fw_ver: str + oem_id: str + mac: str + ip: str + ssid: str + signal_level: int + rssi: int + specs: str + lang: str + device_on: bool + on_time: int + """The time in seconds this device has been ON since the last state change (ON/OFF).""" + overheated: bool + nickname: str + avatar: str + has_set_location_info: bool + region: Optional[str] + latitude: Optional[float] + longitude: Optional[float] + time_diff: Optional[int] + + # Unique to this device + brightness: int + dynamic_light_effect_enable: bool + dynamic_light_effect_id: Optional[str] + hue: Optional[int] + saturation: Optional[int] + color_temp: int + default_states: DefaultLightState + """The default state of a device to be used when internet connectivity is lost after a power cut.""" + + def to_dict(self) -> dict: + """Gets all the properties of this result as a dictionary. + + Returns: + dict: The result as a dictionary. + """ + +class DefaultLightState: + """Light Default State.""" + + brightness: DefaultBrightnessState + re_power_type: Optional[DefaultPowerType] diff --git a/tapo-py/tapo-py/tapo/plug_energy_monitoring_handler.pyi b/tapo-py/tapo-py/tapo/plug_energy_monitoring_handler.pyi new file mode 100644 index 0000000..196b048 --- /dev/null +++ b/tapo-py/tapo-py/tapo/plug_energy_monitoring_handler.pyi @@ -0,0 +1,154 @@ +from datetime import datetime +from enum import StrEnum +from typing import List + +from .types import DeviceUsageEnergyMonitoringResult +from .plug_handler import DeviceInfoPlugResult + +class PlugEnergyMonitoringHandler: + """Handler for the [P110](https://www.tapo.com/en/search/?q=P110) & [P115](https://www.tapo.com/en/search/?q=P115) devices.""" + + def __init__(self, handler: object): + """Private constructor. + It should not be called from outside the tapo library. + """ + async def refresh_session(self) -> None: + """Refreshes the authentication session.""" + async def on(self) -> None: + """Turns *on* the device.""" + async def off(self) -> None: + """Turns *off* the device.""" + async def device_reset(self) -> None: + """*Hardware resets* the device. + + Warning: + This action will reset the device to its factory settings. + The connection to the Wi-Fi network and the Tapo app will be lost, + and the device will need to be reconfigured. + + This feature is especially useful when the device is difficult to access + and requires reconfiguration. + """ + async def get_device_info(self) -> DeviceInfoPlugResult: + """Returns *device info* as `DeviceInfoPlugResult`. + It is not guaranteed to contain all the properties returned from the Tapo API. + If the deserialization fails, or if a property that you care about it's not present, + try `PlugEnergyMonitoringHandler.get_device_info_json`. + + Returns: + DeviceInfoPlugResult: Device info of Tapo P100, P105, P110 and P115. + Superset of `GenericDeviceInfoResult`. + """ + async def get_device_info_json(self) -> dict: + """Returns *device info* as json. + It contains all the properties returned from the Tapo API. + + Returns: + dict: Device info as a dictionary. + """ + async def get_device_usage(self) -> DeviceUsageEnergyMonitoringResult: + """Returns *device usage* as `DeviceUsageResult`. + + Returns: + DeviceUsageEnergyMonitoringResult: + Contains the time usage, the power consumption, and the energy savings of the device. + """ + async def get_current_power(self) -> CurrentPowerResult: + """Returns *current power* as `CurrentPowerResult`. + + Returns: + CurrentPowerResult: Contains the current power reading of the device. + """ + async def get_energy_usage(self) -> EnergyUsageResult: + """Returns *energy usage* as `EnergyUsageResult`. + + Returns: + EnergyUsageResult: + Contains local time, current power and the energy usage and runtime for today and for the current month. + """ + async def get_energy_data( + self, + interval: EnergyDataInterval, + start_date: datetime, + end_date: datetime = None, + ) -> EnergyDataResult: + """Returns *energy data* as `EnergyDataResult`. + + Returns: + EnergyDataResult: Energy data for the requested `EnergyDataInterval`. + """ + +class CurrentPowerResult: + """Contains the current power reading of the device.""" + + current_power: int + """Current power in watts (W).""" + + def to_dict(self) -> dict: + """Gets all the properties of this result as a dictionary. + + Returns: + dict: The result as a dictionary. + """ + +class EnergyUsageResult: + """Contains local time, current power and the energy usage and runtime for today and for the current month.""" + + local_time: datetime + """Local time of the device.""" + current_power: int + """Current power in milliwatts (mW).""" + today_runtime: int + """Today runtime in minutes.""" + today_energy: int + """Today energy usage in watts (W).""" + month_runtime: int + """Current month runtime in minutes.""" + month_energy: int + """Current month energy usage in watts (W).""" + + def to_dict(self) -> dict: + """Gets all the properties of this result as a dictionary. + + Returns: + dict: The result as a dictionary. + """ + +class EnergyDataResult: + """Energy data for the requested `EnergyDataInterval`.""" + + local_time: datetime + """Local time of the device.""" + + data: List[int] + """Energy data for the given `interval` in watts (W).""" + + start_timestamp: int + """Interval start timestamp in milliseconds.""" + + end_timestamp: int + """Interval end timestamp in milliseconds.""" + + interval: int + """Interval in minutes.""" + + def to_dict(self) -> dict: + """Gets all the properties of this result as a dictionary. + + Returns: + dict: The result as a dictionary. + """ + +class EnergyDataInterval(StrEnum): + """Energy data interval.""" + + Hourly = "Hourly" + """Hourly interval. `start_date` and `end_date` are an inclusive interval + that must not be greater than 8 days. + """ + + Daily = "Daily" + """Daily interval. `start_date` must be the first day of a quarter.""" + + Monthly = "Monthly" + """Monthly interval. `start_date` must be the first day of a year.""" diff --git a/tapo-py/tapo-py/tapo/plug_handler.pyi b/tapo-py/tapo-py/tapo/plug_handler.pyi new file mode 100644 index 0000000..d3d6d53 --- /dev/null +++ b/tapo-py/tapo-py/tapo/plug_handler.pyi @@ -0,0 +1,102 @@ +from typing import Optional +from .types import DefaultStateType, DeviceUsageResult + +class PlugHandler: + """Handler for the [P100](https://www.tapo.com/en/search/?q=P100) & [P105](https://www.tapo.com/en/search/?q=P105) devices.""" + + def __init__(self, handler: object): + """Private constructor. + It should not be called from outside the tapo library. + """ + async def refresh_session(self) -> None: + """Refreshes the authentication session.""" + async def on(self) -> None: + """Turns *on* the device.""" + async def off(self) -> None: + """Turns *off* the device.""" + async def device_reset(self) -> None: + """*Hardware resets* the device. + + Warning: + This action will reset the device to its factory settings. + The connection to the Wi-Fi network and the Tapo app will be lost, + and the device will need to be reconfigured. + + This feature is especially useful when the device is difficult to access + and requires reconfiguration. + """ + async def get_device_info(self) -> DeviceInfoPlugResult: + """Returns *device info* as `DeviceInfoPlugResult`. + It is not guaranteed to contain all the properties returned from the Tapo API. + If the deserialization fails, or if a property that you care about it's not present, + try `PlugHandler.get_device_info_json`. + + Returns: + DeviceInfoPlugResult: Device info of Tapo P100, P105, P110 and P115. + Superset of `GenericDeviceInfoResult`. + """ + async def get_device_info_json(self) -> dict: + """Returns *device info* as json. + It contains all the properties returned from the Tapo API. + + Returns: + dict: Device info as a dictionary. + """ + async def get_device_usage(self) -> DeviceUsageResult: + """Returns *device usage* as `DeviceUsageResult`. + + Returns: + DeviceUsageResult: Contains the time usage. + """ + +class DeviceInfoPlugResult: + """Device info of Tapo P100, P105, P110 and P115. Superset of `GenericDeviceInfoResult`.""" + + device_id: str + type: str + model: str + hw_id: str + hw_ver: str + fw_id: str + fw_ver: str + oem_id: str + mac: str + ip: str + ssid: str + signal_level: int + rssi: int + specs: str + lang: str + device_on: bool + on_time: int + """The time in seconds this device has been ON since the last state change (ON/OFF).""" + overheated: bool + nickname: str + avatar: str + has_set_location_info: bool + region: Optional[str] + latitude: Optional[float] + longitude: Optional[float] + time_diff: Optional[int] + + # Unique to this device + default_states: PlugDefaultState + """The default state of a device to be used when internet connectivity is lost after a power cut.""" + + def to_dict(self) -> dict: + """Gets all the properties of this result as a dictionary. + + Returns: + dict: The result as a dictionary. + """ + +class PlugDefaultState: + """Plug Default State.""" + + type: DefaultStateType + state: PlugState + +class PlugState: + """Plug State.""" + + on: Optional[bool] diff --git a/tapo-py/tapo-py/tapo/types.pyi b/tapo-py/tapo-py/tapo/types.pyi new file mode 100644 index 0000000..bd1bfc2 --- /dev/null +++ b/tapo-py/tapo-py/tapo/types.pyi @@ -0,0 +1,108 @@ +from enum import StrEnum + +class DefaultBrightnessState: + """Default brightness state.""" + + type: DefaultStateType + value: int + +class DefaultStateType(StrEnum): + """The type of the default state.""" + + Custom = "custom" + LastStates = "last_states" + +class DefaultPowerType(StrEnum): + """The type of the default power state.""" + + AlwaysOn = "always_on" + LastStates = "last_states" + +class UsageByPeriodResult: + """Usage by period result for today, the past 7 days, and the past 30 days.""" + + today: int + """Today.""" + past7: int + """Past 7 days.""" + past30: int + """Past 30 days.""" + +class DeviceUsageResult: + """Contains the time in use, the power consumption, and the energy savings of the device.""" + + time_usage: UsageByPeriodResult + """Time usage in minutes.""" + power_usage: UsageByPeriodResult + """Power usage in watt-hour (Wh).""" + saved_power: UsageByPeriodResult + """Saved power in watt-hour (Wh).""" + + def to_dict(self) -> dict: + """Gets all the properties of this result as a dictionary. + + Returns: + dict: The result as a dictionary. + """ + +class DeviceUsageEnergyMonitoringResult: + """Contains the time in use, the power consumption, and the energy savings of the device.""" + + time_usage: UsageByPeriodResult + """Time usage in minutes.""" + power_usage: UsageByPeriodResult + """Power usage in watt-hour (Wh).""" + saved_power: UsageByPeriodResult + """Saved power in watt-hour (Wh).""" + + def to_dict(self) -> dict: + """Gets all the properties of this result as a dictionary. + + Returns: + dict: The result as a dictionary. + """ + +class Color(StrEnum): + """List of preset colors as defined in the Google Home app.""" + + CoolWhite = "CoolWhite" + Daylight = "Daylight" + Ivory = "Ivory" + WarmWhite = "WarmWhite" + Incandescent = "Incandescent" + Candlelight = "Candlelight" + Snow = "Snow" + GhostWhite = "GhostWhite" + AliceBlue = "AliceBlue" + LightGoldenrod = "LightGoldenrod" + LemonChiffon = "LemonChiffon" + AntiqueWhite = "AntiqueWhite" + Gold = "Gold" + Peru = "Peru" + Chocolate = "Chocolate" + SandyBrown = "SandyBrown" + Coral = "Coral" + Pumpkin = "Pumpkin" + Tomato = "Tomato" + Vermilion = "Vermilion" + OrangeRed = "OrangeRed" + Pink = "Pink" + Crimson = "Crimson" + DarkRed = "DarkRed" + HotPink = "HotPink" + Smitten = "Smitten" + MediumPurple = "MediumPurple" + BlueViolet = "BlueViolet" + Indigo = "Indigo" + LightSkyBlue = "LightSkyBlue" + CornflowerBlue = "CornflowerBlue" + Ultramarine = "Ultramarine" + DeepSkyBlue = "DeepSkyBlue" + Azure = "Azure" + NavyBlue = "NavyBlue" + LightTurquoise = "LightTurquoise" + Aquamarine = "Aquamarine" + Turquoise = "Turquoise" + LightGreen = "LightGreen" + Lime = "Lime" + ForestGreen = "ForestGreen" diff --git a/tapo-py/tapo.pyi b/tapo-py/tapo.pyi deleted file mode 100644 index fc79f2f..0000000 --- a/tapo-py/tapo.pyi +++ /dev/null @@ -1,995 +0,0 @@ -"""Tapo API Client. - -Tested with light bulbs (L510, L520, L610) and plugs (P100, P105, P110, P115). - -Example: - ```python - import asyncio - from tapo import ApiClient - - - async def main(): - client = ApiClient("tapo-username@example.com", "tapo-password") - device = await client.l530("192.168.1.100") - - await device.on() - - if __name__ == "__main__": - asyncio.run(main()) - ``` - -See [more examples](https://github.com/mihai-dinculescu/tapo/tree/main/tapo-py/examples). -""" - -from datetime import datetime -from enum import StrEnum -from typing import Optional, List - -class ApiClient: - """Tapo API Client. - - Tested with light bulbs (L510, L520, L610) and plugs (P100, P105, P110, P115). - - Example: - ```python - import asyncio - from tapo import ApiClient - - - async def main(): - client = ApiClient("tapo-username@example.com", "tapo-password") - device = await client.l530("192.168.1.100") - - await device.on() - - if __name__ == "__main__": - asyncio.run(main()) - ``` - - See [more examples](https://github.com/mihai-dinculescu/tapo/tree/main/tapo-py/examples). - """ - - def __init__(self, tapo_username: str, tapo_password: str) -> None: - """Returns a new instance of `ApiClient`. - - Args: - tapo_username (str): The Tapo username - tapo_password (str): The Tapo password - - Returns: - ApiClient: Tapo API Client. - - Example: - ```python - import asyncio - from tapo import ApiClient - - - async def main(): - client = ApiClient("tapo-username@example.com", "tapo-password") - device = await client.l530("192.168.1.100") - - await device.on() - - if __name__ == "__main__": - asyncio.run(main()) - ``` - - See [more examples](https://github.com/mihai-dinculescu/tapo/tree/main/tapo-py/examples). - """ - async def generic_device(self, ip_address: str) -> GenericDeviceHandler: - """Specializes the given `ApiClient` into an authenticated `GenericDeviceHandler`. - - Args: - ip_address (str): The IP address of the device - - Returns: - GenericDeviceHandler: Handler for generic devices. It provides the - functionality common to all Tapo [devices](https://www.tapo.com/en/). - - Example: - ```python - client = ApiClient("tapo-username@example.com", "tapo-password") - device = await client.generic_device("192.168.1.100") - - await device.on() - ``` - """ - async def l510(self, ip_address: str) -> LightHandler: - """Specializes the given `ApiClient` into an authenticated `LightHandler`. - - Args: - ip_address (str): The IP address of the device - - Returns: - LightHandler: Handler for the [L510](https://www.tapo.com/en/search/?q=L510), [L520](https://www.tapo.com/en/search/?q=L520) and [L610](https://www.tapo.com/en/search/?q=L610) devices. - - Example: - ```python - client = ApiClient("tapo-username@example.com", "tapo-password") - device = await client.l510("192.168.1.100") - - await device.on() - ``` - """ - async def l520(self, ip_address: str) -> LightHandler: - """Specializes the given `ApiClient` into an authenticated `LightHandler`. - - Args: - ip_address (str): The IP address of the device - - Returns: - LightHandler: Handler for the [L510](https://www.tapo.com/en/search/?q=L510), [L520](https://www.tapo.com/en/search/?q=L520) and [L610](https://www.tapo.com/en/search/?q=L610) devices. - - Example: - ```python - client = ApiClient("tapo-username@example.com", "tapo-password") - device = await client.l520("192.168.1.100") - - await device.on() - ``` - """ - async def l530(self, ip_address: str) -> ColorLightHandler: - """Specializes the given `ApiClient` into an authenticated `ColorLightHandler`. - - Args: - ip_address (str): The IP address of the device - - Returns: - ColorLightHandler: Handler for the [L530](https://www.tapo.com/en/search/?q=L530), [L630](https://www.tapo.com/en/search/?q=L630) and [L900](https://www.tapo.com/en/search/?q=L900) devices. - - Example: - ```python - client = ApiClient("tapo-username@example.com", "tapo-password") - device = await client.l530("192.168.1.100") - - await device.on() - ``` - """ - async def l610(self, ip_address: str) -> LightHandler: - """Specializes the given `ApiClient` into an authenticated `LightHandler`. - - Args: - ip_address (str): The IP address of the device - - Returns: - LightHandler: Handler for the [L510](https://www.tapo.com/en/search/?q=L510), [L520](https://www.tapo.com/en/search/?q=L520) and [L610](https://www.tapo.com/en/search/?q=L610) devices. - - Example: - ```python - client = ApiClient("tapo-username@example.com", "tapo-password") - device = await client.l610("192.168.1.100") - - await device.on() - ``` - """ - async def l630(self, ip_address: str) -> ColorLightHandler: - """Specializes the given `ApiClient` into an authenticated `ColorLightHandler`. - - Args: - ip_address (str): The IP address of the device - - Returns: - ColorLightHandler: Handler for the [L530](https://www.tapo.com/en/search/?q=L530), [L630](https://www.tapo.com/en/search/?q=L630) and [L900](https://www.tapo.com/en/search/?q=L900) devices. - - Example: - ```python - client = ApiClient("tapo-username@example.com", "tapo-password") - device = await client.l630("192.168.1.100") - - await device.on() - ``` - """ - async def l900(self, ip_address: str) -> ColorLightHandler: - """Specializes the given `ApiClient` into an authenticated `ColorLightHandler`. - - Args: - ip_address (str): The IP address of the device - - Returns: - ColorLightHandler: Handler for the [L530](https://www.tapo.com/en/search/?q=L530), [L630](https://www.tapo.com/en/search/?q=L630) and [L900](https://www.tapo.com/en/search/?q=L900) devices. - - Example: - ```python - client = ApiClient("tapo-username@example.com", "tapo-password") - device = await client.l900("192.168.1.100") - - await device.on() - ``` - """ - async def p100(self, ip_address: str) -> PlugHandler: - """Specializes the given `ApiClient` into an authenticated `PlugHandler`. - - Args: - ip_address (str): The IP address of the device - - Returns: - PlugHandler: Handler for the [P100](https://www.tapo.com/en/search/?q=P100) & [P105](https://www.tapo.com/en/search/?q=P105) devices. - - Example: - ```python - client = ApiClient("tapo-username@example.com", "tapo-password") - device = await client.p100("192.168.1.100") - - await device.on() - ``` - """ - async def p105(self, ip_address: str) -> PlugHandler: - """Specializes the given `ApiClient` into an authenticated `PlugHandler`. - - Args: - ip_address (str): The IP address of the device - - Returns: - PlugHandler: Handler for the [P100](https://www.tapo.com/en/search/?q=P100) & [P105](https://www.tapo.com/en/search/?q=P105) devices. - - Example: - ```python - client = ApiClient("tapo-username@example.com", "tapo-password") - device = await client.p105("192.168.1.100") - - await device.on() - ``` - """ - async def p110(self, ip_address: str) -> PlugEnergyMonitoringHandler: - """Specializes the given `ApiClient` into an authenticated `PlugEnergyMonitoringHandler`. - - Args: - ip_address (str): The IP address of the device - - Returns: - PlugEnergyMonitoringHandler: Handler for the [P110](https://www.tapo.com/en/search/?q=P110) & [P115](https://www.tapo.com/en/search/?q=P115) devices. - - Example: - ```python - client = ApiClient("tapo-username@example.com", "tapo-password") - device = await client.p110("192.168.1.100") - - await device.on() - ``` - """ - async def p115(self, ip_address: str) -> PlugEnergyMonitoringHandler: - """Specializes the given `ApiClient` into an authenticated `PlugEnergyMonitoringHandler`. - - Args: - ip_address (str): The IP address of the device - - Returns: - PlugEnergyMonitoringHandler: Handler for the [P110](https://www.tapo.com/en/search/?q=P110) & [P115](https://www.tapo.com/en/search/?q=P115) devices. - - Example: - ```python - client = ApiClient("tapo-username@example.com", "tapo-password") - device = await client.p115("192.168.1.100") - - await device.on() - ``` - """ - -class GenericDeviceHandler: - """Handler for generic devices. It provides the functionality common to - all Tapo [devices](https://www.tapo.com/en/). - """ - - def __init__(self, handler: object): - """Private constructor. - It should not be called from outside the tapo library. - """ - async def refresh_session(self) -> None: - """Refreshes the authentication session.""" - async def on(self) -> None: - """Turns *on* the device.""" - async def off(self) -> None: - """Turns *off* the device.""" - async def get_device_info(self) -> DeviceInfoGenericResult: - """Returns *device info* as `DeviceInfoGenericResult`. - It is not guaranteed to contain all the properties returned from the Tapo API. - If the deserialization fails, or if a property that you care about it's not present, - try `GenericDeviceHandler.get_device_info_json`. - - Returns: - DeviceInfoGenericResult: Device info of a Generic Tapo device. - """ - async def get_device_info_json(self) -> dict: - """Returns *device info* as json. - It contains all the properties returned from the Tapo API. - - Returns: - dict: Device info as a dictionary. - """ - -class LightHandler: - """Handler for the [L510](https://www.tapo.com/en/search/?q=L510), [L520](https://www.tapo.com/en/search/?q=L520) and [L610](https://www.tapo.com/en/search/?q=L610) devices.""" - - def __init__(self, handler: object): - """Private constructor. - It should not be called from outside the tapo library. - """ - async def refresh_session(self) -> None: - """Refreshes the authentication session.""" - async def on(self) -> None: - """Turns *on* the device.""" - async def off(self) -> None: - """Turns *off* the device.""" - async def device_reset(self) -> None: - """*Hardware resets* the device. - - Warning: - This action will reset the device to its factory settings. - The connection to the Wi-Fi network and the Tapo app will be lost, - and the device will need to be reconfigured. - - This feature is especially useful when the device is difficult to access - and requires reconfiguration. - """ - async def get_device_info(self) -> DeviceInfoLightResult: - """Returns *device info* as `DeviceInfoLightResult`. - It is not guaranteed to contain all the properties returned from the Tapo API. - If the deserialization fails, or if a property that you care about it's not present, - try `LightHandler.get_device_info_json`. - - Returns: - DeviceInfoLightResult: Device info of Tapo L510, L520 and L610. - Superset of `GenericDeviceInfoResult`. - """ - async def get_device_info_json(self) -> dict: - """Returns *device info* as json. - It contains all the properties returned from the Tapo API. - - Returns: - dict: Device info as a dictionary. - """ - async def get_device_usage(self) -> DeviceUsageResult: - """Returns *device usage* as `DeviceUsageResult`. - - Returns: - DeviceUsageResult: Contains the time usage. - """ - async def set_brightness(self, brightness: int) -> None: - """Sets the *brightness* and turns *on* the device. - - Args: - brightness (int): between 1 and 100 - """ - -class ColorLightHandler: - """Handler for the [L530](https://www.tapo.com/en/search/?q=L530), [L630](https://www.tapo.com/en/search/?q=L630) and [L900](https://www.tapo.com/en/search/?q=L900) devices.""" - - def __init__(self, handler: object): - """Private constructor. - It should not be called from outside the tapo library. - """ - async def refresh_session(self) -> None: - """Refreshes the authentication session.""" - async def on(self) -> None: - """Turns *on* the device.""" - async def off(self) -> None: - """Turns *off* the device.""" - async def device_reset(self) -> None: - """*Hardware resets* the device. - - Warning: - This action will reset the device to its factory settings. - The connection to the Wi-Fi network and the Tapo app will be lost, - and the device will need to be reconfigured. - - This feature is especially useful when the device is difficult to access - and requires reconfiguration. - """ - async def get_device_info(self) -> DeviceInfoColorLightResult: - """Returns *device info* as `DeviceInfoColorLightResult`. - It is not guaranteed to contain all the properties returned from the Tapo API. - If the deserialization fails, or if a property that you care about it's not present, - try `ColorLightHandler.get_device_info_json`. - - Returns: - DeviceInfoColorLightResult: Device info of Tapo L530, L630 and L900. - Superset of `GenericDeviceInfoResult`. - """ - async def get_device_info_json(self) -> dict: - """Returns *device info* as json. - It contains all the properties returned from the Tapo API. - - Returns: - dict: Device info as a dictionary. - """ - async def get_device_usage(self) -> DeviceUsageResult: - """Returns *device usage* as `DeviceUsageResult`. - - Returns: - DeviceUsageResult: Contains the time usage. - """ - def set(self) -> ColorLightSetDeviceInfoParams: - """Returns a `ColorLightSetDeviceInfoParams` builder that allows - multiple properties to be set in a single request. - `ColorLightSetDeviceInfoParams.send` must be called at the end to apply the changes. - - Returns: - ColorLightSetDeviceInfoParams: Builder that is used by the - `ColorLightHandler.set` API to set multiple properties in a single request. - """ - async def set_brightness(self, brightness: int) -> None: - """Sets the *brightness* and turns *on* the device. - - Args: - brightness (int): between 1 and 100 - """ - async def set_color(self, color: Color) -> None: - """Sets the *color* and turns *on* the device. - - Args: - color (Color): one of `tapo.Color` as defined in the Google Home app. - """ - async def set_hue_saturation(self, hue: int, saturation: int) -> None: - """Sets the *hue*, *saturation* and turns *on* the device. - - Args: - hue (int): between 1 and 360 - saturation (int): between 1 and 100 - """ - async def set_color_temperature(self, color_temperature: int) -> None: - """Sets the *color temperature* and turns *on* the device. - - Args: - color_temperature (int): between 2500 and 6500 - """ - -class ColorLightSetDeviceInfoParams: - """Builder that is used by the `ColorLightHandler.set` API to set - multiple properties in a single request. - """ - - def on(self) -> ColorLightSetDeviceInfoParams: - """Turns *on* the device. - `ColorLightSetDeviceInfoParams.send` must be called at the end to apply the changes. - """ - def off(self) -> ColorLightSetDeviceInfoParams: - """Turns *off* the device. - `ColorLightSetDeviceInfoParams.send` must be called at the end to apply the changes. - """ - def brightness(self, brightness: int) -> ColorLightSetDeviceInfoParams: - """Sets the *brightness*. - `ColorLightSetDeviceInfoParams.send` must be called at the end to apply the changes. - The device will also be turned *on*, unless `ColorLightSetDeviceInfoParams.off` is called. - - Args: - brightness (int): between 1 and 100 - """ - def color(self, color: Color) -> ColorLightSetDeviceInfoParams: - """Sets the *color*. - `ColorLightSetDeviceInfoParams.send` must be called at the end to apply the changes. - The device will also be turned *on*, unless `ColorLightSetDeviceInfoParams.off` is called. - - Args: - color (Color): one of `tapo.Color` as defined in the Google Home app. - """ - def hue_saturation( - self, hue: int, saturation: int - ) -> ColorLightSetDeviceInfoParams: - """Sets the *hue* and *saturation*. - `ColorLightSetDeviceInfoParams.send` must be called at the end to apply the changes. - The device will also be turned *on*, unless `ColorLightSetDeviceInfoParams.off` is called. - - Args: - hue (int): between 1 and 360 - saturation (int): between 1 and 100 - """ - def color_temperature( - self, color_temperature: int - ) -> ColorLightSetDeviceInfoParams: - """ - Sets the *color temperature*. - `ColorLightSetDeviceInfoParams.send` must be called at the end to apply the changes. - The device will also be turned *on*, unless `ColorLightSetDeviceInfoParams.off` is called. - - Args: - color_temperature (int): between 2500 and 6500 - """ - async def send(self) -> None: - """Performs a request to apply the changes to the device.""" - -class PlugHandler: - """Handler for the [P100](https://www.tapo.com/en/search/?q=P100) & [P105](https://www.tapo.com/en/search/?q=P105) devices.""" - - def __init__(self, handler: object): - """Private constructor. - It should not be called from outside the tapo library. - """ - async def refresh_session(self) -> None: - """Refreshes the authentication session.""" - async def on(self) -> None: - """Turns *on* the device.""" - async def off(self) -> None: - """Turns *off* the device.""" - async def device_reset(self) -> None: - """*Hardware resets* the device. - - Warning: - This action will reset the device to its factory settings. - The connection to the Wi-Fi network and the Tapo app will be lost, - and the device will need to be reconfigured. - - This feature is especially useful when the device is difficult to access - and requires reconfiguration. - """ - async def get_device_info(self) -> DeviceInfoPlugResult: - """Returns *device info* as `DeviceInfoPlugResult`. - It is not guaranteed to contain all the properties returned from the Tapo API. - If the deserialization fails, or if a property that you care about it's not present, - try `PlugHandler.get_device_info_json`. - - Returns: - DeviceInfoPlugResult: Device info of Tapo P100, P105, P110 and P115. - Superset of `GenericDeviceInfoResult`. - """ - async def get_device_info_json(self) -> dict: - """Returns *device info* as json. - It contains all the properties returned from the Tapo API. - - Returns: - dict: Device info as a dictionary. - """ - async def get_device_usage(self) -> DeviceUsageResult: - """Returns *device usage* as `DeviceUsageResult`. - - Returns: - DeviceUsageResult: Contains the time usage. - """ - -class PlugEnergyMonitoringHandler: - """Handler for the [P110](https://www.tapo.com/en/search/?q=P110) & [P115](https://www.tapo.com/en/search/?q=P115) devices.""" - - def __init__(self, handler: object): - """Private constructor. - It should not be called from outside the tapo library. - """ - async def refresh_session(self) -> None: - """Refreshes the authentication session.""" - async def on(self) -> None: - """Turns *on* the device.""" - async def off(self) -> None: - """Turns *off* the device.""" - async def device_reset(self) -> None: - """*Hardware resets* the device. - - Warning: - This action will reset the device to its factory settings. - The connection to the Wi-Fi network and the Tapo app will be lost, - and the device will need to be reconfigured. - - This feature is especially useful when the device is difficult to access - and requires reconfiguration. - """ - async def get_device_info(self) -> DeviceInfoPlugResult: - """Returns *device info* as `DeviceInfoPlugResult`. - It is not guaranteed to contain all the properties returned from the Tapo API. - If the deserialization fails, or if a property that you care about it's not present, - try `PlugEnergyMonitoringHandler.get_device_info_json`. - - Returns: - DeviceInfoPlugResult: Device info of Tapo P100, P105, P110 and P115. - Superset of `GenericDeviceInfoResult`. - """ - async def get_device_info_json(self) -> dict: - """Returns *device info* as json. - It contains all the properties returned from the Tapo API. - - Returns: - dict: Device info as a dictionary. - """ - async def get_device_usage(self) -> DeviceUsageEnergyMonitoringResult: - """Returns *device usage* as `DeviceUsageResult`. - - Returns: - DeviceUsageEnergyMonitoringResult: - Contains the time usage, the power consumption, and the energy savings of the device. - """ - async def get_current_power(self) -> CurrentPowerResult: - """Returns *current power* as `CurrentPowerResult`. - - Returns: - CurrentPowerResult: Contains the current power reading of the device. - """ - async def get_energy_usage(self) -> EnergyUsageResult: - """Returns *energy usage* as `EnergyUsageResult`. - - Returns: - EnergyUsageResult: - Contains local time, current power and the energy usage and runtime for today and for the current month. - """ - async def get_energy_data( - self, - interval: EnergyDataInterval, - start_date: datetime, - end_date: datetime = None, - ) -> EnergyDataResult: - """Returns *energy data* as `EnergyDataResult`. - - Returns: - EnergyDataResult: Energy data for the requested `EnergyDataInterval`. - """ - -class DefaultStateType(StrEnum): - """The type of the default state.""" - - Custom = "custom" - LastStates = "last_states" - -class DefaultPowerType(StrEnum): - """The type of the default power state.""" - - AlwaysOn = "always_on" - LastStates = "last_states" - -class DefaultBrightnessState: - """Default brightness state.""" - - type: DefaultStateType - value: int - -class DeviceInfoGenericResult: - """Device info of a Generic Tapo device.""" - - device_id: str - type: str - model: str - hw_id: str - hw_ver: str - fw_id: str - fw_ver: str - oem_id: str - mac: str - ip: str - ssid: str - signal_level: int - rssi: int - specs: str - lang: str - device_on: Optional[bool] - on_time: Optional[int] - """The time in seconds this device has been ON since the last state change (ON/OFF).""" - overheated: bool - nickname: str - avatar: str - has_set_location_info: bool - region: Optional[str] - latitude: Optional[float] - longitude: Optional[float] - time_diff: Optional[int] - - def to_dict(self) -> dict: - """Gets all the properties of this result as a dictionary. - - Returns: - dict: The result as a dictionary. - """ - -class DeviceInfoLightResult: - """Device info of Tapo L510, L520 and L610. Superset of `GenericDeviceInfoResult`.""" - - device_id: str - type: str - model: str - hw_id: str - hw_ver: str - fw_id: str - fw_ver: str - oem_id: str - mac: str - ip: str - ssid: str - signal_level: int - rssi: int - specs: str - lang: str - device_on: bool - on_time: int - """The time in seconds this device has been ON since the last state change (ON/OFF).""" - overheated: bool - nickname: str - avatar: str - has_set_location_info: bool - region: Optional[str] - latitude: Optional[float] - longitude: Optional[float] - time_diff: Optional[int] - - # Unique to this device - brightness: int - dynamic_light_effect_enable: bool - dynamic_light_effect_id: Optional[str] - hue: Optional[int] - saturation: Optional[int] - color_temp: int - default_states: DefaultLightState - """The default state of a device to be used when internet connectivity is lost after a power cut.""" - - def to_dict(self) -> dict: - """Gets all the properties of this result as a dictionary. - - Returns: - dict: The result as a dictionary. - """ - -class DefaultLightState: - """Light Default State.""" - - brightness: DefaultBrightnessState - re_power_type: Optional[DefaultPowerType] - -class DeviceInfoColorLightResult: - """Device info of Tapo L530, L630 and L900. Superset of `GenericDeviceInfoResult`.""" - - device_id: str - type: str - model: str - hw_id: str - hw_ver: str - fw_id: str - fw_ver: str - oem_id: str - mac: str - ip: str - ssid: str - signal_level: int - rssi: int - specs: str - lang: str - device_on: bool - on_time: int - """The time in seconds this device has been ON since the last state change (ON/OFF).""" - overheated: bool - nickname: str - avatar: str - has_set_location_info: bool - region: Optional[str] - latitude: Optional[float] - longitude: Optional[float] - time_diff: Optional[int] - - # Unique to this device - brightness: int - dynamic_light_effect_enable: bool - dynamic_light_effect_id: Optional[str] - hue: Optional[int] - saturation: Optional[int] - color_temp: int - default_states: DefaultColorLightState - """The default state of a device to be used when internet connectivity is lost after a power cut.""" - - def to_dict(self) -> dict: - """Gets all the properties of this result as a dictionary. - - Returns: - dict: The result as a dictionary. - """ - -class DefaultColorLightState: - """Color Light Default State.""" - - type: DefaultStateType - state: ColorLightState - -class ColorLightState: - """Color Light State.""" - - brightness: int - hue: Optional[int] - saturation: Optional[int] - color_temp: int - -class DeviceInfoPlugResult: - """Device info of Tapo P100, P105, P110 and P115. Superset of `GenericDeviceInfoResult`.""" - - device_id: str - type: str - model: str - hw_id: str - hw_ver: str - fw_id: str - fw_ver: str - oem_id: str - mac: str - ip: str - ssid: str - signal_level: int - rssi: int - specs: str - lang: str - device_on: bool - on_time: int - """The time in seconds this device has been ON since the last state change (ON/OFF).""" - overheated: bool - nickname: str - avatar: str - has_set_location_info: bool - region: Optional[str] - latitude: Optional[float] - longitude: Optional[float] - time_diff: Optional[int] - - # Unique to this device - default_states: PlugDefaultState - """The default state of a device to be used when internet connectivity is lost after a power cut.""" - - def to_dict(self) -> dict: - """Gets all the properties of this result as a dictionary. - - Returns: - dict: The result as a dictionary. - """ - -class PlugDefaultState: - """Plug Default State.""" - - type: DefaultStateType - state: PlugState - -class PlugState: - """Plug State.""" - - on: Optional[bool] - -class UsageByPeriodResult: - """Usage by period result for today, the past 7 days, and the past 30 days.""" - - today: int - """Today.""" - past7: int - """Past 7 days.""" - past30: int - """Past 30 days.""" - -class DeviceUsageResult: - """Contains the time in use, the power consumption, and the energy savings of the device.""" - - time_usage: UsageByPeriodResult - """Time usage in minutes.""" - power_usage: UsageByPeriodResult - """Power usage in watt-hour (Wh).""" - saved_power: UsageByPeriodResult - """Saved power in watt-hour (Wh).""" - - def to_dict(self) -> dict: - """Gets all the properties of this result as a dictionary. - - Returns: - dict: The result as a dictionary. - """ - -class DeviceUsageEnergyMonitoringResult: - """Contains the time in use, the power consumption, and the energy savings of the device.""" - - time_usage: UsageByPeriodResult - """Time usage in minutes.""" - power_usage: UsageByPeriodResult - """Power usage in watt-hour (Wh).""" - saved_power: UsageByPeriodResult - """Saved power in watt-hour (Wh).""" - - def to_dict(self) -> dict: - """Gets all the properties of this result as a dictionary. - - Returns: - dict: The result as a dictionary. - """ - -class CurrentPowerResult: - """Contains the current power reading of the device.""" - - current_power: int - """Current power in watts (W).""" - - def to_dict(self) -> dict: - """Gets all the properties of this result as a dictionary. - - Returns: - dict: The result as a dictionary. - """ - -class EnergyUsageResult: - """Contains local time, current power and the energy usage and runtime for today and for the current month.""" - - local_time: datetime - """Local time of the device.""" - current_power: int - """Current power in milliwatts (mW).""" - today_runtime: int - """Today runtime in minutes.""" - today_energy: int - """Today energy usage in watts (W).""" - month_runtime: int - """Current month runtime in minutes.""" - month_energy: int - """Current month energy usage in watts (W).""" - - def to_dict(self) -> dict: - """Gets all the properties of this result as a dictionary. - - Returns: - dict: The result as a dictionary. - """ - -class EnergyDataResult: - """Energy data for the requested `EnergyDataInterval`.""" - - local_time: datetime - """Local time of the device.""" - - data: List[int] - """Energy data for the given `interval` in watts (W).""" - - start_timestamp: int - """Interval start timestamp in milliseconds.""" - - end_timestamp: int - """Interval end timestamp in milliseconds.""" - - interval: int - """Interval in minutes.""" - - def to_dict(self) -> dict: - """Gets all the properties of this result as a dictionary. - - Returns: - dict: The result as a dictionary. - """ - -class EnergyDataInterval(StrEnum): - """Energy data interval.""" - - Hourly = "Hourly" - """Hourly interval. `start_date` and `end_date` are an inclusive interval - that must not be greater than 8 days. - """ - - Daily = "Daily" - """Daily interval. `start_date` must be the first day of a quarter.""" - - Monthly = "Monthly" - """Monthly interval. `start_date` must be the first day of a year.""" - -class Color(StrEnum): - """List of preset colors as defined in the Google Home app.""" - - CoolWhite = "CoolWhite" - Daylight = "Daylight" - Ivory = "Ivory" - WarmWhite = "WarmWhite" - Incandescent = "Incandescent" - Candlelight = "Candlelight" - Snow = "Snow" - GhostWhite = "GhostWhite" - AliceBlue = "AliceBlue" - LightGoldenrod = "LightGoldenrod" - LemonChiffon = "LemonChiffon" - AntiqueWhite = "AntiqueWhite" - Gold = "Gold" - Peru = "Peru" - Chocolate = "Chocolate" - SandyBrown = "SandyBrown" - Coral = "Coral" - Pumpkin = "Pumpkin" - Tomato = "Tomato" - Vermilion = "Vermilion" - OrangeRed = "OrangeRed" - Pink = "Pink" - Crimson = "Crimson" - DarkRed = "DarkRed" - HotPink = "HotPink" - Smitten = "Smitten" - MediumPurple = "MediumPurple" - BlueViolet = "BlueViolet" - Indigo = "Indigo" - LightSkyBlue = "LightSkyBlue" - CornflowerBlue = "CornflowerBlue" - Ultramarine = "Ultramarine" - DeepSkyBlue = "DeepSkyBlue" - Azure = "Azure" - NavyBlue = "NavyBlue" - LightTurquoise = "LightTurquoise" - Aquamarine = "Aquamarine" - Turquoise = "Turquoise" - LightGreen = "LightGreen" - Lime = "Lime" - ForestGreen = "ForestGreen" diff --git a/tapo/CHANGELOG.md b/tapo/CHANGELOG.md new file mode 120000 index 0000000..83b6947 --- /dev/null +++ b/tapo/CHANGELOG.md @@ -0,0 +1 @@ +CHANGELOG.md \ No newline at end of file