Watch
0
0
Fork
You've already forked esp32-c_its-companion
0

Compare commits

..
Author SHA1 Message Date
Jannik Beyerstedt
0fedbe7398 BLE: Add "service change attribute" 2026-08-24 15:25:01 +02:00

View file

@ -39,11 +39,69 @@ pub enum BleSendable {
SpatemRaw(io::msg::RawMsgRx),
}
#[gatt_server]
struct Server {
// GAP + 4 GATT attributes + our service(s)
const _ATTRIBUTE_TABLE_SIZE: usize = GAP_SERVICE_ATTRIBUTE_COUNT + 4 + CITSEvents::ATTRIBUTE_COUNT;
pub struct Server<'values> {
server: AttributeServer<
'values,
embassy_sync::blocking_mutex::raw::NoopRawMutex,
DefaultPacketPool,
_ATTRIBUTE_TABLE_SIZE,
1,
CONNECTIONS_MAX,
>,
c_its_events: CITSEvents,
}
impl<'values> Server<'values> {
// we implement this ourselves to add the "SERVICE_CHANGED" GATT characteristic,
// otherwise client devices won't update the service's characteristics when they change.
fn new_with_config(config: PeripheralConfig<'values>) -> Result<Self, &'static str> {
let mut table: AttributeTable<
'_,
embassy_sync::blocking_mutex::raw::NoopRawMutex,
_ATTRIBUTE_TABLE_SIZE,
> = AttributeTable::new();
// manual implementation of: gap.build(&mut table)?;
if !config.name.is_ascii() || config.name.len() > 22 {
return Err("Device name is too long. Max length is 22 bytes");
}
let mut gap_builder = table.add_service(Service::new(service::GAP));
gap_builder.add_characteristic_ro(characteristic::DEVICE_NAME, config.name.as_bytes());
gap_builder.add_characteristic_ro(characteristic::APPEARANCE, config.appearance);
gap_builder.build();
// add custom GATT service
let mut gatt_builder = table.add_service(Service::new(service::GATT));
gatt_builder.add_characteristic_ro(characteristic::SERVICE_CHANGED, &[1, 0, 255, 255]); // [0x0001, 0xFFFF] in little-endian
gatt_builder.build();
let c_its_events = CITSEvents::new(&mut table);
Ok(Self {
server: AttributeServer::new(table),
c_its_events,
})
}
}
impl<'values> core::ops::Deref for Server<'values> {
type Target = AttributeServer<
'values,
embassy_sync::blocking_mutex::raw::NoopRawMutex,
DefaultPacketPool,
_ATTRIBUTE_TABLE_SIZE,
1,
CONNECTIONS_MAX,
>;
fn deref(&self) -> &Self::Target {
&self.server
}
}
#[gatt_service(uuid = "c0b70000-d4f4-4000-ada8-f99a02ee315c")]
struct CITSEvents {
#[descriptor(uuid = descriptors::MEASUREMENT_DESCRIPTION, name = "Position", read, value = "PositionState proto msg", type = &'static str)]
@ -135,10 +193,10 @@ pub async fn run(
"Starting advertising and GATT service for {}",
features.join(",")
);
let server = Server::new_with_config(GapConfig::Peripheral(PeripheralConfig {
let server = Server::new_with_config(PeripheralConfig {
name: &name,
appearance: &appearance::UNKNOWN,
}))
})
.unwrap();
let _ = embassy_futures::join::join(ble_task(runner), async {