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

adjust to new btleplug

This commit is contained in:
Robin Appelman 2021-03-06 12:52:07 +01:00
commit b2e39d8893
2 changed files with 32 additions and 19 deletions

View file

@ -7,9 +7,9 @@ description = "Read Xiaomi MI Temperature and Humidity Sensor over BLE"
license = "MIT/Apache-2.0" license = "MIT/Apache-2.0"
[dependencies] [dependencies]
btleplug = { version = "0.5.0", git = "https://github.com/icewind1991/btleplug", branch = "store-service-data" } btleplug = { version = "0.7", git = "https://github.com/icewind1991/btleplug", branch = "unify-platform-api" }
num_enum = "0.4.2" num_enum = "0.4"
[dev-dependencies] [dev-dependencies]
main_error = "0.1.0" main_error = "0.1"
env_logger = "0.7.1" env_logger = "0.7"

View file

@ -1,11 +1,11 @@
pub use btleplug::api::BDAddr; pub use btleplug::api::BDAddr;
use btleplug::api::{Central, CentralEvent, Peripheral}; use btleplug::api::{Central, CentralEvent, Peripheral};
use btleplug::bluez::adapter::ConnectedAdapter; use btleplug::platform::{Adapter, Manager};
use btleplug::bluez::manager::Manager;
use num_enum::TryFromPrimitive; use num_enum::TryFromPrimitive;
use std::collections::HashMap; use std::collections::HashMap;
use std::convert::TryFrom; use std::convert::TryFrom;
/// Detected mitemp sensor and the data read from it
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct Sensor { pub struct Sensor {
pub mac: BDAddr, pub mac: BDAddr,
@ -33,7 +33,10 @@ impl SensorRawData {
} }
} }
pub fn listen<P: Peripheral, A: Central<P> + 'static>( /// Listen for sensor data
///
/// Returns an iterator that will block waiting for new sensor data
pub fn listen<A: Central + 'static>(
adapter: A, adapter: A,
) -> Result<impl Iterator<Item = Sensor>, btleplug::Error> { ) -> Result<impl Iterator<Item = Sensor>, btleplug::Error> {
let mut sensors: HashMap<BDAddr, SensorRawData> = HashMap::new(); let mut sensors: HashMap<BDAddr, SensorRawData> = HashMap::new();
@ -51,13 +54,13 @@ pub fn listen<P: Peripheral, A: Central<P> + 'static>(
} }
_ => None, _ => None,
}) })
.flat_map(move |bd_addr| { .filter_map(move |bd_addr| adapter.peripheral(bd_addr))
let peripheral = adapter.peripheral(bd_addr).unwrap(); .flat_map(|peripheral| {
peripheral peripheral
.properties() .properties()
.service_data .service_data
.into_iter() .into_iter()
.map(move |(_, data)| (bd_addr, data)) .map(move |(_, data)| (peripheral.address(), data))
}) })
.filter_map(|(bd_addr, data)| Some((bd_addr, parse_advertising_data(&data).ok()?))) .filter_map(|(bd_addr, data)| Some((bd_addr, parse_advertising_data(&data).ok()?)))
.map(move |(bd_addr, update)| { .map(move |(bd_addr, update)| {
@ -70,10 +73,17 @@ pub fn listen<P: Peripheral, A: Central<P> + 'static>(
})) }))
} }
/// Collected data from a sensor
///
/// Because not all data is emitted at the same time, some fields might not be populated yet
/// in which case they are set to 0
#[derive(Default, Clone, Debug)] #[derive(Default, Clone, Debug)]
pub struct SensorData { pub struct SensorData {
/// Battery percentage
pub battery: u8, pub battery: u8,
/// Temperature in °C
pub temperature: f32, pub temperature: f32,
/// Humidity in %H
pub humidity: f32, pub humidity: f32,
} }
@ -87,16 +97,19 @@ impl From<SensorRawData> for SensorData {
} }
} }
pub fn adapter_by_mac(addr: BDAddr) -> Result<ConnectedAdapter, btleplug::Error> { pub fn adapter_by_mac(addr: BDAddr) -> Result<Adapter, btleplug::Error> {
let manager = Manager::new()?; let manager = Manager::new()?;
let adapters = manager.adapters()?; manager
.adapters()?
let adapter = adapters
.into_iter() .into_iter()
.find(|adapter| adapter.addr == addr) .find(|adapter| {
.ok_or(btleplug::Error::DeviceNotFound)?; adapter
.address()
adapter.connect() .ok()
.filter(|adapter_addr| *adapter_addr == addr)
.is_some()
})
.ok_or(btleplug::Error::DeviceNotFound)
} }
#[derive(Debug, Eq, PartialEq, TryFromPrimitive, Clone, Copy)] #[derive(Debug, Eq, PartialEq, TryFromPrimitive, Clone, Copy)]
@ -120,7 +133,7 @@ struct InvalidServiceData;
fn parse_advertising_data(service_data: &[u8]) -> Result<SensorUpdate, InvalidServiceData> { fn parse_advertising_data(service_data: &[u8]) -> Result<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 sensor_type = SensorType::try_from(service_data[11]).map_err(|_| InvalidServiceData)?; let sensor_type = SensorType::try_from(service_data[11]).map_err(|_| InvalidServiceData)?;