From ce5152e4d4140912da370c47d247b667e565758d Mon Sep 17 00:00:00 2001 From: Andrzej Klajnert Date: Sun, 27 Sep 2020 18:54:14 +0200 Subject: [PATCH] Define errors, raise errors in `new()` instead just `unwrap()`. --- Cargo.toml | 4 ++- src/lib.rs | 84 ++++++++++++++++++++++++++++++++++++++++-------------- 2 files changed, 65 insertions(+), 23 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 821bfce..08342c1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,4 +7,6 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -btleplug = "0.5.1" \ No newline at end of file +btleplug = "0.5.1" +failure = "0.1.8" +failure_derive = "0.1.8" \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index d358543..eda396c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,9 @@ extern crate btleplug; +extern crate failure; +#[macro_use] +extern crate failure_derive; -use btleplug::api::{Central, Characteristic, Peripheral, UUID}; +use btleplug::api::{BDAddr, Central, Characteristic, Peripheral, UUID}; #[cfg(target_os = "linux")] use btleplug::bluez::{ adapter::ConnectedAdapter, manager::Manager, peripheral::Peripheral as PeripheralStruct, @@ -63,52 +66,89 @@ pub fn bytes_to_tenth_milimeters(bytes: &[u8]) -> i16 { } pub struct Idasen { + pub mac_addr: BDAddr, desk: PeripheralStruct, control_characteristic: Characteristic, position_characteristic: Characteristic, } +#[derive(Debug, Fail)] pub enum Error { + #[fail(display = "Cannot find the device.")] + CannotFindDevice, + + #[fail(display = "Cannot connect to the device.")] + ConnectionFailed, + + #[fail(display = "Bluetooth characteristics not found: '{}'.", characteristic)] + CharacteristicsNotFound { characteristic: String }, + + #[fail(display = "Desired position has to be between MIN_HEIGHT and MAX_HEIGHT.")] PositionNotInRange, } impl Idasen { - pub fn new() -> Self { + pub fn new() -> Result { let manager = Manager::new().unwrap(); let central = get_central(&manager); central.start_scan().unwrap(); - thread::sleep(Duration::from_secs(2)); - - let desk = central - .peripherals() - .into_iter() - .find(|p| { - p.properties() - .local_name - .iter() - .any(|name| name.contains("Desk")) - }) - .unwrap(); - desk.connect().unwrap(); + let desk = Idasen::find_desk(central); + if desk.is_none() { + return Err(Error::CannotFindDevice); + } + let desk = desk.unwrap(); + if desk.connect().is_err() { + return Err(Error::ConnectionFailed); + } + let mac_addr = desk.address(); let characteristics = desk.discover_characteristics().unwrap(); + let control_characteristic = characteristics .iter() - .find(|characteristic| characteristic.uuid == CONTROL_UUID) - .unwrap() - .clone(); + .find(|characteristic| characteristic.uuid == CONTROL_UUID); + if control_characteristic.is_none() { + return Err(Error::CharacteristicsNotFound { + characteristic: "Control".to_string(), + }); + } + let control_characteristic = control_characteristic.unwrap().clone(); + let position_characteristic = characteristics .iter() - .find(|characteristics| characteristics.uuid == POSITION_UUID) - .unwrap() - .clone(); + .find(|characteristics| characteristics.uuid == POSITION_UUID); + if position_characteristic.is_none() { + return Err(Error::CharacteristicsNotFound { + characteristic: "Control".to_string(), + }); + } + let position_characteristic = position_characteristic.unwrap().clone(); - Self { + Ok(Self { desk, + mac_addr, control_characteristic, position_characteristic, + }) + } + + fn find_desk(central: Adapter) -> Option { + let mut attempt = 0; + while attempt < 120 { + let desk = central.peripherals().into_iter().find(|p| { + p.properties() + .local_name + .iter() + .any(|name| name.contains("Desk")) + }); + if desk.is_some() { + return desk; + } + attempt += 1; + thread::sleep(Duration::from_millis(50)); } + None } /// Move desk up.