Skip to content

Commit

Permalink
Finished move_to() method, add some docstrings
Browse files Browse the repository at this point in the history
  • Loading branch information
aklajnert committed Sep 27, 2020
1 parent 976faa9 commit 0590f57
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 42 deletions.
3 changes: 1 addition & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,4 @@ edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
#btleplug = "0.5.1"
btleplug = { path = "../btleplug" }
btleplug = "0.5.1"
114 changes: 74 additions & 40 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use btleplug::corebluetooth::{
use btleplug::winrtble::{
adapter::Adapter, manager::Manager, peripheral::Peripheral as PeripheralStruct,
};
use std::cmp::{max, min, Ordering};
use std::thread;
use std::time::Duration;

Expand All @@ -22,59 +23,53 @@ use std::time::Duration;
#[cfg(any(target_os = "windows", target_os = "macos"))]
fn get_central(manager: &Manager) -> Adapter {
let adapters = manager.adapters().unwrap();
adapters.into_iter().nth(0).unwrap()
adapters.into_iter().next().unwrap()
}

#[cfg(target_os = "linux")]
fn get_central(manager: &Manager) -> ConnectedAdapter {
let adapters = manager.adapters().unwrap();
let adapter = adapters.into_iter().nth(0).unwrap();
let adapter = adapters.into_iter().next().unwrap();
adapter.connect().unwrap()
}

#[cfg(any(target_os = "windows", target_os = "macos"))]
type BtCentral = Adapter;

#[cfg(target_os = "linux")]
type BtCentral = ConnectedAdapter;

const CONTROL_UUID: UUID = UUID::B128([
0x8a, 0xf7, 0x15, 0x02, 0x9c, 0x00, 0x49, 0x8a, 0x24, 0x10, 0x8a, 0x33, 0x02, 0x00, 0xfa, 0x99,
]);

const STATUS_UUID: UUID = UUID::B128([
0x8a, 0xf7, 0x15, 0x02, 0x9c, 0x00, 0x49, 0x8a, 0x24, 0x10, 0x8a, 0x33, 0x21, 0x00, 0xfa, 0x99,
]);
const POSITION_UUID: UUID = UUID::B128([
0x8a, 0xf7, 0x15, 0x02, 0x9c, 0x00, 0x49, 0x8a, 0x24, 0x10, 0x8a, 0x33, 0x20, 0x00, 0xfa, 0x99,
0x8a, 0xf7, 0x15, 0x02, 0x9c, 0x00, 0x49, 0x8a, 0x24, 0x10, 0x8a, 0x33, 0x21, 0x00, 0xfa, 0x99,
]);

const UP: [u8; 2] = [0x47, 0x00];
const DOWN: [u8; 2] = [0x46, 0x00];
const STOP: [u8; 2] = [0xFF, 0x00];

pub const MIN_HEIGHT: f32 = 0.62;
pub const MAX_HEIGHT: f32 = 1.27;
pub const MIN_HEIGHT: i16 = 6200;
pub const MAX_HEIGHT: i16 = 12700;

/// convert desk response from bytes to meters
///
/// ```
/// assert_eq!(idasen::bytes_to_meters(&[0x64, 0x19, 0x00, 0x00]), idasen::MAX_HEIGHT);
/// assert_eq!(idasen::bytes_to_meters(&[0x00, 0x00, 0x00, 0x00]), idasen::MIN_HEIGHT);
/// assert_eq!(idasen::bytes_to_meters(&[0x51, 0x04, 0x00, 0x00]), 0.7305);
/// assert_eq!(idasen::bytes_to_meters(&[0x08, 0x08, 0x00, 0x00]), 0.8256);
/// assert_eq!(idasen::bytes_to_tenth_milimeters(&[0x64, 0x19, 0x00, 0x00]), idasen::MAX_HEIGHT);
/// assert_eq!(idasen::bytes_to_tenth_milimeters(&[0x00, 0x00, 0x00, 0x00]), idasen::MIN_HEIGHT);
/// assert_eq!(idasen::bytes_to_tenth_milimeters(&[0x51, 0x04, 0x00, 0x00]), 7305);
/// assert_eq!(idasen::bytes_to_tenth_milimeters(&[0x08, 0x08, 0x00, 0x00]), 8256);
/// assert_eq!(idasen::bytes_to_tenth_milimeters(&[0x64, 0x18, 0x00, 0x00]), 12444);
/// ```
pub fn bytes_to_meters(bytes: &[u8]) -> f32 {
let as_int = ((bytes[1] as u32) << 8) + bytes[0] as u32;
(as_int as f32 / 10000.0) + MIN_HEIGHT
pub fn bytes_to_tenth_milimeters(bytes: &[u8]) -> i16 {
let as_int = ((bytes[1] as i16) << 8) + bytes[0] as i16;
as_int + MIN_HEIGHT
}

pub struct Idasen {
manager: Manager,
central: BtCentral,
desk: PeripheralStruct,
control_characteristic: Characteristic,
status_characteristic: Characteristic,
position_characteristic: Characteristic,
}

pub enum Error {
PositionNotInRange,
}

impl Idasen {
Expand Down Expand Up @@ -103,37 +98,76 @@ impl Idasen {
.find(|characteristic| characteristic.uuid == CONTROL_UUID)
.unwrap()
.clone();
let status_characteristic = characteristics
let position_characteristic = characteristics
.iter()
.find(|characteristics| characteristics.uuid == STATUS_UUID)
.find(|characteristics| characteristics.uuid == POSITION_UUID)
.unwrap()
.clone();

Self {
manager,
central,
desk,
control_characteristic,
status_characteristic,
position_characteristic,
}
}

pub fn up(&self) {
self.desk.command(&self.control_characteristic, &UP);
/// Move desk up.
pub fn up(&self) -> btleplug::Result<()> {
self.desk.command(&self.control_characteristic, &UP)
}

/// Lower the desk's position.
pub fn down(&self) -> btleplug::Result<()> {
self.desk.command(&self.control_characteristic, &DOWN)
}

pub fn down(&self) {
self.desk.command(&self.control_characteristic, &DOWN);
/// Stop desk from moving.
pub fn stop(&self) -> btleplug::Result<()> {
self.desk.command(&self.control_characteristic, &STOP)
}

pub fn stop(&self) {
self.desk.command(&self.control_characteristic, &STOP);
/// Move desk to a desired position. The precision is decent, usually less than 1mm off.
pub fn move_to(&self, target_position: i16) -> Result<(), Error> {
if target_position < MIN_HEIGHT || target_position > MAX_HEIGHT {
return Err(Error::PositionNotInRange);
}

let going_up = match target_position.cmp(&self.position()) {
Ordering::Greater => true,
Ordering::Less => false,
Ordering::Equal => return Ok(()),
};

let mut position_reached = false;
let mut last_position = self.position();
let mut speed;
while !position_reached {
let current_position = self.position();
let remaining_distance = (target_position - current_position).abs();
speed = (last_position - current_position).abs();
if remaining_distance <= min(speed, 5) {
position_reached = true;
let _ = self.stop();
} else if going_up {
let _ = self.up();
} else if !going_up {
let _ = self.down();
}
if remaining_distance < max(speed * 10, 10) {
let _ = self.stop();
}
last_position = current_position;
}

Ok(())
}

pub fn height(&self) -> f32 {
let response = self
.desk
.read_by_type(&self.status_characteristic, self.status_characteristic.uuid);
bytes_to_meters(&response.unwrap())
/// Return the desk height in tenth milimeters (1m = 10000)
pub fn position(&self) -> i16 {
let response = self.desk.read_by_type(
&self.position_characteristic,
self.position_characteristic.uuid,
);
bytes_to_tenth_milimeters(&response.unwrap())
}
}

0 comments on commit 0590f57

Please sign in to comment.