-
-
Notifications
You must be signed in to change notification settings - Fork 44
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
tapo-py: Add full support for the KE100 TRV
Addresses #128.
- Loading branch information
1 parent
29e3674
commit 80deac8
Showing
15 changed files
with
343 additions
and
86 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
"""KE100 TRV Example""" | ||
|
||
import asyncio | ||
import os | ||
|
||
from tapo import ApiClient | ||
from tapo.requests import TemperatureUnitKE100 | ||
|
||
|
||
async def main(): | ||
tapo_username = os.getenv("TAPO_USERNAME") | ||
tapo_password = os.getenv("TAPO_PASSWORD") | ||
ip_address = os.getenv("IP_ADDRESS") | ||
# Name of the KE100 device. | ||
# Can be obtained from the Tapo App or by executing `get_child_device_component_list()` on the hub device. | ||
device_name = os.getenv("DEVICE_NAME") | ||
target_temperature = int(os.getenv("TARGET_TEMPERATURE")) | ||
|
||
client = ApiClient(tapo_username, tapo_password) | ||
hub = await client.h100(ip_address) | ||
|
||
# Get a handler for the child device | ||
device = await hub.ke100(nickname=device_name) | ||
|
||
# Get the device info of the child device | ||
device_info = await device.get_device_info() | ||
print(f"Device info: {device_info.to_dict()}") | ||
|
||
# Set target temperature. | ||
# KE100 currently only supports Celsius as temperature unit. | ||
print(f"Setting target temperature to {target_temperature} degrees Celsius...") | ||
await device.set_target_temperature(target_temperature, TemperatureUnitKE100.Celsius) | ||
|
||
# Get the device info of the child device | ||
device_info = await device.get_device_info() | ||
print(f"Device info: {device_info.to_dict()}") | ||
|
||
|
||
if __name__ == "__main__": | ||
asyncio.run(main()) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
use std::{ops::Deref, sync::Arc}; | ||
|
||
use pyo3::{prelude::*, types::PyDict}; | ||
use tapo::responses::{KE100Result, TemperatureUnitKE100}; | ||
use tapo::KE100Handler; | ||
|
||
use crate::call_handler_method; | ||
|
||
#[derive(Clone)] | ||
#[pyclass(name = "KE100Handler")] | ||
pub struct PyKE100Handler { | ||
handler: Arc<KE100Handler>, | ||
} | ||
|
||
impl PyKE100Handler { | ||
pub fn new(handler: KE100Handler) -> Self { | ||
Self { | ||
handler: Arc::new(handler), | ||
} | ||
} | ||
} | ||
|
||
#[pymethods] | ||
impl PyKE100Handler { | ||
pub async fn get_device_info(&self) -> PyResult<KE100Result> { | ||
let handler = self.handler.clone(); | ||
call_handler_method!(handler.deref(), KE100Handler::get_device_info) | ||
} | ||
|
||
pub async fn get_device_info_json(&self) -> PyResult<Py<PyDict>> { | ||
let handler = self.handler.clone(); | ||
let result = call_handler_method!(handler.deref(), KE100Handler::get_device_info_json)?; | ||
Python::with_gil(|py| tapo::python::serde_object_to_py_dict(py, &result)) | ||
} | ||
|
||
pub async fn set_child_protection(&self, on: bool) -> PyResult<()> { | ||
let handler = self.handler.clone(); | ||
call_handler_method!(handler.deref(), KE100Handler::set_child_protection, on) | ||
} | ||
|
||
pub async fn set_frost_protection(&self, on: bool) -> PyResult<()> { | ||
let handler = self.handler.clone(); | ||
call_handler_method!(handler.deref(), KE100Handler::set_frost_protection, on) | ||
} | ||
|
||
pub async fn set_max_control_temperature( | ||
&self, | ||
value: u8, | ||
unit: TemperatureUnitKE100, | ||
) -> PyResult<()> { | ||
let handler = self.handler.clone(); | ||
call_handler_method!( | ||
handler.deref(), | ||
KE100Handler::set_max_control_temperature, | ||
value, | ||
unit | ||
) | ||
} | ||
|
||
pub async fn set_min_control_temperature( | ||
&self, | ||
value: u8, | ||
unit: TemperatureUnitKE100, | ||
) -> PyResult<()> { | ||
let handler = self.handler.clone(); | ||
call_handler_method!( | ||
handler.deref(), | ||
KE100Handler::set_min_control_temperature, | ||
value, | ||
unit | ||
) | ||
} | ||
|
||
pub async fn set_target_temperature( | ||
&self, | ||
value: u8, | ||
unit: TemperatureUnitKE100, | ||
) -> PyResult<()> { | ||
let handler = self.handler.clone(); | ||
call_handler_method!( | ||
handler.deref(), | ||
KE100Handler::set_target_temperature, | ||
value, | ||
unit | ||
) | ||
} | ||
|
||
pub async fn set_temperature_offset( | ||
&self, | ||
value: i8, | ||
unit: TemperatureUnitKE100, | ||
) -> PyResult<()> { | ||
let handler = self.handler.clone(); | ||
call_handler_method!( | ||
handler.deref(), | ||
KE100Handler::set_temperature_offset, | ||
value, | ||
unit | ||
) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,7 +9,7 @@ from tapo.responses import ( | |
T300Result, | ||
T31XResult, | ||
) | ||
from tapo import S200BHandler, T100Handler, T110Handler, T300Handler, T31XHandler | ||
from tapo import KE100Handler, S200BHandler, T100Handler, T110Handler, T300Handler, T31XHandler | ||
|
||
class HubHandler: | ||
"""Handler for the [H100](https://www.tapo.com/en/search/?q=H100) hubs.""" | ||
|
@@ -72,6 +72,33 @@ class HubHandler: | |
dict: Device info as a dictionary. | ||
""" | ||
|
||
async def ke100( | ||
self, device_id: Optional[str] = None, nickname: Optional[str] = None | ||
) -> KE100Handler: | ||
"""Returns a `KE100Handler` for the device matching the provided `device_id` or `nickname`. | ||
Args: | ||
device_id (Optional[str]): The Device ID of the device | ||
nickname (Optional[str]): The Nickname of the device | ||
Returns: | ||
KE100Handler: Handler for the [KE100](https://www.tp-link.com/en/search/?q=KE100) devices. | ||
Example: | ||
```python | ||
# Connect to the hub | ||
client = ApiClient("[email protected]", "tapo-password") | ||
hub = await client.h100("192.168.1.100") | ||
# Get a handler for the child device | ||
device = await hub.ke100(device_id="0000000000000000000000000000000000000000") | ||
# Get the device info of the child device | ||
device_info = await device.get_device_info() | ||
print(f"Device info: {device_info.to_dict()}") | ||
``` | ||
""" | ||
|
||
async def s200b( | ||
self, device_id: Optional[str] = None, nickname: Optional[str] = None | ||
) -> S200BHandler: | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
from tapo.requests import TemperatureUnitKE100 | ||
from tapo.responses import KE100Result | ||
|
||
class KE100Handler: | ||
"""Handler for the [KE100](https://www.tp-link.com/en/search/?q=KE100) devices.""" | ||
|
||
async def get_device_info(self) -> KE100Result: | ||
"""Returns *device info* as `KE100Result`. | ||
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 `KE100Handler.get_device_info_json`. | ||
Returns: | ||
KE100Result: Device info of Tapo KE100 thermostatic radiator valve (TRV). | ||
""" | ||
|
||
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 set_child_protection(self, on: bool) -> None: | ||
"""Sets *child protection* on the device to *on* or *off*. | ||
Args: | ||
on (bool) | ||
""" | ||
|
||
async def set_frost_protection(self, on: bool) -> None: | ||
"""Sets *frost protection* on the device to *on* or *off*. | ||
Args: | ||
on (bool) | ||
""" | ||
|
||
async def set_max_control_temperature(self, value: int, unit: TemperatureUnitKE100) -> None: | ||
"""Sets the *maximum control temperature*. | ||
Args: | ||
value (int) | ||
unit (TemperatureUnitKE100) | ||
""" | ||
|
||
async def set_min_control_temperature(self, value: int, unit: TemperatureUnitKE100) -> None: | ||
"""Sets the *minimum control temperature*. | ||
Args: | ||
value (int) | ||
unit (TemperatureUnitKE100) | ||
""" | ||
|
||
async def set_target_temperature(self, value: int, unit: TemperatureUnitKE100) -> None: | ||
"""Sets the *target temperature*. | ||
Args: | ||
value (int): between `min_control_temperature` and `max_control_temperature` | ||
unit (TemperatureUnitKE100) | ||
""" | ||
|
||
async def set_temperature_offset(self, value: int, unit: TemperatureUnitKE100) -> None: | ||
"""Sets the *temperature offset*. | ||
Args: | ||
value (int): between -10 and 10 | ||
unit (TemperatureUnitKE100) | ||
""" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,6 @@ | ||
from .color import * | ||
from .energy_data_interval import * | ||
from .set_device_info import * | ||
from tapo.responses import ( | ||
TemperatureUnitKE100 as TemperatureUnitKE100, | ||
) |
Oops, something went wrong.