From e338a46165be2c6d5c96f4b8a4f5ef0b3b004492 Mon Sep 17 00:00:00 2001 From: Connor Radeloff Date: Wed, 26 Feb 2025 17:12:08 -0600 Subject: [PATCH] Remove unnecessary comment --- examples/apps/src/ble_scanner.rs | 195 ++++++++++++++++++++++++++++--- 1 file changed, 178 insertions(+), 17 deletions(-) diff --git a/examples/apps/src/ble_scanner.rs b/examples/apps/src/ble_scanner.rs index 75f00c37..e56ea8f2 100644 --- a/examples/apps/src/ble_scanner.rs +++ b/examples/apps/src/ble_scanner.rs @@ -2,16 +2,29 @@ use bt_hci::cmd::le::LeSetScanParams; use bt_hci::controller::ControllerCmdSync; use core::cell::RefCell; use embassy_futures::join::join; +use embassy_futures::select::select; +use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; +use embassy_sync::signal::Signal; use embassy_time::{Duration, Timer}; -use heapless::Deque; +use heapless::{Deque, String, Vec}; use trouble_host::prelude::*; /// Max number of connections const CONNECTIONS_MAX: usize = 1; const L2CAP_CHANNELS_MAX: usize = 1; -const L2CAP_MTU: usize = 27; -pub async fn run(controller: C) +const IDENTIFY: [u8; 20] = [ + 239, 221, 11, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 104, 59, +]; + +const NOTIFICATION_REQUEST: [u8; 14] = [ + 0xef, 0xdd, 0x0c, 0x09, 0x00, 0x01, 0x01, 0x02, 0x02, 0x05, 0x03, 0x04, 0x15, 0x06, +]; +const HEARTBEAT: [u8; 7] = [239, 221, 0, 2, 0, 2, 0]; + +const HEARTBEAT_INTERVAL: Duration = Duration::from_millis(2000); + +pub async fn run(controller: C) where C: Controller + ControllerCmdSync, { @@ -23,30 +36,118 @@ where let mut resources: HostResources = HostResources::new(); let stack = trouble_host::new(controller, &mut resources).set_random_address(address); let Host { - central, mut runner, .. + mut central, + mut runner, + .. } = stack.build(); let printer = Printer { seen: RefCell::new(Deque::new()), + found: Signal::new(), }; - let mut scanner = Scanner::new(central); - let _ = join(runner.run_with_handler(&printer), async { - let mut config = ScanConfig::default(); - config.active = true; - config.phys = PhySet::M1; - config.interval = Duration::from_secs(1); - config.window = Duration::from_secs(1); - let mut _session = scanner.scan(&config).await.unwrap(); - // Scan forever - loop { - Timer::after(Duration::from_secs(1)).await; - } + + let _ = select(runner.run_with_handler(&printer), async { + let mut central = { + let mut scanner = Scanner::new(central); + { + let mut config = ScanConfig::default(); + config.active = true; + config.phys = PhySet::M1; + config.interval = Duration::from_secs(1); + config.window = Duration::from_secs(1); + let mut _session = scanner.scan(&config).await.unwrap(); + // Scan until we've found an inner value + loop { + if !printer.found.signaled() { + Timer::after(Duration::from_secs(1)).await; + continue; + } + + break; + } + } + + scanner.into_inner() + }; + + let found = printer.found.try_take().unwrap(); + + let (addr, addr_kind) = found; + info!("Found the device! addr: {:?}, kind: {:?}", addr, addr_kind); + + let config = ConnectConfig { + connect_params: Default::default(), + scan_config: ScanConfig { + filter_accept_list: &[(addr_kind, &addr)], + ..Default::default() + }, + }; + + let conn = central.connect(&config).await.unwrap(); + info!("Connected, creating gatt client"); + + let client = GattClient::::new(&stack, &conn).await.unwrap(); + + let _ = join(client.task(), async { + info!("Looking for battery service"); + let services = client.services_by_uuid(&Uuid::new_short(0x1820)).await.unwrap(); + let service = services.first().unwrap().clone(); + + info!("Looking for value handle"); + let c: Characteristic = client + .characteristic_by_uuid(&service, &Uuid::new_short(0x2a80)) + .await + .unwrap(); + + info!("Characteristic: {:?}", c.handle); + + info!("Subscribing notifications"); + let mut listener = client.subscribe(&c, false).await.unwrap(); + + join( + async { + loop { + let data = listener.next().await; + info!("Got notification: {:?} (val: {})", data.as_ref(), data.as_ref()[0]); + } + }, + async { + Timer::after(Duration::from_millis(150)).await; + info!("Writing Heartbeat"); + client + .write_characteristic_without_response(&c, &IDENTIFY) + .await + .unwrap(); + client + .write_characteristic_without_response(&c, &NOTIFICATION_REQUEST) + .await + .unwrap(); + loop { + Timer::after(HEARTBEAT_INTERVAL).await; + info!("Writing Heartbeat"); + client + .write_characteristic_without_response(&c, &IDENTIFY) + .await + .unwrap(); + } + }, + ) + .await; + + info!("Disconnected"); + }) + .await; }) .await; + + let Some(value) = printer.found.try_take() else { + panic!("Idk how you got here but you did. Good job.") + }; } struct Printer { seen: RefCell>, + found: Signal, } impl EventHandler for Printer { @@ -54,7 +155,30 @@ impl EventHandler for Printer { let mut seen = self.seen.borrow_mut(); while let Some(Ok(report)) = it.next() { if seen.iter().find(|b| b.raw() == report.addr.raw()).is_none() { - info!("discovered: {:?}", report.addr); + //info!("discovered: {:?}", report.addr); + let mut advertisements = AdStructure::decode(report.data); + while let Some(Ok(ad)) = advertisements.next() { + match ad { + AdStructure::CompleteLocalName(n) => { + let value = get_name_string(n); + info!("Complete Name: {:?}", value); + if value.starts_with("ACAIA") { + info!("SIGNALING"); + self.found.signal((report.addr, report.addr_kind)) + } + } + AdStructure::ShortenedLocalName(n) => { + let value = get_name_string(n); + info!("Short Name: {:?}", value); + if value.starts_with("ACAIA") { + info!("SIGNALING"); + self.found.signal((report.addr, report.addr_kind)) + } + } + _ => {} + } + } + if seen.is_full() { seen.pop_front(); } @@ -63,3 +187,40 @@ impl EventHandler for Printer { } } } + +fn get_name_string(slice: &[u8]) -> String<291> { + let mut vec = Vec::::new(); + vec.extend_from_slice(&slice).unwrap(); + String::from_utf8(vec).unwrap() +} + +fn encode(msg_type: u8, payload: &[u8]) -> [u8; N] { + let header1 = 0xef; // Replace with your actual HEADER1 value + let header2 = 0xdd; // Replace with your actual HEADER2 value + + let mut bytes = [0u8; N]; + + bytes[0] = header1; + bytes[1] = header2; + bytes[2] = msg_type; + + let mut cksum1 = 0; + let mut cksum2 = 0; + + for (i, &val) in payload.iter().enumerate() { + let val = val & 0xff; + bytes[3 + i] = val; + if i % 2 == 0 { + cksum1 += val as u16; + } else { + cksum2 += val as u16; + } + } + + bytes[payload.len() + 3] = (cksum1 & 0xFF) as u8; + bytes[payload.len() + 4] = (cksum2 & 0xFF) as u8; + + info!("{:?}", bytes); + + bytes +}