diff --git a/smart-house/src/bin/mocks_example.rs b/smart-house/src/bin/mocks_example.rs index ea7447d..0d5a475 100644 --- a/smart-house/src/bin/mocks_example.rs +++ b/smart-house/src/bin/mocks_example.rs @@ -7,7 +7,7 @@ fn main() -> Result<(), Box> { let dev = house.get_room_mut("Main").unwrap().get_device_mut("PSocA").unwrap(); if let Device::PowerSocket(psoc) = dev { - psoc.set_on(!psoc.is_on()); + psoc.set_on(!psoc.is_on().unwrap()).unwrap(); } house.print_status(); diff --git a/smart-house/src/bin/power_socket_client.rs b/smart-house/src/bin/power_socket_client.rs index a9dc184..ecfed6b 100644 --- a/smart-house/src/bin/power_socket_client.rs +++ b/smart-house/src/bin/power_socket_client.rs @@ -10,7 +10,7 @@ fn main() -> Result<(), Box> { println!("{}", power_socket.display()); std::thread::sleep(Duration::from_secs(2)); - power_socket.set_on(!power_socket.is_on()); + power_socket.set_on(!power_socket.is_on().unwrap()).unwrap(); println!("{}", power_socket0.display()); println!("{}", power_socket.display()); diff --git a/smart-house/src/bin/stubs_example.rs b/smart-house/src/bin/stubs_example.rs index e168f12..b19e242 100644 --- a/smart-house/src/bin/stubs_example.rs +++ b/smart-house/src/bin/stubs_example.rs @@ -60,7 +60,7 @@ fn switch_off_power_socket_in_hall_demo(house: &mut House) { println!("FAILED!"); return; }; - power_socket.set_on(false); + power_socket.set_on(false).unwrap(); println!("SUCCESS"); house.print_status(); } diff --git a/smart-house/src/house.rs b/smart-house/src/house.rs index cf96164..a619e7c 100644 --- a/smart-house/src/house.rs +++ b/smart-house/src/house.rs @@ -108,7 +108,7 @@ mod tests { let Device::PowerSocket(powers_socket) = house.get_room_mut("main").unwrap().get_device_mut("PSocA").unwrap() else { unreachable!() }; - powers_socket.set_on(true); + powers_socket.set_on(true).unwrap(); assert_eq!( format!("{}", house.get_room("main").unwrap().get_device("PSocA").unwrap().display()), diff --git a/smart-house/src/power_socket.rs b/smart-house/src/power_socket.rs index 3a4dd4e..4de6436 100644 --- a/smart-house/src/power_socket.rs +++ b/smart-house/src/power_socket.rs @@ -1,6 +1,5 @@ use std::cell::RefCell; use std::fmt::{Debug, Display}; -use std::io; use std::io::{Read, Write}; use std::net::{SocketAddr, TcpStream}; use std::time::Duration; @@ -17,35 +16,50 @@ impl PowerSocket { } } - pub fn connect(addr: &str) -> Result { + pub fn connect(addr: &str) -> Result { let handle = PowerSocketClient::new(addr)?; Ok(Self { handle: Box::new(handle) }) } - pub fn is_on(&self) -> bool { + pub fn is_on(&self) -> Result { self.handle.is_on() } - pub fn set_on(&mut self, on: bool) { + pub fn set_on(&mut self, on: bool) -> Result<(), std::io::Error> { self.handle.set_on(on) } - pub fn get_power(&self) -> f32 { + pub fn get_power(&self) -> Result { self.handle.get_power() } pub fn display(&self) -> impl Display { - let state = if self.is_on() { "ON" } else { "OFF" }; - format!("PowerSocket[ {} : {:02.1} ]", state, self.get_power()) + const ERR: &str = "PowerSocket[ ERR ]"; + let power = match self.get_power() { + Ok(power) => power, + Err(e) => { + eprintln!("error on get power: {:?}", e); + return ERR.to_string(); + } + }; + let on = match self.is_on() { + Ok(state) => state, + Err(e) => { + eprintln!("error on get state: {:?}", e); + return ERR.to_string(); + } + }; + let state = if on { "ON" } else { "OFF" }; + format!("PowerSocket[ {} : {:02.1} ]", state, power) } } trait PowerSocketHandle: Debug { - fn is_on(&self) -> bool; + fn is_on(&self) -> Result; - fn set_on(&mut self, on: bool); + fn set_on(&mut self, on: bool) -> Result<(), std::io::Error>; - fn get_power(&self) -> f32; + fn get_power(&self) -> Result; } #[derive(Debug)] @@ -61,16 +75,17 @@ impl PowerSocketStub { } impl PowerSocketHandle for PowerSocketStub { - fn is_on(&self) -> bool { - self.on + fn is_on(&self) -> Result { + Ok(self.on) } - fn set_on(&mut self, on: bool) { - self.on = on + fn set_on(&mut self, on: bool) -> Result<(), std::io::Error> { + self.on = on; + Ok(()) } - fn get_power(&self) -> f32 { - if self.on { self.power_rate } else { 0.0 } + fn get_power(&self) -> Result { + Ok(if self.on { self.power_rate } else { 0.0 }) } } @@ -82,8 +97,8 @@ struct PowerSocketClient { } impl PowerSocketClient { - fn new(addr: &str) -> Result { - let addr: SocketAddr = addr.parse().map_err(io::Error::other)?; + fn new(addr: &str) -> Result { + let addr: SocketAddr = addr.parse().map_err(std::io::Error::other)?; let stream = TcpStream::connect_timeout(&addr, TIMEOUT)?; stream.set_write_timeout(Some(TIMEOUT))?; stream.set_read_timeout(Some(TIMEOUT))?; @@ -97,28 +112,44 @@ const CMD_TURN_OFF: u8 = 3; const CMD_GET_POWER: u8 = 4; impl PowerSocketHandle for PowerSocketClient { - fn is_on(&self) -> bool { + fn is_on(&self) -> Result { let mut buf = [CMD_GET_ON; 1]; - self.stream.borrow_mut().write_all(&buf).expect("CMD_GET_ON request should be sent"); - self.stream.borrow_mut().read_exact(&mut buf).expect("CMD_GET_ON response should be received"); - !matches!(buf, [0]) - } - - fn set_on(&mut self, on: bool) { - let cmd = if on { CMD_TURN_ON } else { CMD_TURN_OFF }; - let mut buf = [cmd; 1]; - self.stream.borrow_mut().write_all(&buf).expect("change state request should be sent"); - self.stream.borrow_mut().read_exact(&mut buf).expect("change state response should be received"); - } - - fn get_power(&self) -> f32 { - let mut buf = [CMD_GET_POWER; 4]; - self.stream.borrow_mut().write_all(&buf[0..1]).expect("CMD_GET_POWER request should be sent"); + self.stream + .borrow_mut() + .write_all(&buf) + .map_err(|e| std::io::Error::other(format!("CMD_GET_ON request error: {:?}", e)))?; self.stream .borrow_mut() .read_exact(&mut buf) - .expect("CMD_GET_POWER response should be received"); - f32::from_le_bytes(buf) + .map_err(|e| std::io::Error::other(format!("CMD_GET_ON response error: {:?}", e)))?; + Ok(!matches!(buf, [0])) + } + + fn set_on(&mut self, on: bool) -> Result<(), std::io::Error> { + let cmd = if on { CMD_TURN_ON } else { CMD_TURN_OFF }; + let mut buf = [cmd; 1]; + self.stream + .borrow_mut() + .write_all(&buf) + .map_err(|e| std::io::Error::other(format!("change state request error: {:?}", e)))?; + self.stream + .borrow_mut() + .read_exact(&mut buf) + .map_err(|e| std::io::Error::other(format!("change state response error: {:?}", e)))?; + Ok(()) + } + + fn get_power(&self) -> Result { + let mut buf = [CMD_GET_POWER; 4]; + self.stream + .borrow_mut() + .write_all(&buf[0..1]) + .map_err(|e| std::io::Error::other(format!("CMD_GET_POWER request error: {:?}", e)))?; + self.stream + .borrow_mut() + .read_exact(&mut buf) + .map_err(|e| std::io::Error::other(format!("CMD_GET_POWER response error: {:?}", e)))?; + Ok(f32::from_le_bytes(buf)) } } @@ -129,12 +160,12 @@ mod tests { #[test] fn smoke_test() { let mut power_socket = PowerSocket::stub(12.4, false); - assert!(!power_socket.is_on()); - assert_eq!(power_socket.get_power(), 0.0); + assert!(!power_socket.is_on().unwrap()); + assert_eq!(power_socket.get_power().unwrap(), 0.0); - power_socket.set_on(true); - assert!(power_socket.is_on()); - assert_eq!(power_socket.get_power(), 12.4); + power_socket.set_on(true).unwrap(); + assert!(power_socket.is_on().unwrap()); + assert_eq!(power_socket.get_power().unwrap(), 12.4); } #[test] diff --git a/smart-house/src/room.rs b/smart-house/src/room.rs index 735899f..38efac2 100644 --- a/smart-house/src/room.rs +++ b/smart-house/src/room.rs @@ -70,7 +70,7 @@ mod tests { let Device::PowerSocket(power_socket) = room.get_device_mut("PSoc").unwrap() else { unreachable!() }; - power_socket.set_on(true); + power_socket.set_on(true).unwrap(); assert_eq!(format!("{}", room.get_device("PSoc").unwrap().display()), "DEV:PowerSocket[ ON : 12.3 ]"); assert_eq!(format!("{}", room.get_device("Therm").unwrap().display()), "DEV:Thermometer[ 21.6 ]"); @@ -92,7 +92,7 @@ mod tests { let Some(Device::Thermometer(removed)) = room.remove_device("Therm") else { unreachable!() }; - assert_eq!(removed.get_temperature(), 21.56); + assert_eq!(removed.get_temperature().unwrap(), 21.56); assert_eq!(room.devices.len(), 2); } } diff --git a/smart-house/src/thermometer.rs b/smart-house/src/thermometer.rs index 1f69d58..b2097fa 100644 --- a/smart-house/src/thermometer.rs +++ b/smart-house/src/thermometer.rs @@ -21,17 +21,24 @@ impl Thermometer { Ok(Self { handle: Box::new(handle) }) } - pub fn get_temperature(&self) -> f32 { + pub fn get_temperature(&self) -> Result { self.handle.get_temperature() } pub fn display(&self) -> impl Display { - format!("Thermometer[ {:02.1} ]", self.get_temperature()) + let output = self.get_temperature(); + match output { + Ok(v) => format!("Thermometer[ {:02.1} ]", v), + Err(e) => { + eprintln!("error fetching temperature: {:?}", e); + "Thermometer[ ERR ]".to_string() + } + } } } trait ThermometerHandle: Debug { - fn get_temperature(&self) -> f32; + fn get_temperature(&self) -> Result; } #[derive(Debug)] @@ -46,8 +53,8 @@ impl ThermometerHandleStub { } impl ThermometerHandle for ThermometerHandleStub { - fn get_temperature(&self) -> f32 { - self.temperature + fn get_temperature(&self) -> Result { + Ok(self.temperature) } } @@ -91,8 +98,8 @@ impl ThermometerClient { } impl ThermometerHandle for ThermometerClient { - fn get_temperature(&self) -> f32 { - f32::from_le_bytes(self.value.load(Ordering::Relaxed).to_le_bytes()) + fn get_temperature(&self) -> Result { + Ok(f32::from_le_bytes(self.value.load(Ordering::Relaxed).to_le_bytes())) } } @@ -103,7 +110,7 @@ mod tests { #[test] fn smoke_test() { let thermometer = Thermometer::stub(20.0); - assert_eq!(thermometer.get_temperature(), 20.0); + assert_eq!(thermometer.get_temperature().unwrap(), 20.0); } #[test]