Skip to content

Commit 0af97d0

Browse files
HaoboGululf
authored andcommitted
feat(example): add example for connecting to multiple peripherals
Signed-off-by: Haobo Gu <[email protected]>
1 parent 80e7056 commit 0af97d0

File tree

3 files changed

+133
-0
lines changed

3 files changed

+133
-0
lines changed
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
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+
}

examples/apps/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ pub(crate) mod fmt;
77
pub mod ble_advertise;
88
pub mod ble_advertise_multiple;
99
pub mod ble_bas_central;
10+
pub mod ble_bas_central_multiple;
1011
pub mod ble_bas_central_sec;
1112
pub mod ble_bas_peripheral;
1213
pub mod ble_bas_peripheral_sec;
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
#![no_std]
2+
#![no_main]
3+
4+
use embassy_executor::Spawner;
5+
use esp_hal::clock::CpuClock;
6+
use esp_hal::timer::timg::TimerGroup;
7+
use esp_radio::Controller;
8+
use esp_radio::ble::controller::BleConnector;
9+
use static_cell::StaticCell;
10+
use trouble_example_apps::ble_bas_central_multiple;
11+
use trouble_host::prelude::ExternalController;
12+
use {esp_alloc as _, esp_backtrace as _};
13+
14+
esp_bootloader_esp_idf::esp_app_desc!();
15+
16+
#[esp_hal_embassy::main]
17+
async fn main(_s: Spawner) {
18+
esp_println::logger::init_logger_from_env();
19+
let peripherals = esp_hal::init(esp_hal::Config::default().with_cpu_clock(CpuClock::max()));
20+
esp_alloc::heap_allocator!(size: 72 * 1024);
21+
let timg0 = TimerGroup::new(peripherals.TIMG0);
22+
23+
#[cfg(target_arch = "riscv32")]
24+
let software_interrupt = esp_hal::interrupt::software::SoftwareInterruptControl::new(peripherals.SW_INTERRUPT);
25+
26+
esp_preempt::start(
27+
timg0.timer0,
28+
#[cfg(target_arch = "riscv32")]
29+
software_interrupt.software_interrupt0,
30+
);
31+
32+
static RADIO: StaticCell<Controller<'static>> = StaticCell::new();
33+
let radio = RADIO.init(esp_radio::init().unwrap());
34+
35+
#[cfg(not(feature = "esp32"))]
36+
{
37+
let systimer = esp_hal::timer::systimer::SystemTimer::new(peripherals.SYSTIMER);
38+
esp_hal_embassy::init(systimer.alarm0);
39+
}
40+
#[cfg(feature = "esp32")]
41+
{
42+
esp_hal_embassy::init(timg0.timer1);
43+
}
44+
45+
let bluetooth = peripherals.BT;
46+
let connector = BleConnector::new(radio, bluetooth);
47+
let controller: ExternalController<_, 20> = ExternalController::new(connector);
48+
49+
ble_bas_central_multiple::run(controller).await;
50+
}

0 commit comments

Comments
 (0)