Skip to content

Commit

Permalink
Merge pull request #102 from pferreir/add-notifs
Browse files Browse the repository at this point in the history
Add possibility to listen to notifications
  • Loading branch information
lulf authored Sep 11, 2024
2 parents 29dabe7 + 1c5426a commit 0e0d942
Show file tree
Hide file tree
Showing 11 changed files with 425 additions and 65 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
**/target
Cargo.lock
58 changes: 43 additions & 15 deletions examples/apps/src/ble_bas_central.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
use embassy_futures::join::join;
use embassy_sync::blocking_mutex::raw::NoopRawMutex;
use embassy_time::{Duration, Timer};
use static_cell::StaticCell;
use trouble_host::attribute::Uuid;
use trouble_host::connection::ConnectConfig;
use trouble_host::packet_pool::PacketPool;
use trouble_host::scan::ScanConfig;
use trouble_host::{Address, BleHost, BleHostResources, Controller, PacketQos};

Expand Down Expand Up @@ -39,27 +41,53 @@ where

info!("Scanning for peripheral...");
let _ = join(ble.run(), async {
static PACKET_POOL: StaticCell<PacketPool<NoopRawMutex, 24, 64, 1>> = StaticCell::new();
let packet_pool = PACKET_POOL.init(PacketPool::new(PacketQos::None));

info!("Connecting");

let conn = ble.connect(&config).await.unwrap();
info!("Connected, creating gatt client");

let mut client = ble.gatt_client::<10, 128>(&conn).await.unwrap();
let client = ble.gatt_client::<10, 64, 16, 24>(&conn, packet_pool).await.unwrap();

let _ = join(client.task(), async {
info!("Looking for battery service");
let services = client.services_by_uuid(&Uuid::new_short(0x180f)).await.unwrap();
let service = services.first().unwrap().clone();

info!("Looking for battery service");
let services = client.services_by_uuid(&Uuid::new_short(0x180f)).await.unwrap();
let service = services.first().unwrap().clone();
info!("Looking for value handle");
let c = client
.characteristic_by_uuid(&service, &Uuid::new_short(0x2a19))
.await
.unwrap();

info!("Looking for value handle");
let c = client
.characteristic_by_uuid(&service, &Uuid::new_short(0x2a19))
.await
.unwrap();
info!("Subscribing notifications");
let mut listener = client.subscribe(&c, false).await.unwrap();

loop {
let mut data = [0; 1];
client.read_characteristic(&c, &mut data[..]).await.unwrap();
info!("Read value: {}", data[0]);
Timer::after(Duration::from_secs(10)).await;
}
let _ = join(
async {
loop {
let mut data = [0; 1];
client.read_characteristic(&c, &mut data[..]).await.unwrap();
info!("Read value: {}", data[0]);
Timer::after(Duration::from_secs(10)).await;
}
},
async {
loop {
let (len, data) = listener.next().await;
info!(
"Got notification: {:?} (val: {})",
&data.as_ref()[..len as usize],
data.as_ref()[0]
);
}
},
)
.await;
})
.await;
})
.await;
}
2 changes: 1 addition & 1 deletion examples/rp-pico-w/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ edition = "2021"
resolver = "2"

[dependencies]
embassy-executor = { version = "0.6", default-features = false, features = ["task-arena-size-65536", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers", "executor-interrupt"] }
embassy-executor = { version = "0.6", default-features = false, features = ["task-arena-size-98304", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers", "executor-interrupt"] }
embassy-time = { version = "0.3.0", default-features = false, features = ["defmt", "defmt-timestamp-uptime"] }
embassy-rp = { version = "0.2.0", features = ["defmt", "unstable-pac", "time-driver", "critical-section-impl", "rp2040"] }
embassy-futures = "0.1.1"
Expand Down
56 changes: 56 additions & 0 deletions examples/rp-pico-w/src/bin/ble_bas_central.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#![no_std]
#![no_main]

use bt_hci::controller::ExternalController;
use cyw43_pio::PioSpi;
use defmt::*;
use embassy_executor::Spawner;
use embassy_rp::bind_interrupts;
use embassy_rp::gpio::{Level, Output};
use embassy_rp::peripherals::{DMA_CH0, PIO0};
use embassy_rp::pio::{InterruptHandler, Pio};
use static_cell::StaticCell;
use trouble_example_apps::ble_bas_central;
use {defmt_rtt as _, embassy_time as _, panic_probe as _};

bind_interrupts!(struct Irqs {
PIO0_IRQ_0 => InterruptHandler<PIO0>;
});

#[embassy_executor::task]
async fn cyw43_task(runner: cyw43::Runner<'static, Output<'static>, PioSpi<'static, PIO0, 0, DMA_CH0>>) -> ! {
runner.run().await
}

#[embassy_executor::main]
async fn main(spawner: Spawner) {
let p = embassy_rp::init(Default::default());

//
// IMPORTANT
//
// Download and make sure these files from https://github.com/embassy-rs/embassy/tree/main/cyw43-firmware
// are available in the below path.
//
// IMPORTANT
//

let fw = include_bytes!("../../cyw43-firmware/43439A0.bin");
let clm = include_bytes!("../../cyw43-firmware/43439A0_clm.bin");
let btfw = include_bytes!("../../cyw43-firmware/43439A0_btfw.bin");

let pwr = Output::new(p.PIN_23, Level::Low);
let cs = Output::new(p.PIN_25, Level::High);
let mut pio = Pio::new(p.PIO0, Irqs);
let spi = PioSpi::new(&mut pio.common, pio.sm0, pio.irq0, cs, p.PIN_24, p.PIN_29, p.DMA_CH0);

static STATE: StaticCell<cyw43::State> = StaticCell::new();
let state = STATE.init(cyw43::State::new());
let (_net_device, bt_device, mut control, runner) = cyw43::new_with_bluetooth(state, pwr, spi, fw, btfw).await;
unwrap!(spawner.spawn(cyw43_task(runner)));
control.init(clm).await;

let controller: ExternalController<_, 10> = ExternalController::new(bt_device);

ble_bas_central::run(controller).await;
}
42 changes: 40 additions & 2 deletions host/src/attribute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use embassy_sync::blocking_mutex::raw::RawMutex;
use embassy_sync::blocking_mutex::Mutex;

use crate::att::AttErrorCode;
use crate::cursor::WriteCursor;
use crate::cursor::{ReadCursor, WriteCursor};
pub use crate::types::uuid::Uuid;
use crate::Error;

Expand Down Expand Up @@ -211,6 +211,15 @@ impl<'d> AttributeData<'d> {
_ => Err(AttErrorCode::WriteNotPermitted),
}
}

pub fn decode_declaration(data: &[u8]) -> Result<Self, Error> {
let mut r = ReadCursor::new(data);
Ok(Self::Declaration {
props: CharacteristicProps(r.read()?),
handle: r.read()?,
uuid: Uuid::from_slice(r.remaining()),
})
}
}

impl<'a> fmt::Debug for Attribute<'a> {
Expand Down Expand Up @@ -614,7 +623,7 @@ impl<const T: usize> From<[CharacteristicProp; T]> for CharacteristicProps {
}

impl CharacteristicProps {
fn any(&self, props: &[CharacteristicProp]) -> bool {
pub fn any(&self, props: &[CharacteristicProp]) -> bool {
for p in props {
if (*p as u8) & self.0 != 0 {
return true;
Expand All @@ -629,3 +638,32 @@ pub struct AttributeValue<'d, M: RawMutex> {
}

impl<'d, M: RawMutex> AttributeValue<'d, M> {}

#[derive(Clone, Copy)]
pub enum CCCDFlag {
Notify = 0x1,
Indicate = 0x2,
}

pub struct CCCD(pub(crate) u16);

impl<const T: usize> From<[CCCDFlag; T]> for CCCD {
fn from(props: [CCCDFlag; T]) -> Self {
let mut val: u16 = 0;
for prop in props {
val |= prop as u16;
}
CCCD(val)
}
}

impl CCCD {
pub fn any(&self, props: &[CCCDFlag]) -> bool {
for p in props {
if (*p as u16) & self.0 != 0 {
return true;
}
}
false
}
}
2 changes: 1 addition & 1 deletion host/src/channel_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -449,7 +449,7 @@ impl<'d, const RXQ: usize> ChannelManager<'d, RXQ> {
for (idx, storage) in state.channels.iter_mut().enumerate() {
if cid == storage.cid {
storage.state = ChannelState::PeerDisconnecting;
let _ = self.inbound[idx as usize].close();
let _ = self.inbound[idx].close();
state.disconnect_waker.wake();
break;
}
Expand Down
Loading

0 comments on commit 0e0d942

Please sign in to comment.