diff options
-rwxr-xr-x[-rw-r--r--] | .gitignore | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | Cargo.lock | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | Cargo.toml | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | examples/ping.rs | 0 | ||||
-rwxr-xr-x | examples/simpleclient.rs | 107 | ||||
-rwxr-xr-x[-rw-r--r--] | src/client.rs | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | src/commands/mod.rs | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | src/commands/stream_mapper.rs | 384 | ||||
-rwxr-xr-x[-rw-r--r--] | src/enums.rs | 198 | ||||
-rwxr-xr-x[-rw-r--r--] | src/events/mod.rs | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | src/events/stream_mapper.rs | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | src/lib.rs | 3 |
12 files changed, 400 insertions, 292 deletions
diff --git a/.gitignore b/.gitignore index ea8c4bf..ea8c4bf 100644..100755 --- a/.gitignore +++ b/.gitignore diff --git a/Cargo.lock b/Cargo.lock index f9b2e50..f9b2e50 100644..100755 --- a/Cargo.lock +++ b/Cargo.lock diff --git a/Cargo.toml b/Cargo.toml index 69d3fc1..69d3fc1 100644..100755 --- a/Cargo.toml +++ b/Cargo.toml diff --git a/examples/ping.rs b/examples/ping.rs index 4a6a7cb..4a6a7cb 100644..100755 --- a/examples/ping.rs +++ b/examples/ping.rs diff --git a/examples/simpleclient.rs b/examples/simpleclient.rs new file mode 100755 index 0000000..52b4300 --- /dev/null +++ b/examples/simpleclient.rs @@ -0,0 +1,107 @@ + + +use std::io::*; +use std::sync::Arc; + +use flicbtn::*; + +#[tokio::main] +async fn main() -> Result<()> { + + let event = event_handler(|event| { println!("ping response: {:?}", event); }); + + let client = FlicClient::new("127.0.0.1:5551").await? + .register_event_handler(event).await + ; + let client1 = Arc::new(client); + let client2 = client1.clone(); + + let button = "80:e4:da:76:fa:55"; + + let mut scan_wizard_id = 0; + let mut conn_id = 0; + + let cmd = tokio::spawn(async move { + + println!("==============================================="); + println!("*** Hello to the Flic2 Button Simple Client ***"); + println!("==============================================="); + client1.submit(Command::GetInfo).await; + println!(""); + + loop { + + show_commands(); + + println!(""); + print!("-- Choose: "); + + let _ = stdout().flush(); + + let mut input = String::new(); + stdin().read_line(&mut input).expect("Did not enter correct string!"); + + println!("[{}]", &input.as_str()[0..input.len()-2]); + + match &input.as_str()[..input.len()-2] { + "X" => break, + "1" => { + println!("-- start scan wizard"); + scan_wizard_id += 1; + client1.submit(Command::CreateScanWizard{scan_wizard_id}).await; + } + "2" => { + println!("-- cancel scan wizard"); + client1.submit(Command::CancelScanWizard{scan_wizard_id}).await; + //scan_wizard_id -= 1; + } + "3" => { + println!("-- create connection channel"); + conn_id += 1; + client1.submit(Command::CreateConnectionChannel{ + conn_id, + bd_addr: button.to_string(), + latency_mode: LatencyMode::NormalLatency, + auto_disconnect_time: 11111_i16, + }).await; + } + "4" => { + println!("-- remove connection channel"); + client1.submit(Command::RemoveConnectionChannel{ + conn_id, + }).await; + //conn_id -= 1; + } + "5" => { + println!("-- button info"); + client1.submit(Command::GetButtonInfo{bd_addr: button.to_string()}).await; + } + _ => { + println!("-- unknown command"); + } + } + + println!(""); + } + + client1.stop().await; + }); + let lst = tokio::spawn(async move { + client2.listen().await; + println!("stop"); + }); + + lst.await?; + cmd.await?; + + Ok(()) +} + +fn show_commands() { + println!("1) Start Scan Wizard"); + println!("2) Cancel Scan Wizard"); + println!("3) Create Connection Channel"); + println!("4) Remove Connection Channel"); + println!("5) Get Button Info"); + println!("X) End"); +}
\ No newline at end of file diff --git a/src/client.rs b/src/client.rs index a1a63f7..a1a63f7 100644..100755 --- a/src/client.rs +++ b/src/client.rs diff --git a/src/commands/mod.rs b/src/commands/mod.rs index e2b886b..e2b886b 100644..100755 --- a/src/commands/mod.rs +++ b/src/commands/mod.rs diff --git a/src/commands/stream_mapper.rs b/src/commands/stream_mapper.rs index 2b6f612..4b13bc8 100644..100755 --- a/src/commands/stream_mapper.rs +++ b/src/commands/stream_mapper.rs @@ -1,192 +1,192 @@ -
-use regex::Regex;
-
-use std::collections::VecDeque;
-use std::collections::vec_deque::Drain;
-use std::convert::TryInto;
-
-use super::*;
-
-pub struct CommandToByteMapper {
- buffer: VecDeque<u8>,
-}
-impl CommandToByteMapper {
-
- pub fn new() -> CommandToByteMapper {
- CommandToByteMapper{ buffer: VecDeque::new() }
- }
-
- pub fn map(&mut self, command: Command) -> Drain<u8> {
- self.clear_buffer();
-
- self.write_u8(command.opcode());
- match command {
- Command::GetInfo => {},
- Command::CreateScanner {
- scan_id,
- } => {
-
- self.write_u32(scan_id);
- },
- Command::RemoveScanner {
- scan_id,
- } => {
-
- self.write_u32(scan_id);
- },
- Command::CreateConnectionChannel {
- conn_id,
- bd_addr,
- latency_mode,
- auto_disconnect_time,
- } => {
-
- self.write_u32(conn_id);
- self.write_bdaddr(&bd_addr[..]);
- if let Ok(latency_mode) = latency_mode.try_into() {
- self.write_u8(latency_mode);
- }
- self.write_i16(auto_disconnect_time);
- },
- Command::RemoveConnectionChannel {
- conn_id,
- } => {
-
- self.write_u32(conn_id);
- },
- Command::ForceDisconnect {
- bd_addr,
- } => {
-
- self.write_bdaddr(&bd_addr[..]);
- },
- Command::ChangeModeParameters {
- conn_id,
- latency_mode,
- auto_disconnect_time,
- } => {
-
- self.write_u32(conn_id);
- if let Ok(latency_mode) = latency_mode.try_into() {
- self.write_u8(latency_mode);
- }
- self.write_i16(auto_disconnect_time);
- },
- Command::Ping {
- ping_id,
- } => {
-
- self.write_u32(ping_id);
- },
- Command::GetButtonInfo {
- bd_addr,
- } => {
-
- self.write_bdaddr(&bd_addr[..]);
- },
- Command::CreateScanWizard {
- scan_wizard_id,
- } => {
-
- self.write_u32(scan_wizard_id);
- },
- Command::CancelScanWizard {
- scan_wizard_id,
- } => {
-
- self.write_u32(scan_wizard_id);
- },
- Command::DeleteButton {
- bd_addr,
- } => {
-
- self.write_bdaddr(&bd_addr[..]);
- },
- Command::CreateBatteryStatusListener {
- listener_id,
- bd_addr,
- } => {
-
- self.write_u32(listener_id);
- self.write_bdaddr(&bd_addr[..]);
- },
- Command::RemoveBatteryStatusListener {
- listener_id,
- } => {
-
- self.write_u32(listener_id);
- },
- }
-
- self.prepend_size();
-
- self.buffer.drain(..)
- }
-
- fn clear_buffer(&mut self) {
- self.buffer.drain(..);
- }
-
- fn prepend_size(&mut self) {
- let len = self.buffer.len();
- self.buffer.push_front((len >> 8) as u8);
- self.buffer.push_front((len & 255) as u8);
- }
- fn write_u8(&mut self, value: u8) {
- let mut buf = vec![value].into_iter().collect();
- self.buffer.append(&mut buf);
- }
-/*
- fn write_bool(&mut self, value: bool) {
- if value {
- self.write_u8(1);
- }
- else {
- self.write_u8(0);
- }
- }
-*/
- fn write_u16(&mut self, value: u16) {
- self.write_u8(value as u8);
- self.write_u8((value >> 8) as u8);
- }
- fn write_i16(&mut self, value: i16) {
- self.write_u8(value as u8);
- self.write_u8((value >> 8) as u8);
- }
- fn write_u32(&mut self, value: u32) {
- self.write_u16(value as u16);
- self.write_u16((value >> 16) as u16);
- }
-/*
- fn write_i32(&mut self, value: i32) {
- self.write_i16(value as i16);
- self.write_i16((value >> 16) as i16);
- }
-*/
- fn write_bdaddr(&mut self, str: &str) {
- let re = Regex::new(r"([0-9a-z]{2}:){5}[0-9a-z]{2}").unwrap();
- if re.is_match(str) {
- if let Some(b) = hex_to_u8(&str[15..]) { self.write_u8(b); }
- if let Some(b) = hex_to_u8(&str[12..]) { self.write_u8(b); }
- if let Some(b) = hex_to_u8(&str[ 9..]) { self.write_u8(b); }
- if let Some(b) = hex_to_u8(&str[ 6..]) { self.write_u8(b); }
- if let Some(b) = hex_to_u8(&str[ 3..]) { self.write_u8(b); }
- if let Some(b) = hex_to_u8(&str[ ..]) { self.write_u8(b); }
- }
- }
-
-}
-
-fn hex_to_u8(buffer: &str) -> Option<u8> {
- let mut char_indices = buffer.char_indices();
- match (char_indices.next(), char_indices.next()) {
- (Some((0, upper)), Some((1, lower))) => {
- let mut b = 0u8;
- if let Some(v) = upper.to_digit(16) { b += (v as u8) << 4; }
- if let Some(v) = lower.to_digit(16) { b += v as u8; }
- Some(b)
- },
- _ => None,
- }
-}
+ +use regex::Regex; + +use std::collections::VecDeque; +use std::collections::vec_deque::Drain; +use std::convert::TryInto; + +use super::*; + +pub struct CommandToByteMapper { + buffer: VecDeque<u8>, +} +impl CommandToByteMapper { + + pub fn new() -> CommandToByteMapper { + CommandToByteMapper{ buffer: VecDeque::new() } + } + + pub fn map(&mut self, command: Command) -> Drain<u8> { + self.clear_buffer(); + + self.write_u8(command.opcode()); + match command { + Command::GetInfo => {}, + Command::CreateScanner { + scan_id, + } => { + + self.write_u32(scan_id); + }, + Command::RemoveScanner { + scan_id, + } => { + + self.write_u32(scan_id); + }, + Command::CreateConnectionChannel { + conn_id, + bd_addr, + latency_mode, + auto_disconnect_time, + } => { + + self.write_u32(conn_id); + self.write_bdaddr(&bd_addr[..]); + if let Ok(latency_mode) = latency_mode.try_into() { + self.write_u8(latency_mode); + } + self.write_i16(auto_disconnect_time); + }, + Command::RemoveConnectionChannel { + conn_id, + } => { + + self.write_u32(conn_id); + }, + Command::ForceDisconnect { + bd_addr, + } => { + + self.write_bdaddr(&bd_addr[..]); + }, + Command::ChangeModeParameters { + conn_id, + latency_mode, + auto_disconnect_time, + } => { + + self.write_u32(conn_id); + if let Ok(latency_mode) = latency_mode.try_into() { + self.write_u8(latency_mode); + } + self.write_i16(auto_disconnect_time); + }, + Command::Ping { + ping_id, + } => { + + self.write_u32(ping_id); + }, + Command::GetButtonInfo { + bd_addr, + } => { + + self.write_bdaddr(&bd_addr[..]); + }, + Command::CreateScanWizard { + scan_wizard_id, + } => { + + self.write_u32(scan_wizard_id); + }, + Command::CancelScanWizard { + scan_wizard_id, + } => { + + self.write_u32(scan_wizard_id); + }, + Command::DeleteButton { + bd_addr, + } => { + + self.write_bdaddr(&bd_addr[..]); + }, + Command::CreateBatteryStatusListener { + listener_id, + bd_addr, + } => { + + self.write_u32(listener_id); + self.write_bdaddr(&bd_addr[..]); + }, + Command::RemoveBatteryStatusListener { + listener_id, + } => { + + self.write_u32(listener_id); + }, + } + + self.prepend_size(); + + self.buffer.drain(..) + } + + fn clear_buffer(&mut self) { + self.buffer.drain(..); + } + + fn prepend_size(&mut self) { + let len = self.buffer.len(); + self.buffer.push_front((len >> 8) as u8); + self.buffer.push_front((len & 255) as u8); + } + fn write_u8(&mut self, value: u8) { + let mut buf = vec![value].into_iter().collect(); + self.buffer.append(&mut buf); + } +/* + fn write_bool(&mut self, value: bool) { + if value { + self.write_u8(1); + } + else { + self.write_u8(0); + } + } +*/ + fn write_u16(&mut self, value: u16) { + self.write_u8(value as u8); + self.write_u8((value >> 8) as u8); + } + fn write_i16(&mut self, value: i16) { + self.write_u8(value as u8); + self.write_u8((value >> 8) as u8); + } + fn write_u32(&mut self, value: u32) { + self.write_u16(value as u16); + self.write_u16((value >> 16) as u16); + } +/* + fn write_i32(&mut self, value: i32) { + self.write_i16(value as i16); + self.write_i16((value >> 16) as i16); + } +*/ + fn write_bdaddr(&mut self, str: &str) { + let re = Regex::new(r"([0-9a-z]{2}:){5}[0-9a-z]{2}").unwrap(); + if re.is_match(str) { + if let Some(b) = hex_to_u8(&str[15..]) { self.write_u8(b); } + if let Some(b) = hex_to_u8(&str[12..]) { self.write_u8(b); } + if let Some(b) = hex_to_u8(&str[ 9..]) { self.write_u8(b); } + if let Some(b) = hex_to_u8(&str[ 6..]) { self.write_u8(b); } + if let Some(b) = hex_to_u8(&str[ 3..]) { self.write_u8(b); } + if let Some(b) = hex_to_u8(&str[ ..]) { self.write_u8(b); } + } + } + +} + +fn hex_to_u8(buffer: &str) -> Option<u8> { + let mut char_indices = buffer.char_indices(); + match (char_indices.next(), char_indices.next()) { + (Some((0, upper)), Some((1, lower))) => { + let mut b = 0u8; + if let Some(v) = upper.to_digit(16) { b += (v as u8) << 4; } + if let Some(v) = lower.to_digit(16) { b += v as u8; } + Some(b) + }, + _ => None, + } +} diff --git a/src/enums.rs b/src/enums.rs index 64284a2..83fe016 100644..100755 --- a/src/enums.rs +++ b/src/enums.rs @@ -1,99 +1,99 @@ -
-#![allow(dead_code)]
-
-use num_enum::TryFromPrimitive;
-use num_enum::IntoPrimitive;
-
-// Enums
-
-#[repr(u8)]
-#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone, IntoPrimitive, TryFromPrimitive)]
-pub enum CreateConnectionChannelError {
- NoError,
- MaxPendingConnectionsReached,
-}
-
-#[repr(u8)]
-#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone, IntoPrimitive, TryFromPrimitive)]
-pub enum ConnectionStatus {
- Disconnected,
- Connected,
- Ready,
-}
-
-#[repr(u8)]
-#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone, IntoPrimitive, TryFromPrimitive)]
-pub enum DisconnectReason {
- Unspecified,
- ConnectionEstablishmentFailed,
- TimedOut,
- BondingKeysMismatch,
-}
-
-#[repr(u8)]
-#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone, IntoPrimitive, TryFromPrimitive)]
-pub enum RemovedReason {
- RemovedByThisClient,
- ForceDisconnectedByThisClient,
- ForceDisconnectedByOtherClient,
-
- ButtonIsPrivate,
- VerifyTimeout,
- InternetBackendError,
- InvalidData,
-
- CouldntLoadDevice,
-
- DeletedByThisClient,
- DeletedByOtherClient,
- ButtonBelongsToOtherPartner,
- DeletedFromButton,
-}
-
-#[repr(u8)]
-#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone, IntoPrimitive, TryFromPrimitive)]
-pub enum ClickType {
- ButtonDown,
- ButtonUp,
- ButtonClick,
- ButtonSingleClick,
- ButtonDoubleClick,
- ButtonHold,
-}
-
-#[repr(u8)]
-#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone, IntoPrimitive, TryFromPrimitive)]
-pub enum BdAddrType {
- PublicBdAddrType,
- RandomBdAddrType,
-}
-
-#[repr(u8)]
-#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone, IntoPrimitive, TryFromPrimitive)]
-pub enum LatencyMode {
- NormalLatency,
- LowLatency,
- HighLatency,
-}
-
-#[repr(u8)]
-#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone, IntoPrimitive, TryFromPrimitive)]
-pub enum ScanWizardResult {
- WizardSuccess,
- WizardCancelledByUser,
- WizardFailedTimeout,
- WizardButtonIsPrivate,
- WizardBluetoothUnavailable,
- WizardInternetBackendError,
- WizardInvalidData,
- WizardButtonBelongsToOtherPartner,
- WizardButtonAlreadyConnectedToOtherDevice,
-}
-
-#[repr(u8)]
-#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone, IntoPrimitive, TryFromPrimitive)]
-pub enum BluetoothControllerState {
- Detached,
- Resetting,
- Attached,
-}
+ +#![allow(dead_code)] + +use num_enum::TryFromPrimitive; +use num_enum::IntoPrimitive; + +// Enums + +#[repr(u8)] +#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone, IntoPrimitive, TryFromPrimitive)] +pub enum CreateConnectionChannelError { + NoError, + MaxPendingConnectionsReached, +} + +#[repr(u8)] +#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone, IntoPrimitive, TryFromPrimitive)] +pub enum ConnectionStatus { + Disconnected, + Connected, + Ready, +} + +#[repr(u8)] +#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone, IntoPrimitive, TryFromPrimitive)] +pub enum DisconnectReason { + Unspecified, + ConnectionEstablishmentFailed, + TimedOut, + BondingKeysMismatch, +} + +#[repr(u8)] +#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone, IntoPrimitive, TryFromPrimitive)] +pub enum RemovedReason { + RemovedByThisClient, + ForceDisconnectedByThisClient, + ForceDisconnectedByOtherClient, + + ButtonIsPrivate, + VerifyTimeout, + InternetBackendError, + InvalidData, + + CouldntLoadDevice, + + DeletedByThisClient, + DeletedByOtherClient, + ButtonBelongsToOtherPartner, + DeletedFromButton, +} + +#[repr(u8)] +#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone, IntoPrimitive, TryFromPrimitive)] +pub enum ClickType { + ButtonDown, + ButtonUp, + ButtonClick, + ButtonSingleClick, + ButtonDoubleClick, + ButtonHold, +} + +#[repr(u8)] +#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone, IntoPrimitive, TryFromPrimitive)] +pub enum BdAddrType { + PublicBdAddrType, + RandomBdAddrType, +} + +#[repr(u8)] +#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone, IntoPrimitive, TryFromPrimitive)] +pub enum LatencyMode { + NormalLatency, + LowLatency, + HighLatency, +} + +#[repr(u8)] +#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone, IntoPrimitive, TryFromPrimitive)] +pub enum ScanWizardResult { + WizardSuccess, + WizardCancelledByUser, + WizardFailedTimeout, + WizardButtonIsPrivate, + WizardBluetoothUnavailable, + WizardInternetBackendError, + WizardInvalidData, + WizardButtonBelongsToOtherPartner, + WizardButtonAlreadyConnectedToOtherDevice, +} + +#[repr(u8)] +#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone, IntoPrimitive, TryFromPrimitive)] +pub enum BluetoothControllerState { + Detached, + Resetting, + Attached, +} diff --git a/src/events/mod.rs b/src/events/mod.rs index 0cfd910..0cfd910 100644..100755 --- a/src/events/mod.rs +++ b/src/events/mod.rs diff --git a/src/events/stream_mapper.rs b/src/events/stream_mapper.rs index 5244d58..5244d58 100644..100755 --- a/src/events/stream_mapper.rs +++ b/src/events/stream_mapper.rs diff --git a/src/lib.rs b/src/lib.rs index ba9a5f6..43f8ede 100644..100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,4 +6,5 @@ mod client; pub use client::*; pub use commands::Command; -pub use events::Event;
\ No newline at end of file +pub use events::Event; +pub use enums::*;
\ No newline at end of file |