|
| 1 | +use embassy_futures::join::{join, join3}; |
| 2 | +use embassy_time::{Duration, Timer}; |
| 3 | +use trouble_host::prelude::*; |
| 4 | + |
| 5 | +/// Max number of connections |
| 6 | +const CONNECTIONS_MAX: usize = 2; |
| 7 | + |
| 8 | +/// Max number of L2CAP channels. |
| 9 | +const L2CAP_CHANNELS_MAX: usize = 4; // Signal + att + CoC |
| 10 | + |
| 11 | +pub async fn run<C>(controller: C) |
| 12 | +where |
| 13 | + C: Controller, |
| 14 | +{ |
| 15 | + // Using a fixed "random" address can be useful for testing. In real scenarios, one would |
| 16 | + // use e.g. the MAC 6 byte array as the address (how to get that varies by the platform). |
| 17 | + let address: Address = Address::random([0xff, 0x8f, 0x1b, 0x05, 0xe4, 0xff]); |
| 18 | + info!("Our address = {:?}", address); |
| 19 | + |
| 20 | + let mut resources: HostResources<DefaultPacketPool, CONNECTIONS_MAX, L2CAP_CHANNELS_MAX> = HostResources::new(); |
| 21 | + let stack = trouble_host::new(controller, &mut resources).set_random_address(address); |
| 22 | + let Host { mut runner, .. } = stack.build(); |
| 23 | + |
| 24 | + info!("Scanning for peripheral..."); |
| 25 | + // NOTE: Modify this to match the address of the peripheral you want to connect to. |
| 26 | + let fut1 = scan(&stack, [0xff, 0x8f, 0x1a, 0x05, 0xe4, 0xff]); |
| 27 | + let fut2 = scan(&stack, [0xff, 0x8f, 0x1a, 0x05, 0xe5, 0xff]); |
| 28 | + let _ = join3(runner.run(), fut1, fut2).await; |
| 29 | +} |
| 30 | + |
| 31 | +async fn scan<'a, C: Controller, P: PacketPool>(stack: &'a Stack<'a, C, P>, addr: [u8; 6]) { |
| 32 | + let Host { mut central, .. } = stack.build(); |
| 33 | + let target: Address = Address::random(addr); |
| 34 | + |
| 35 | + let config = ConnectConfig { |
| 36 | + connect_params: Default::default(), |
| 37 | + scan_config: ScanConfig { |
| 38 | + filter_accept_list: &[(target.kind, &target.addr)], |
| 39 | + ..Default::default() |
| 40 | + }, |
| 41 | + }; |
| 42 | + |
| 43 | + info!("Connecting to {:?}", addr); |
| 44 | + let conn = central.connect(&config).await.unwrap(); |
| 45 | + info!("Connected, creating gatt client"); |
| 46 | + |
| 47 | + let client = GattClient::<C, _, 10>::new(stack, &conn).await.unwrap(); |
| 48 | + |
| 49 | + let _ = join(client.task(), async { |
| 50 | + info!("Looking for battery service"); |
| 51 | + let services = client.services_by_uuid(&Uuid::new_short(0x180f)).await.unwrap(); |
| 52 | + let service = services.first().unwrap().clone(); |
| 53 | + |
| 54 | + info!("Looking for value handle"); |
| 55 | + let c: Characteristic<u8> = client |
| 56 | + .characteristic_by_uuid(&service, &Uuid::new_short(0x2a19)) |
| 57 | + .await |
| 58 | + .unwrap(); |
| 59 | + |
| 60 | + info!("Subscribing notifications"); |
| 61 | + let mut listener = client.subscribe(&c, false).await.unwrap(); |
| 62 | + |
| 63 | + let _ = join( |
| 64 | + async { |
| 65 | + loop { |
| 66 | + let mut data = [0; 1]; |
| 67 | + client.read_characteristic(&c, &mut data[..]).await.unwrap(); |
| 68 | + info!("Read value: {}", data[0]); |
| 69 | + Timer::after(Duration::from_secs(10)).await; |
| 70 | + } |
| 71 | + }, |
| 72 | + async { |
| 73 | + loop { |
| 74 | + let data = listener.next().await; |
| 75 | + info!("Got notification: {:?} (val: {})", data.as_ref(), data.as_ref()[0]); |
| 76 | + } |
| 77 | + }, |
| 78 | + ) |
| 79 | + .await; |
| 80 | + }) |
| 81 | + .await; |
| 82 | +} |
0 commit comments