forked from deviceplug/btleplug
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathadapter.rs
157 lines (142 loc) · 5.37 KB
/
adapter.rs
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
149
150
151
152
153
154
155
156
157
use super::internal::{
run_corebluetooth_thread, CoreBluetoothEvent, CoreBluetoothMessage, CoreBluetoothReply,
CoreBluetoothReplyFuture,
};
use super::peripheral::{Peripheral, PeripheralId};
use crate::api::{Central, CentralEvent, CentralState, ScanFilter};
use crate::common::adapter_manager::AdapterManager;
use crate::{Error, Result};
use async_trait::async_trait;
use futures::channel::mpsc::{self, Sender};
use futures::sink::SinkExt;
use futures::stream::{Stream, StreamExt};
use log::*;
use objc2_core_bluetooth::CBManagerState;
use std::pin::Pin;
use std::sync::Arc;
use tokio::task;
/// Implementation of [api::Central](crate::api::Central).
#[derive(Clone, Debug)]
pub struct Adapter {
manager: Arc<AdapterManager<Peripheral>>,
sender: Sender<CoreBluetoothMessage>,
}
fn get_central_state(state: CBManagerState) -> CentralState {
match state {
CBManagerState::PoweredOn => CentralState::PoweredOn,
CBManagerState::PoweredOff => CentralState::PoweredOff,
_ => CentralState::Unknown,
}
}
impl Adapter {
pub(crate) async fn new() -> Result<Self> {
let (sender, mut receiver) = mpsc::channel(256);
let adapter_sender = run_corebluetooth_thread(sender)?;
// Since init currently blocked until the state update, we know the
// receiver is dropped after that. We can pick it up here and make it
// part of our event loop to update our peripherals.
debug!("Waiting on adapter connect");
if !matches!(
receiver.next().await,
Some(CoreBluetoothEvent::DidUpdateState { state: _ })
) {
return Err(Error::Other(
"Adapter failed to connect.".to_string().into(),
));
}
debug!("Adapter connected");
let manager = Arc::new(AdapterManager::default());
let manager_clone = manager.clone();
let adapter_sender_clone = adapter_sender.clone();
task::spawn(async move {
while let Some(msg) = receiver.next().await {
match msg {
CoreBluetoothEvent::DeviceDiscovered {
uuid,
name,
event_receiver,
} => {
manager_clone.add_peripheral(Peripheral::new(
uuid,
name,
Arc::downgrade(&manager_clone),
event_receiver,
adapter_sender_clone.clone(),
));
manager_clone.emit(CentralEvent::DeviceDiscovered(uuid.into()));
}
CoreBluetoothEvent::DeviceUpdated { uuid, name } => {
let id = uuid.into();
if let Some(entry) = manager_clone.peripheral_mut(&id) {
entry.value().update_name(&name);
manager_clone.emit(CentralEvent::DeviceUpdated(id));
}
}
CoreBluetoothEvent::DeviceDisconnected { uuid } => {
manager_clone.emit(CentralEvent::DeviceDisconnected(uuid.into()));
}
CoreBluetoothEvent::DidUpdateState { state } => {
let central_state = get_central_state(state);
manager_clone.emit(CentralEvent::StateUpdate(central_state));
}
}
}
});
Ok(Adapter {
manager,
sender: adapter_sender,
})
}
}
#[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<()> {
self.sender
.to_owned()
.send(CoreBluetoothMessage::StartScanning { filter })
.await?;
Ok(())
}
async fn stop_scan(&self) -> Result<()> {
self.sender
.to_owned()
.send(CoreBluetoothMessage::StopScanning)
.await?;
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 PeripheralId".to_string(),
))
}
async fn adapter_info(&self) -> Result<String> {
// TODO: Get information about the adapter.
Ok("CoreBluetooth".to_string())
}
async fn adapter_state(&self) -> Result<CentralState> {
let fut = CoreBluetoothReplyFuture::default();
self.sender
.to_owned()
.send(CoreBluetoothMessage::GetAdapterState {
future: fut.get_state_clone(),
})
.await?;
match fut.await {
CoreBluetoothReply::AdapterState(state) => {
let central_state = get_central_state(state);
return Ok(central_state.clone());
}
_ => panic!("Shouldn't get anything but a AdapterState!"),
}
}
}