1use serde::{Deserialize, Serialize};
2
3use super::enums::{DeviceMode, DeviceStatus};
4
5#[derive(Debug, Clone, Serialize, Deserialize)]
7pub struct RointeDevice {
8 pub data: DeviceData,
10 pub serialnumber: Option<String>,
12 pub firmware: Option<FirmwareInfo>,
14}
15
16#[derive(Debug, Clone, Serialize, Deserialize)]
21pub struct DeviceData {
22 pub name: String,
24
25 #[serde(rename = "type")]
29 pub device_type: String,
30
31 pub product_version: Option<String>,
33
34 pub nominal_power: Option<u32>,
36
37 pub power: bool,
39
40 pub mode: DeviceMode,
42
43 pub status: DeviceStatus,
45
46 pub temp: f64,
48
49 pub temp_calc: Option<f64>,
51
52 pub temp_probe: Option<f64>,
54
55 pub comfort: f64,
57
58 pub eco: f64,
60
61 pub ice: f64,
63
64 pub ice_mode: bool,
66
67 pub schedule: Option<Vec<String>>,
74
75 pub schedule_day: Option<u8>,
77
78 pub schedule_hour: Option<u8>,
80
81 pub um_max_temp: Option<f64>,
83
84 pub um_min_temp: Option<f64>,
86
87 pub user_mode: Option<bool>,
89
90 pub last_sync_datetime_app: i64,
95
96 pub last_sync_datetime_device: Option<i64>,
98}
99
100#[derive(Debug, Clone, Serialize, Deserialize)]
102pub struct FirmwareInfo {
103 pub firmware_version_device: Option<String>,
105}
106
107#[cfg(test)]
108mod tests {
109 use super::*;
110
111 const SAMPLE_DEVICE_JSON: &str = r#"{
112 "data": {
113 "name": "Kitchen Radiator",
114 "type": "radiator",
115 "product_version": "v2",
116 "nominal_power": 1500,
117 "power": true,
118 "mode": "manual",
119 "status": "comfort",
120 "temp": 21.5,
121 "temp_calc": 21.3,
122 "temp_probe": 21.2,
123 "comfort": 21.0,
124 "eco": 18.0,
125 "ice": 8.0,
126 "ice_mode": false,
127 "schedule": [
128 "CCCCCCCCEEEEEEEEEEEEEECC",
129 "CCCCCCCCEEEEEEEEEEEEEECC",
130 "CCCCCCCCEEEEEEEEEEEEEECC",
131 "CCCCCCCCEEEEEEEEEEEEEECC",
132 "CCCCCCCCEEEEEEEEEEEEEECC",
133 "CCCCCCCCCCCCCCCCCCCCCCCC",
134 "CCCCCCCCCCCCCCCCCCCCCCCC"
135 ],
136 "schedule_day": 0,
137 "schedule_hour": 0,
138 "um_max_temp": 30.0,
139 "um_min_temp": 7.0,
140 "user_mode": false,
141 "last_sync_datetime_app": 1708360000000,
142 "last_sync_datetime_device": 1708359000000
143 },
144 "serialnumber": "ROINTE12345",
145 "firmware": {
146 "firmware_version_device": "3.2.1"
147 }
148 }"#;
149
150 #[test]
151 fn test_deserialize_full_device() {
152 let device: RointeDevice = serde_json::from_str(SAMPLE_DEVICE_JSON).unwrap();
153
154 assert_eq!(device.data.name, "Kitchen Radiator");
155 assert_eq!(device.data.device_type, "radiator");
156 assert_eq!(device.data.temp, 21.5);
157 assert_eq!(device.data.comfort, 21.0);
158 assert_eq!(device.data.eco, 18.0);
159 assert_eq!(device.data.ice, 8.0);
160 assert!(device.data.power);
161 assert!(!device.data.ice_mode);
162 assert_eq!(device.data.mode, DeviceMode::Manual);
163 assert_eq!(device.data.status, DeviceStatus::Comfort);
164
165 let schedule = device.data.schedule.unwrap();
166 assert_eq!(schedule.len(), 7);
167 assert_eq!(schedule[0], "CCCCCCCCEEEEEEEEEEEEEECC");
168
169 assert_eq!(device.serialnumber.as_deref(), Some("ROINTE12345"));
170 let fw = device.firmware.unwrap();
171 assert_eq!(fw.firmware_version_device.as_deref(), Some("3.2.1"));
172 }
173
174 #[test]
175 fn test_deserialize_device_status_none() {
176 let json = r#"{
177 "data": {
178 "name": "Bedroom",
179 "type": "radiator",
180 "power": true,
181 "mode": "manual",
182 "status": "none",
183 "temp": 20.0,
184 "comfort": 21.0,
185 "eco": 18.0,
186 "ice": 8.0,
187 "ice_mode": false,
188 "last_sync_datetime_app": 1708360000000
189 }
190 }"#;
191
192 let device: RointeDevice = serde_json::from_str(json).unwrap();
193 assert_eq!(device.data.status, DeviceStatus::NoStatus);
194 }
195
196 #[test]
197 fn test_deserialize_auto_mode() {
198 let json = r#"{
199 "data": {
200 "name": "Hall",
201 "type": "radiator",
202 "power": true,
203 "mode": "auto",
204 "status": "eco",
205 "temp": 18.0,
206 "comfort": 21.0,
207 "eco": 18.0,
208 "ice": 8.0,
209 "ice_mode": false,
210 "last_sync_datetime_app": 1708360000000
211 }
212 }"#;
213
214 let device: RointeDevice = serde_json::from_str(json).unwrap();
215 assert_eq!(device.data.mode, DeviceMode::Auto);
216 }
217}