Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a921ebd434 |
2 changed files with 25 additions and 78 deletions
94
src/ble.rs
94
src/ble.rs
|
|
@ -39,67 +39,16 @@ pub enum BleSendable {
|
||||||
SpatemRaw(io::msg::RawMsgRx),
|
SpatemRaw(io::msg::RawMsgRx),
|
||||||
}
|
}
|
||||||
|
|
||||||
// GAP + 4 GATT attributes + our service(s)
|
#[gatt_server]
|
||||||
const _ATTRIBUTE_TABLE_SIZE: usize = GAP_SERVICE_ATTRIBUTE_COUNT + 4 + CITSEvents::ATTRIBUTE_COUNT;
|
struct Server {
|
||||||
|
generic: Generic,
|
||||||
pub struct Server<'values> {
|
|
||||||
server: AttributeServer<
|
|
||||||
'values,
|
|
||||||
embassy_sync::blocking_mutex::raw::NoopRawMutex,
|
|
||||||
DefaultPacketPool,
|
|
||||||
_ATTRIBUTE_TABLE_SIZE,
|
|
||||||
1,
|
|
||||||
CONNECTIONS_MAX,
|
|
||||||
>,
|
|
||||||
c_its_events: CITSEvents,
|
c_its_events: CITSEvents,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'values> Server<'values> {
|
#[gatt_service(uuid = "1801")]
|
||||||
// we implement this ourselves to add the "SERVICE_CHANGED" GATT characteristic,
|
pub(crate) struct Generic {
|
||||||
// otherwise client devices won't update the service's characteristics when they change.
|
#[characteristic(uuid = characteristic::SERVICE_CHANGED, indicate, read, value = 0x0100FFFF)]
|
||||||
fn new_with_config(config: PeripheralConfig<'values>) -> Result<Self, &'static str> {
|
service_changed: u32,
|
||||||
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")]
|
#[gatt_service(uuid = "c0b70000-d4f4-4000-ada8-f99a02ee315c")]
|
||||||
|
|
@ -114,7 +63,7 @@ struct CITSEvents {
|
||||||
raw_notify: [u8; io::msg::RawNotify::PROTO_SIZE],
|
raw_notify: [u8; io::msg::RawNotify::PROTO_SIZE],
|
||||||
|
|
||||||
#[cfg(feature = "cam")]
|
#[cfg(feature = "cam")]
|
||||||
// #[descriptor(uuid = descriptors::MEASUREMENT_DESCRIPTION, name = "CAM", read, value = "RawMsgRx proto msg", type = &'static str)]
|
#[descriptor(uuid = descriptors::MEASUREMENT_DESCRIPTION, name = "CAM", read, value = "RawMsgRx proto msg", type = &'static str)]
|
||||||
#[characteristic(uuid = "c0b70001-d4f4-4003-ada8-f99a02ee315c", read, value = [0u8; io::msg::RawMsgRx::PROTO_SIZE])]
|
#[characteristic(uuid = "c0b70001-d4f4-4003-ada8-f99a02ee315c", read, value = [0u8; io::msg::RawMsgRx::PROTO_SIZE])]
|
||||||
cam_raw: [u8; io::msg::RawMsgRx::PROTO_SIZE],
|
cam_raw: [u8; io::msg::RawMsgRx::PROTO_SIZE],
|
||||||
#[cfg(feature = "cam")]
|
#[cfg(feature = "cam")]
|
||||||
|
|
@ -123,7 +72,7 @@ struct CITSEvents {
|
||||||
cam_event: [u8; io::msg::CamEvent::PROTO_SIZE],
|
cam_event: [u8; io::msg::CamEvent::PROTO_SIZE],
|
||||||
|
|
||||||
#[cfg(feature = "denm")]
|
#[cfg(feature = "denm")]
|
||||||
// #[descriptor(uuid = descriptors::MEASUREMENT_DESCRIPTION, name = "DENM", read, value = "RawMsgRx proto msg", type = &'static str)]
|
#[descriptor(uuid = descriptors::MEASUREMENT_DESCRIPTION, name = "DENM", read, value = "RawMsgRx proto msg", type = &'static str)]
|
||||||
#[characteristic(uuid = "c0b70001-d4f4-4005-ada8-f99a02ee315c", read, value = [0u8; io::msg::RawMsgRx::PROTO_SIZE])]
|
#[characteristic(uuid = "c0b70001-d4f4-4005-ada8-f99a02ee315c", read, value = [0u8; io::msg::RawMsgRx::PROTO_SIZE])]
|
||||||
denm_raw: [u8; io::msg::RawMsgRx::PROTO_SIZE],
|
denm_raw: [u8; io::msg::RawMsgRx::PROTO_SIZE],
|
||||||
#[cfg(feature = "denm")]
|
#[cfg(feature = "denm")]
|
||||||
|
|
@ -132,11 +81,11 @@ struct CITSEvents {
|
||||||
denm_event: [u8; io::msg::DenmEvent::PROTO_SIZE],
|
denm_event: [u8; io::msg::DenmEvent::PROTO_SIZE],
|
||||||
|
|
||||||
#[cfg(feature = "spat")]
|
#[cfg(feature = "spat")]
|
||||||
// #[descriptor(uuid = descriptors::MEASUREMENT_DESCRIPTION, name = "MAPEM", read, value = "RawMsgRx proto msg", type = &'static str)]
|
#[descriptor(uuid = descriptors::MEASUREMENT_DESCRIPTION, name = "MAPEM", read, value = "RawMsgRx proto msg", type = &'static str)]
|
||||||
#[characteristic(uuid = "c0b70001-d4f4-4007-ada8-f99a02ee315c", read, value = [0u8; io::msg::RawMsgRx::PROTO_SIZE])]
|
#[characteristic(uuid = "c0b70001-d4f4-4007-ada8-f99a02ee315c", read, value = [0u8; io::msg::RawMsgRx::PROTO_SIZE])]
|
||||||
mapem_raw: [u8; io::msg::RawMsgRx::PROTO_SIZE],
|
mapem_raw: [u8; io::msg::RawMsgRx::PROTO_SIZE],
|
||||||
#[cfg(feature = "spat")]
|
#[cfg(feature = "spat")]
|
||||||
// #[descriptor(uuid = descriptors::MEASUREMENT_DESCRIPTION, name = "SPATEM", read, value = "RawMsgRx proto msg", type = &'static str)]
|
#[descriptor(uuid = descriptors::MEASUREMENT_DESCRIPTION, name = "SPATEM", read, value = "RawMsgRx proto msg", type = &'static str)]
|
||||||
#[characteristic(uuid = "c0b70001-d4f4-4008-ada8-f99a02ee315c", read, value = [0u8; io::msg::RawMsgRx::PROTO_SIZE])]
|
#[characteristic(uuid = "c0b70001-d4f4-4008-ada8-f99a02ee315c", read, value = [0u8; io::msg::RawMsgRx::PROTO_SIZE])]
|
||||||
spatem_raw: [u8; io::msg::RawMsgRx::PROTO_SIZE],
|
spatem_raw: [u8; io::msg::RawMsgRx::PROTO_SIZE],
|
||||||
}
|
}
|
||||||
|
|
@ -167,7 +116,6 @@ pub async fn run(
|
||||||
esp_radio::ble::controller::BleConnector<'static>,
|
esp_radio::ble::controller::BleConnector<'static>,
|
||||||
CONTROLLER_SLOTS,
|
CONTROLLER_SLOTS,
|
||||||
>,
|
>,
|
||||||
name: alloc::string::String,
|
|
||||||
) {
|
) {
|
||||||
let mut resources: HostResources<DefaultPacketPool, CONNECTIONS_MAX, L2CAP_CHANNELS_MAX> =
|
let mut resources: HostResources<DefaultPacketPool, CONNECTIONS_MAX, L2CAP_CHANNELS_MAX> =
|
||||||
HostResources::new();
|
HostResources::new();
|
||||||
|
|
@ -193,18 +141,23 @@ pub async fn run(
|
||||||
"Starting advertising and GATT service for {}",
|
"Starting advertising and GATT service for {}",
|
||||||
features.join(",")
|
features.join(",")
|
||||||
);
|
);
|
||||||
let server = Server::new_with_config(PeripheralConfig {
|
let server = Server::new_with_config(GapConfig::Peripheral(PeripheralConfig {
|
||||||
name: &name,
|
name: "ESP32 C-ITS",
|
||||||
appearance: &appearance::UNKNOWN, // maybe appearance::outdoor_sports_activity::LOCATION_AND_NAVIGATION_DISPLAY ?
|
appearance: &appearance::UNKNOWN, // TODO MESH_DEVICE?? outdoor_sports_activity::LOCATION_AND_NAVIGATION_DISPLAY
|
||||||
})
|
}))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
let handle_start = 0x0100_u16; // little-endian
|
||||||
|
let handle_end = 0xFFFF_u16;
|
||||||
|
let concatenated: u32 = ((handle_start as u32) << 16) | handle_end as u32;
|
||||||
|
info!("Concatenated: {concatenated:?}");
|
||||||
|
let test = server.set(&server.generic.service_changed, &concatenated);
|
||||||
|
info!("We were able to set service changed? {test:?}");
|
||||||
|
|
||||||
let _ = embassy_futures::join::join(ble_task(runner), async {
|
let _ = embassy_futures::join::join(ble_task(runner), async {
|
||||||
loop {
|
loop {
|
||||||
match advertise(&mut peripheral, &server).await {
|
match advertise(&mut peripheral, &server).await {
|
||||||
Ok(conn) => {
|
Ok(conn) => {
|
||||||
info!("BLE: New client connected");
|
|
||||||
|
|
||||||
// set up tasks when the connection is established to a central, so they don't run when no one is connected.
|
// set up tasks when the connection is established to a central, so they don't run when no one is connected.
|
||||||
let a = gatt_events_task(&server, &conn);
|
let a = gatt_events_task(&server, &conn);
|
||||||
let b = publishing_task(&server, &conn);
|
let b = publishing_task(&server, &conn);
|
||||||
|
|
@ -247,7 +200,7 @@ async fn advertise<'values, 'server, C: Controller>(
|
||||||
server: &'server Server<'values>,
|
server: &'server Server<'values>,
|
||||||
) -> Result<GattConnection<'values, 'server, DefaultPacketPool>, BleHostError<C::Error>> {
|
) -> Result<GattConnection<'values, 'server, DefaultPacketPool>, BleHostError<C::Error>> {
|
||||||
let mut advertiser_data = [0; 35];
|
let mut advertiser_data = [0; 35];
|
||||||
let service_uuid = Uuid::from(0xc0b7_0000_d4f4_4000_ada8_f99a_02ee_315c_u128)
|
let service_uuid = Uuid::from(0xc0b70000d4f44000ada8f99a02ee315cu128)
|
||||||
.as_raw()
|
.as_raw()
|
||||||
.try_into()
|
.try_into()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
@ -255,6 +208,7 @@ async fn advertise<'values, 'server, C: Controller>(
|
||||||
&[
|
&[
|
||||||
AdStructure::Flags(LE_GENERAL_DISCOVERABLE | BR_EDR_NOT_SUPPORTED),
|
AdStructure::Flags(LE_GENERAL_DISCOVERABLE | BR_EDR_NOT_SUPPORTED),
|
||||||
AdStructure::ServiceUuids128(&[service_uuid]),
|
AdStructure::ServiceUuids128(&[service_uuid]),
|
||||||
|
AdStructure::ServiceUuids16(&[service::GATT.to_le_bytes()]),
|
||||||
],
|
],
|
||||||
&mut advertiser_data[..],
|
&mut advertiser_data[..],
|
||||||
)?;
|
)?;
|
||||||
|
|
|
||||||
|
|
@ -219,14 +219,7 @@ async fn main(spawner: Spawner) -> ! {
|
||||||
#[cfg(feature = "ble")]
|
#[cfg(feature = "ble")]
|
||||||
{
|
{
|
||||||
let controller = ble::make_controller(peripherals.BT);
|
let controller = ble::make_controller(peripherals.BT);
|
||||||
let serial = &mac.as_bytes()[4..7];
|
spawner.spawn(ble::run(controller).expect("Failed to spawn BLE task"));
|
||||||
let name = alloc::format!(
|
|
||||||
"ESP32 C-ITS {:02x}{:02x}{:02x}",
|
|
||||||
serial[0],
|
|
||||||
serial[1],
|
|
||||||
serial[2]
|
|
||||||
);
|
|
||||||
spawner.spawn(ble::run(controller, name).expect("Failed to spawn BLE task"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setup GNSS:
|
// Setup GNSS:
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue