From 36bfd7c66ad1332eaedecde3b6273f4db0559103 Mon Sep 17 00:00:00 2001 From: Romeo Disca Date: Fri, 7 Aug 2020 18:04:29 +0200 Subject: chore: create simple command submitter --- src/client.rs | 47 +++++++++++++++++++++++++-- src/commands.rs | 99 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/events.rs | 72 ++++++++++++++++++++++++++++++++++------- src/main.rs | 10 ++++-- 4 files changed, 213 insertions(+), 15 deletions(-) create mode 100755 src/commands.rs (limited to 'src') diff --git a/src/client.rs b/src/client.rs index 3557df8..b6b681a 100644 --- a/src/client.rs +++ b/src/client.rs @@ -1,6 +1,11 @@ +use std::sync::Arc; + +use tokio::io::*; +use tokio::net::TcpStream; use super::events::*; +use super::commands::Command; pub fn event_handler(f: F) -> Box where F: FnMut(Event) + 'static @@ -9,16 +14,54 @@ pub fn event_handler(f: F) -> Box } pub struct FlicClient { + reader: Arc, + writer: Arc, map: Vec>, + is_running: bool, } impl FlicClient { - pub fn new() -> FlicClient { - FlicClient{map: vec![]} + pub async fn new(conn: &str) -> Result { + match TcpStream::connect(conn).await { + Ok(stream) => { + let reader = Arc::new(stream); + let writer = reader.clone(); + + Ok(FlicClient{ + reader, + writer, + map: vec![], + is_running: true, + }) + } + Err(err) => Err(err) + } + } pub fn register_event_handler(mut self, event: Box) -> Self { self.map.push(event); self } + pub async fn listen(&mut self) { + while self.is_running { + if let Some(mut r) = Arc::get_mut(&mut self.reader) { + if let Ok(value) = r.read_u8().await { + for ref mut f in self.map.as_mut_slice() { + f(Event::read_event(value, &mut r)); + } + } + } + } + } + pub fn stop(&mut self) { + self.is_running = false; + } + + pub fn submit(&mut self, cmd: Command) -> Result<()> { + if let Some(mut w) = Arc::get_mut(&mut self.writer) { + cmd.write_command(&mut w)?; + } + Ok(()) + } } diff --git a/src/commands.rs b/src/commands.rs new file mode 100755 index 0000000..d84d9cd --- /dev/null +++ b/src/commands.rs @@ -0,0 +1,99 @@ + +use num_enum::TryFromPrimitive; +use num_enum::IntoPrimitive; +use tokio::io::*; +use tokio::net::TcpStream; + +use super::enums::LatencyMode; + +/// Commands + +pub enum Command { + GetInfo, + CreateScanner { + scan_id: u32, + }, + RemoveScanner { + scan_id: u32, + }, + CreateConnectionChannel { + conn_id: u32, + bd_addr: String, + latency_mode: LatencyMode, + auto_disconnect_time: i16, + }, + RemoveConnectionChannel { + conn_id: u32, + }, + ForceDisconnect { + bd_addr: String, + }, + ChangeModeParameters { + conn_id: u32, + latency_mode: LatencyMode, + auto_disconnect_time: i16, + }, + Ping { + ping_id: u32, + }, + GetButtonInfo { + bd_addr: String, + }, + CreateScanWizard { + scan_wizard_id: u32, + }, + CancelScanWizard { + scan_wizard_id: u32, + }, + DeleteButton { + bd_addr: String, + }, + CreateBatteryStatusListener { + listener_id: u32, + bd_addr: String, + }, + RemoveBatteryStatusListener { + listener_id: u32, + }, +} + +impl Command { + pub fn opcode(&self) -> u8 { + match self { + Self::GetInfo{..} => 0, + Self::CreateScanner{..} => 1, + Self::RemoveScanner{..} => 2, + Self::CreateConnectionChannel{..} => 3, + Self::RemoveConnectionChannel{..} => 4, + Self::ForceDisconnect{..} => 5, + Self::ChangeModeParameters{..} => 6, + Self::Ping{..} => 7, + Self::GetButtonInfo{..} => 8, + Self::CreateScanWizard{..} => 9, + Self::CancelScanWizard{..} => 10, + Self::DeleteButton{..} => 11, + Self::CreateBatteryStatusListener{..} => 12, + Self::RemoveBatteryStatusListener{..} => 13, + } + } + pub fn write_command(&self, writer: &mut TcpStream) -> Result<()> { + match self { + Self::GetInfo{..} => 0, + Self::CreateScanner{..} => 1, + Self::RemoveScanner{..} => 2, + Self::CreateConnectionChannel{..} => 3, + Self::RemoveConnectionChannel{..} => 4, + Self::ForceDisconnect{..} => 5, + Self::ChangeModeParameters{..} => 6, + Self::Ping{..} => 7, + Self::GetButtonInfo{..} => 8, + Self::CreateScanWizard{..} => 9, + Self::CancelScanWizard{..} => 10, + Self::DeleteButton{..} => 11, + Self::CreateBatteryStatusListener{..} => 12, + Self::RemoveBatteryStatusListener{..} => 13, + }; + + Ok(()) + } +} \ No newline at end of file diff --git a/src/events.rs b/src/events.rs index aa53280..ac00472 100644 --- a/src/events.rs +++ b/src/events.rs @@ -1,11 +1,14 @@ +use tokio::net::TcpStream; + use super::enums::*; #[allow(dead_code)] #[derive(Debug, PartialEq, Eq, Clone)] pub enum Event { + CorruptEvent, + AdvertisementPacket { - opcode: u8, scan_id: u32, bd_addr: String, name: String, @@ -33,7 +36,25 @@ pub enum Event { removed_reason: RemovedReason, }, - ButtonEvent { + ButtonUpOrDown{ + conn_id: u32, + click_type: ClickType, + was_queued: bool, + time_diff: i32, + }, + ButtonClickOrHold{ + conn_id: u32, + click_type: ClickType, + was_queued: bool, + time_diff: i32, + }, + ButtonSingleOrDoubleClick{ + conn_id: u32, + click_type: ClickType, + was_queued: bool, + time_diff: i32, + }, + ButtonSingleOrDoubleClickOrHold{ conn_id: u32, click_type: ClickType, was_queued: bool, @@ -41,12 +62,10 @@ pub enum Event { }, NewVerifiedButton { - opcode: u8, bd_addr: String, }, GetInfoResponse { - opcode: u8, bluetooth_controller_state: BluetoothControllerState, my_bd_addr: String, my_bd_addr_type: BdAddrType, @@ -58,27 +77,22 @@ pub enum Event { }, NoSpaceForNewConnection { - opcode: u8, max_concurrently_connected_buttons: u8, }, GotSpaceForNewConnection { - opcode: u8, max_concurrently_connected_buttons: u8, }, BluetoothControllerStateChange { - opcode: u8, state: BluetoothControllerState, }, PingResponse { - opcode: u8, ping_id: u32, }, GetButtonInfoResponse { - opcode: u8, bd_addr: String, uuid: String, color: Option, @@ -105,15 +119,51 @@ pub enum Event { }, ButtonDeleted { - opcode: u8, bd_addr: String, deleted_by_this_client: bool, }, BatteryStatus { - opcode: u8, listener_id: u32, battery_percentage: i8, timestamp: u64, }, } + +impl Event { + pub fn opcode(&self) -> u8 { + match self { + Self::CorruptEvent => 255, + Self::AdvertisementPacket{..} => 0, + Self::CreateConnectionChannelResponse{..} => 1, + Self::ConnectionStatusChanged{..} => 2, + Self::ConnectionChannelRemoved{..} => 3, + Self::ButtonUpOrDown{..} => 4, + Self::ButtonClickOrHold{..} => 5, + Self::ButtonSingleOrDoubleClick{..} => 6, + Self::ButtonSingleOrDoubleClickOrHold{..} => 7, + Self::NewVerifiedButton{..} => 8, + Self::GetInfoResponse{..} => 9, + Self::NoSpaceForNewConnection{..} => 10, + Self::GotSpaceForNewConnection{..} => 11, + Self::BluetoothControllerStateChange{..} => 12, + Self::PingResponse{..} => 13, + Self::GetButtonInfoResponse{..} => 14, + Self::ScanWizardFoundPrivateButton{..} => 15, + Self::ScanWizardFoundPublicButton{..} => 16, + Self::ScanWizardButtonConnected{..} => 17, + Self::ScanWizardCompleted{..} => 18, + Self::ButtonDeleted{..} => 19, + Self::BatteryStatus{..} => 20, + } + } + + pub fn read_event(opcode: u8, reader: &mut TcpStream) -> Event { + match opcode { + 13 => Self::PingResponse{ping_id: 8}, + _ => Self::CorruptEvent, + } + } + +} + diff --git a/src/main.rs b/src/main.rs index fff75ce..bcefc75 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,17 +1,23 @@ mod enums; mod events; +mod commands; mod client; +use std::error::Error; + use client::*; -fn main() { +#[tokio::main] +async fn main() -> Result<(), Box> { let event = event_handler(|event| { println!("ping response: {:?}", event); }); let event2 = event_handler(|event| { println!("ping response: {:?}", event); }); - let _client = FlicClient::new() + let _client = FlicClient::new("127.0.0.1:5551").await? .register_event_handler(event) .register_event_handler(event2) ; + + Ok(()) } -- cgit v1.2.3