1
0
Fork 0
mirror of https://codeberg.org/icewind/mitemp-rs.git synced 2026-06-03 17:24:08 +02:00

get bdaddr from service data

This commit is contained in:
Robin Appelman 2021-10-31 18:22:04 +01:00
commit 68b7c2ddcc

View file

@ -1,12 +1,9 @@
pub use btleplug::api::BDAddr; pub use btleplug::api::BDAddr;
use btleplug::api::{Central, CentralEvent, Peripheral, ScanFilter}; use btleplug::api::{Central, CentralEvent, ScanFilter};
use btleplug::platform::PeripheralId;
use futures_util::{future::ready, StreamExt};
use num_enum::TryFromPrimitive; use num_enum::TryFromPrimitive;
use std::collections::HashMap; use std::collections::HashMap;
use std::convert::TryFrom; use std::convert::TryFrom;
use tokio_stream::{Stream, StreamExt};
use tokio_stream::Stream;
use uuid::Uuid; use uuid::Uuid;
/// Detected mitemp sensor and the data read from it /// Detected mitemp sensor and the data read from it
@ -55,29 +52,12 @@ pub async fn listen<'a, A: Central + 'static>(
adapter.start_scan(ScanFilter::default()).await?; adapter.start_scan(ScanFilter::default()).await?;
Ok(event_receiver Ok(event_receiver
.filter_map(|event| { .filter_map(|event| match event {
ready(match event { CentralEvent::ServiceDataAdvertisement { service_data, .. } => Some(service_data),
CentralEvent::ServiceDataAdvertisement { id, service_data } => {
Some((id, service_data))
}
_ => None, _ => None,
}) })
}) .filter_map(|mut service_data| service_data.remove(&UUID))
.filter_map(move |(id, service_data)| async move { .filter_map(|data| parse_advertising_data(&data).ok())
let addr = id_to_addr(adapter, id).await?;
Some((addr, service_data))
})
.filter_map(
|(bd_addr, mut service_data): (BDAddr, HashMap<Uuid, Vec<u8>>)| {
ready(service_data.remove(&UUID).map(move |data| (bd_addr, data)))
},
)
.filter_map(|(bd_addr, data)| {
ready(match parse_advertising_data(&data) {
Ok(update) => Some((bd_addr, update)),
_ => None,
})
})
.map(move |(bd_addr, update)| { .map(move |(bd_addr, update)| {
let sensor_data = sensors.entry(bd_addr).or_default(); let sensor_data = sensors.entry(bd_addr).or_default();
sensor_data.update(update); sensor_data.update(update);
@ -88,11 +68,6 @@ pub async fn listen<'a, A: Central + 'static>(
})) }))
} }
async fn id_to_addr<A: Central + 'static>(adapter: &A, id: PeripheralId) -> Option<BDAddr> {
let peripheral = adapter.peripheral(&id).await.ok()?;
Some(peripheral.address())
}
/// Collected data from a sensor /// Collected data from a sensor
/// ///
/// Because not all data is emitted at the same time, some fields might not be populated yet /// Because not all data is emitted at the same time, some fields might not be populated yet
@ -136,11 +111,21 @@ enum SensorUpdate {
struct InvalidServiceData; struct InvalidServiceData;
fn parse_advertising_data(service_data: &[u8]) -> Result<SensorUpdate, InvalidServiceData> { fn parse_advertising_data(
service_data: &[u8],
) -> Result<(BDAddr, SensorUpdate), InvalidServiceData> {
let sensor_type = &service_data[1..4]; let sensor_type = &service_data[1..4];
if sensor_type != [0x20, 0xaa, 0x01] { if sensor_type != [0x20, 0xaa, 0x01] {
return Err(InvalidServiceData); return Err(InvalidServiceData);
} }
let addr = BDAddr::from([
service_data[10],
service_data[9],
service_data[8],
service_data[7],
service_data[6],
service_data[5],
]);
let sensor_type = SensorType::try_from(service_data[11]).map_err(|_| InvalidServiceData)?; let sensor_type = SensorType::try_from(service_data[11]).map_err(|_| InvalidServiceData)?;
let data_length = service_data[13] as usize; let data_length = service_data[13] as usize;
@ -149,7 +134,9 @@ fn parse_advertising_data(service_data: &[u8]) -> Result<SensorUpdate, InvalidSe
} }
let sensor_data = &service_data[14..14 + data_length]; let sensor_data = &service_data[14..14 + data_length];
Ok(match sensor_type { Ok((
addr,
match sensor_type {
SensorType::Battery => SensorUpdate::Battery(sensor_data[0]), SensorType::Battery => SensorUpdate::Battery(sensor_data[0]),
SensorType::Temperature => { SensorType::Temperature => {
SensorUpdate::Temperature(i16::from_le_bytes([sensor_data[0], sensor_data[1]])) SensorUpdate::Temperature(i16::from_le_bytes([sensor_data[0], sensor_data[1]]))
@ -161,5 +148,6 @@ fn parse_advertising_data(service_data: &[u8]) -> Result<SensorUpdate, InvalidSe
i16::from_le_bytes([sensor_data[0], sensor_data[1]]), i16::from_le_bytes([sensor_data[0], sensor_data[1]]),
u16::from_le_bytes([sensor_data[2], sensor_data[3]]), u16::from_le_bytes([sensor_data[2], sensor_data[3]]),
), ),
}) },
))
} }