1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
use std::time::Duration;
use crate::tapo_vendor::error::Error;
use crate::tapo_vendor::requests::ScheduleRule;
use crate::tapo_vendor::responses::{
DeviceInfoPlugResult, DeviceUsageResult, PowerState, ScheduleRuleResult, Timer,
};
tapo_handler! {
/// Handler for the [P100](https://www.tapo.com/en/search/?q=P100),
/// [P105](https://www.tapo.com/en/search/?q=P105), [P125](https://www.tapo.com/en/search/?q=P125),
/// [P125M](https://www.tapo.com/en/search/?q=P125M) and
/// [TP10](https://www.tapo.com/en/search/?q=TP10) devices.
PlugHandler(DeviceInfoPlugResult),
on_off,
device_usage = DeviceUsageResult,
device_management,
}
impl PlugHandler {
/// Arms the plug's countdown timer (the "Timer" feature in the
/// Tapo app), replacing any timer that is currently armed.
/// After `delay`, the plug transitions to `desired_state`.
///
/// # Arguments
///
/// * `delay` - between 1 second and 24 hours, the maximum the Tapo app allows.
/// * `desired_state` - the state the plug transitions to when the timer fires.
pub async fn set_timer(
&self,
delay: Duration,
desired_state: PowerState,
) -> Result<Timer, Error> {
self.client
.read()
.await
.set_timer(delay, desired_state)
.await
}
/// Returns the armed timer, or `None` if no timer is armed.
pub async fn get_timer(&self) -> Result<Option<Timer>, Error> {
self.client.read().await.get_timer().await
}
/// Cancels the armed timer (the "Stop" button in the Tapo app),
/// or returns successfully if no timer was armed.
pub async fn clear_timer(&self) -> Result<(), Error> {
self.client.read().await.clear_timer().await
}
/// Adds a new schedule rule to the device. Returns it as a
/// [`ScheduleRuleResult`] carrying the device-assigned `id`. Schedule rules fire on the device
/// itself, so they keep working even if the phone / Wi-Fi router / Tapo
/// cloud is offline.
///
/// # Arguments
///
/// * `rule` - the rule to add; build one with the [`ScheduleRule`]
/// builders. Any `id` it carries is ignored, because the device assigns
/// one.
///
/// The device has a fixed capacity (a P110 stores 32 rules) and returns
/// a device error once it is full.
pub async fn add_schedule_rule(&self, rule: ScheduleRule) -> Result<ScheduleRuleResult, Error> {
self.client.read().await.add_schedule_rule(rule).await
}
/// Edits an existing schedule rule, replacing it with the given one.
///
/// # Arguments
///
/// * `rule` - the replacement rule. Its `id` must be set to the id of the
/// rule to update, either from `add_schedule_rule` /
/// `get_schedule_rules` or via [`ScheduleRule::with_id`]; an unset id is
/// an `Error::Validation`, and an id the device does not know is a
/// device error.
pub async fn edit_schedule_rule(&self, rule: ScheduleRule) -> Result<(), Error> {
self.client.read().await.edit_schedule_rule(rule).await
}
/// Returns every schedule rule currently stored on the device. A rule the
/// library cannot parse is skipped rather than failing the whole listing.
pub async fn get_schedule_rules(&self) -> Result<Vec<ScheduleRuleResult>, Error> {
self.client.read().await.get_schedule_rules().await
}
/// Returns how many schedule rules the device can store in total, as
/// reported by the device itself. A P110 stores 32. Compare against the
/// length of `get_schedule_rules` to tell whether there is room for
/// another rule, because `add_schedule_rule` fails once the device is
/// full.
pub async fn get_max_schedule_rules(&self) -> Result<u32, Error> {
self.client.read().await.get_max_schedule_rules().await
}
/// Removes a single schedule rule, leaving every other rule in place.
///
/// # Arguments
///
/// * `id` - the device-assigned id of the rule to remove.
pub async fn remove_schedule_rule(&self, id: impl Into<String>) -> Result<(), Error> {
self.client
.read()
.await
.remove_schedule_rule(id.into())
.await
}
/// Removes every schedule rule from the device.
pub async fn remove_all_schedule_rules(&self) -> Result<(), Error> {
self.client.read().await.remove_all_schedule_rules().await
}
}