btleplug/winrtble/ble/
watcher.rs1use crate::{api::ScanFilter, Error, Result};
15use windows::{core::Ref, Devices::Bluetooth::Advertisement::*, Foundation::TypedEventHandler};
16
17pub type AdvertisementEventHandler =
18 Box<dyn Fn(&BluetoothLEAdvertisementReceivedEventArgs) -> windows::core::Result<()> + Send>;
19
20#[derive(Debug)]
21pub struct BLEWatcher {
22 watcher: BluetoothLEAdvertisementWatcher,
23}
24
25impl From<windows::core::Error> for Error {
26 fn from(err: windows::core::Error) -> Error {
27 Error::Other(format!("{:?}", err).into())
28 }
29}
30
31impl BLEWatcher {
32 pub fn new() -> Result<Self> {
33 let ad = BluetoothLEAdvertisementFilter::new()?;
34 let watcher = BluetoothLEAdvertisementWatcher::Create(&ad)?;
35 Ok(BLEWatcher { watcher })
36 }
37
38 pub fn start(&self, filter: ScanFilter, on_received: AdvertisementEventHandler) -> Result<()> {
39 let ScanFilter { services } = filter;
40 let ad = self.watcher.AdvertisementFilter()?.Advertisement()?;
41 let ad_services = ad.ServiceUuids()?;
42 ad_services.Clear()?;
43 for service in services {
44 ad_services.Append(windows::core::GUID::from(service.as_u128()))?;
45 }
46 self.watcher
47 .SetScanningMode(BluetoothLEScanningMode::Active)?;
48 let _ = self.watcher.SetAllowExtendedAdvertisements(true);
49 let handler: TypedEventHandler<
50 BluetoothLEAdvertisementWatcher,
51 BluetoothLEAdvertisementReceivedEventArgs,
52 > = TypedEventHandler::new(
53 move |_sender, args: Ref<BluetoothLEAdvertisementReceivedEventArgs>| {
54 if let Ok(args) = args.ok() {
55 on_received(args)?;
56 }
57 Ok(())
58 },
59 );
60
61 self.watcher.Received(&handler)?;
62 self.watcher.Start()?;
63 Ok(())
64 }
65
66 pub fn stop(&self) -> Result<()> {
67 self.watcher.Stop()?;
68 Ok(())
69 }
70}