-
-
Notifications
You must be signed in to change notification settings - Fork 188
Expand file tree
/
Copy pathadapter.rs
More file actions
148 lines (131 loc) · 4.79 KB
/
adapter.rs
File metadata and controls
148 lines (131 loc) · 4.79 KB
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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
// btleplug Source Code File
//
// Copyright 2020 Nonpolynomial Labs LLC. All rights reserved.
//
// Licensed under the BSD 3-Clause license. See LICENSE file in the project root
// for full license information.
//
// Some portions of this file are taken and/or modified from Rumble
// (https://github.com/mwylde/rumble), using a dual MIT/Apache License under the
// following copyright:
//
// Copyright (c) 2014 The Rust Project Developers
use super::{ble::watcher::BLEWatcher, peripheral::Peripheral, peripheral::PeripheralId};
use crate::{
api::{BDAddr, Central, CentralEvent, CentralState, ScanFilter},
common::adapter_manager::AdapterManager,
Error, Result,
};
use async_trait::async_trait;
use futures::stream::Stream;
use log::debug;
use std::convert::TryInto;
use std::fmt::{self, Debug, Formatter};
use std::pin::Pin;
use std::sync::{Arc, Mutex};
use windows::{
Devices::{Bluetooth::BluetoothAdapter, Radios::{Radio, RadioState}},
Foundation::TypedEventHandler,
};
/// Implementation of [api::Central](crate::api::Central).
#[derive(Clone)]
pub struct Adapter {
watcher: Arc<Mutex<BLEWatcher>>,
manager: Arc<AdapterManager<Peripheral>>,
radio: Radio,
adapter: BluetoothAdapter,
}
// https://github.com/microsoft/windows-rs/blob/master/crates/libs/windows/src/Windows/Devices/Radios/mod.rs
fn get_central_state(radio: &Radio) -> CentralState {
let state = radio.State().unwrap_or(RadioState::Unknown);
match state {
RadioState::On => CentralState::PoweredOn,
RadioState::Off => CentralState::PoweredOff,
_ => CentralState::Unknown,
}
}
impl Adapter {
pub(crate) async fn new(adapter: BluetoothAdapter) -> Result<Self> {
let radio = adapter.GetRadioAsync()?.await?;
let watcher = Arc::new(Mutex::new(BLEWatcher::new()?));
let manager = Arc::new(AdapterManager::default());
let radio_clone = radio.clone();
let manager_clone = manager.clone();
let handler = TypedEventHandler::new(move |_sender, _args| {
let state = get_central_state(&radio_clone);
manager_clone.emit(CentralEvent::StateUpdate(state.into()));
Ok(())
});
if let Err(err) = radio.StateChanged(&handler) {
eprintln!("radio.StateChanged error: {}", err);
}
Ok(Adapter {
watcher,
manager,
radio,
adapter,
})
}
}
impl Debug for Adapter {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
f.debug_struct("Adapter")
.field("manager", &self.manager)
.finish()
}
}
#[async_trait]
impl Central for Adapter {
type Peripheral = Peripheral;
async fn events(&self) -> Result<Pin<Box<dyn Stream<Item = CentralEvent> + Send>>> {
Ok(self.manager.event_stream())
}
async fn start_scan(&self, filter: ScanFilter) -> Result<()> {
let watcher = self.watcher.lock().map_err(Into::<Error>::into)?;
let manager = self.manager.clone();
watcher.start(
filter,
Box::new(move |args| {
let bluetooth_address = args.BluetoothAddress()?;
let address: BDAddr = bluetooth_address.try_into().unwrap();
if let Some(mut entry) = manager.peripheral_mut(&address.into()) {
entry.value_mut().update_properties(args);
manager.emit(CentralEvent::DeviceUpdated(address.into()));
} else {
let peripheral = Peripheral::new(Arc::downgrade(&manager), address);
peripheral.update_properties(args);
manager.add_peripheral(peripheral);
manager.emit(CentralEvent::DeviceDiscovered(address.into()));
}
Ok(())
}),
)
}
async fn stop_scan(&self) -> Result<()> {
let watcher = self.watcher.lock().map_err(Into::<Error>::into)?;
watcher.stop()?;
Ok(())
}
async fn peripherals(&self) -> Result<Vec<Peripheral>> {
Ok(self.manager.peripherals())
}
async fn peripheral(&self, id: &PeripheralId) -> Result<Peripheral> {
self.manager.peripheral(id).ok_or(Error::DeviceNotFound)
}
async fn add_peripheral(&self, _address: &PeripheralId) -> Result<Peripheral> {
Err(Error::NotSupported(
"Can't add a Peripheral from a BDAddr".to_string(),
))
}
async fn adapter_info(&self) -> Result<String> {
Ok(format!("DeviceId: {}\n", self.adapter.DeviceId()?.to_string()))
}
async fn adapter_mac(&self) -> Result<BDAddr> {
let address = self.adapter.BluetoothAddress()?;
let mac = BDAddr::try_from(address)?;
Ok(mac)
}
async fn adapter_state(&self) -> Result<CentralState> {
Ok(get_central_state(&self.radio))
}
}