1#![crate_name = "eq3_max_cube_rs"]
2
3use anyhow::{anyhow, Result};
4use async_std::io::BufReader;
5use async_std::net::{TcpStream, ToSocketAddrs};
6use async_std::prelude::*;
7use log::debug;
8
9pub mod messages;
10
11use messages::{from_message_m, Device, DeviceConfig, DeviceMode, Devices, Rooms};
12use serde::Serialize;
13
14use crate::messages::from_message_l;
15
16#[derive(Debug, Serialize)]
19pub struct MaxCube {
20 #[serde(skip_serializing)]
22 stream: TcpStream,
23
24 pub rooms: Rooms,
26
27 pub devices: Devices,
29}
30
31impl MaxCube {
32 pub async fn new<A>(addr: A) -> Result<Self>
45 where
46 A: ToSocketAddrs,
47 {
48 let stream = TcpStream::connect(addr).await?;
49
50 let mut cube = MaxCube {
51 stream,
52 rooms: Rooms::new(),
53 devices: Devices::new(),
54 };
55
56 let mut reader = BufReader::new(&cube.stream);
63
64 loop {
65 let mut received = String::new();
66 reader.read_line(&mut received).await?;
67 let received = received.replace("\r\n", "");
68 debug!("{:?}", received);
69
70 if received.starts_with('L') {
71 from_message_l(&received, &mut cube.devices)?;
72 break;
73 } else if received.starts_with('M') {
74 (cube.rooms, cube.devices) = from_message_m(&received)?;
75 }
76 }
77
78 Ok(cube)
79 }
80
81 pub async fn set_temperature(&mut self, rf_address: u32, temperature: f64) -> Result<()> {
89 let mut dev_conf = DeviceConfig::new();
93
94 let mut dev_it = self.devices.iter().filter(|e| {
95 if let Device::HeaterThermostat(ts) = e {
96 ts.rf_address == rf_address
97 } else {
98 false
99 }
100 });
101
102 if let Some(dev) = dev_it.next() {
103 if let Device::HeaterThermostat(ts) = dev {
104 dev_conf = dev_conf.set_room_id(ts.room_id);
105 } else {
106 return Err(anyhow!("Device type not supported."));
107 }
108 } else {
109 return Err(anyhow!("Device with RF address {} not found.", rf_address));
110 }
111
112 let cmd = dev_conf
113 .set_address(rf_address)
114 .set_mode(DeviceMode::Manual)
115 .set_temperature(temperature)
116 .build();
117
118 self.stream.write_all(cmd.as_bytes()).await?;
119 self.stream.flush().await?;
120
121 let mut resp = "".to_string();
122 let mut reader = BufReader::new(&self.stream);
123 reader.read_line(&mut resp).await?;
124
125 let resp_code = resp
126 .split(',')
127 .into_iter()
128 .collect::<Vec<_>>()
129 .get(1)
130 .ok_or(anyhow!("Response not well-formatted."))?
131 .parse::<u8>()?;
132
133 if resp_code == 0 {
134 Ok(())
135 } else {
136 Err(anyhow!("Device configuration failed."))
137 }
138 }
139}