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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
mod client;
mod error;
use client::Client;
pub use error::Error;
use serde::{Deserialize, Deserializer};
fn deserialize_temperature<'de, D>(deserializer: D) -> Result<f64, D::Error>
where
D: Deserializer<'de>,
{
let val = f64::deserialize(deserializer)?;
Ok(val / 10.0)
}
fn deserialize_optional_temperature<'de, D>(deserializer: D) -> Result<Option<f64>, D::Error>
where
D: Deserializer<'de>,
{
let val = Option::<f64>::deserialize(deserializer)?;
Ok(val.map(|v| v / 10.0))
}
#[derive(Debug, Deserialize, PartialEq, Eq)]
pub enum State {
On,
Off,
}
#[derive(Debug, Deserialize, PartialEq, Eq)]
pub enum Mode {
Auto,
}
#[derive(Debug, Deserialize, PartialEq, Eq)]
pub enum DemandType {
Modulating,
}
#[derive(Debug, Deserialize, PartialEq, Eq)]
pub enum ControlType {
FromSchedule,
FromBoost,
FromManualOverride,
}
pub struct Hub {
client: Client,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct RoomStat {
#[serde(rename = "id")]
pub id: usize,
#[serde(deserialize_with = "deserialize_temperature")]
pub set_point: f64,
#[serde(deserialize_with = "deserialize_temperature")]
pub measured_temperature: f64,
pub measured_humidity: f64,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct Room {
#[serde(rename = "id")]
pub id: usize,
#[serde(default, deserialize_with = "deserialize_optional_temperature")]
pub manual_set_point: Option<f64>,
pub schedule_id: usize,
pub comfort_mode_score: u32,
pub heating_rate: u32,
pub room_stat_id: usize,
pub name: String,
pub mode: Mode,
pub demand_type: DemandType,
pub window_detection_active: bool,
#[serde(deserialize_with = "deserialize_temperature")]
pub calculated_temperature: f64,
#[serde(deserialize_with = "deserialize_temperature")]
pub current_set_point: f64,
pub percentage_demand: u8,
pub control_output_state: State,
pub setpoint_origin: ControlType,
#[serde(deserialize_with = "deserialize_temperature")]
pub displayed_set_point: f64,
#[serde(deserialize_with = "deserialize_temperature")]
pub scheduled_set_point: f64,
pub away_mode_suppressed: bool,
#[serde(deserialize_with = "deserialize_temperature")]
pub rounded_alexa_temperature: f64,
pub effective_mode: Mode,
pub percentage_demand_for_itrv: u8,
pub control_direction: String,
pub heating_type: String,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct HotWater {
#[serde(rename = "id")]
pub id: usize,
pub override_water_heating_state: State,
pub schedule_id: usize,
pub mode: String,
pub water_heating_state: State,
pub scheduled_water_heating_state: State,
pub hot_water_relay_state: State,
pub hot_water_description: ControlType,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct HeatingChannel {
#[serde(rename = "id")]
pub id: usize,
pub name: String,
pub room_ids: Vec<usize>,
pub percentage_demand: u8,
pub demand_on_off_output: State,
pub heating_relay_state: State,
pub is_smart_valve_preventing_demand: bool,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct Domain {
#[serde(rename = "HeatingChannel")]
pub heating_channels: Vec<HeatingChannel>,
pub hot_water: Vec<HotWater>,
#[serde(rename = "Room")]
pub rooms: Vec<Room>,
#[serde(rename = "RoomStat")]
pub room_stats: Vec<RoomStat>,
}
impl Hub {
pub fn new(host: &str, secret: &str) -> Self {
Self {
client: Client::new(host, secret),
}
}
pub async fn domain(&self) -> Result<Domain, Error> {
self.client.get("/domain/").await
}
}