1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
use std::sync::mpsc::Receiver;
use btleplug::api::{BDAddr, Central, CentralEvent, Peripheral};
use btleplug::bluez::adapter::ConnectedAdapter;
use btleplug::bluez::manager::Manager;
pub use btleplug::Error as BleError;
pub use ruuvi_sensor_protocol::{ParseError, SensorValues};
pub struct BleAdapter {
adapter: ConnectedAdapter,
}
impl BleAdapter {
pub fn connect() -> Result<Self, BleError> {
let manager = Manager::new()?;
let adapter = manager.adapters()?.pop().ok_or(BleError::DeviceNotFound)?;
let adapter = adapter.connect()?;
adapter.active(false);
adapter.filter_duplicates(false);
Ok(BleAdapter { adapter })
}
pub fn start_scan(self) -> Result<ScanResults, BleError> {
self.adapter.start_scan()?;
let receiver = self.adapter.event_receiver().unwrap();
Ok(ScanResults {
adapter: self.adapter,
receiver,
})
}
}
pub struct ScanResults {
adapter: ConnectedAdapter,
receiver: Receiver<CentralEvent>,
}
impl Iterator for ScanResults {
type Item = Result<SensorValues, ParseError>;
fn next(&mut self) -> Option<Result<SensorValues, ParseError>> {
loop {
let event = self.receiver.iter().next();
if let Some(event) = event {
match event {
CentralEvent::DeviceDiscovered(address)
| CentralEvent::DeviceUpdated(address) => {
match parse_sensor_data(&self.adapter, address) {
Some(data) => return Some(data),
None => continue,
}
}
_ => continue,
}
};
return None;
}
}
}
fn parse_sensor_data(
adapter: &ConnectedAdapter,
address: BDAddr,
) -> Option<Result<SensorValues, ParseError>> {
let data = adapter
.peripheral(address)
.map(|peripheral| peripheral.properties().manufacturer_data)
.flatten();
if let Some(data) = data {
if data.len() > 2 {
let id = ((data[1] as u16) << 8) | data[0] as u16;
return match SensorValues::from_manufacturer_specific_data(id, &data[2..]) {
Ok(sensor_values) => Some(Ok(sensor_values)),
Err(err) => match err {
ParseError::UnknownManufacturerId(_) => None,
err => Some(Err(err)),
},
};
}
}
None
}