1use std::collections::{HashMap, HashSet};
4use std::marker::PhantomData;
5
6use bluer::{AdapterEvent, DeviceProperty};
7use futures::FutureExt;
8use futures::StreamExt;
9
10impl super::BluetoothRfcommConnectableTrait for bluer::rfcomm::ConnectRequest {
11 async fn accept(self) -> Result<crate::BluetoothStream, String> {
12 bluer::rfcomm::ConnectRequest::accept(self)
13 .map(|a| crate::BluetoothStream::Bluez(Box::pin(a)))
14 .map_err(|e| e.to_string())
15 }
16}
17
18impl super::BluetoothRfcommProfileTrait for bluer::rfcomm::ProfileHandle {
19 async fn connectable(&mut self) -> Result<crate::BluetoothRfcommConnectable,String> {
20 self.next().await.map(|a|a.into()).ok_or("Failed to get bluetooth connection".to_string())
21 }
22}
23
24impl super::BluetoothDeviceTrait for bluer::Device {
25 #[doc = " Get all known uuids for this device"]
26 fn get_uuids(&mut self) -> Result<Vec<crate::BluetoothUuid>, std::io::Error> {
27 todo!()
28 }
29
30 #[doc = " Retrieve the device name"]
31 fn get_name(&self) -> Result<String, std::io::Error> {
32 todo!()
33 }
34
35 #[doc = " Retrieve the device address"]
36 fn get_address(&mut self) -> Result<String, std::io::Error> {
37 todo!()
38 }
39
40 #[doc = " Retrieve the device pairing (bonding) status"]
41 fn get_pair_state(&self) -> Result<crate::PairingStatus, std::io::Error> {
42 todo!()
43 }
44
45 #[doc = " Attempt to get an rfcomm socket for the given uuid and seciruty setting"]
46 fn get_rfcomm_socket(
47 &mut self,
48 uuid: crate::BluetoothUuid,
49 is_secure: bool,
50 ) -> Result<crate::BluetoothRfcommSocket, String> {
51 todo!()
52 }
53}
54
55pub struct BluetoothRfcommSocket {
57 inner: u32,
59}
60
61pub struct BluetoothDiscovery<'a> {
63 _dummy: PhantomData<&'a ()>,
65}
66
67impl<'a> BluetoothDiscovery<'a> {
68 fn new() -> Self {
70 Self {
71 _dummy: PhantomData,
72 }
73 }
74}
75
76impl<'a> super::BluetoothDiscoveryTrait for BluetoothDiscovery<'a> {}
77
78impl<'a> Drop for BluetoothDiscovery<'a> {
79 fn drop(&mut self) {}
80}
81
82pub struct BluetoothHandler {
84 session: bluer::Session,
86 adapters: Vec<bluer::Adapter>,
88 _blue_agent_handle: bluer::agent::AgentHandle,
90}
91
92impl TryFrom<super::BluetoothRfcommProfileSettings> for bluer::rfcomm::Profile {
93 type Error = String;
94 fn try_from(value: super::BluetoothRfcommProfileSettings) -> Result<Self, Self::Error> {
95 let service = if let Some(v) = value.service_uuid {
96 Some(bluer::Uuid::parse_str(&v).map_err(|e| e.to_string())?)
97 } else {
98 None
99 };
100 Ok(Self {
101 uuid: bluer::Uuid::parse_str(&value.uuid).map_err(|e| e.to_string())?,
102 name: value.name,
103 service,
104 role: None,
105 channel: value.channel,
106 psm: value.psm,
107 require_authentication: value.authenticate,
108 require_authorization: value.authorize,
109 auto_connect: value.auto_connect,
110 service_record: value.sdp_record,
111 version: value.sdp_version,
112 features: value.sdp_features,
113 ..Default::default()
114 })
115 }
116}
117
118impl super::BluetoothAdapterTrait for BluetoothHandler {
119 async fn register_rfcomm_profile(
120 &self,
121 settings: super::BluetoothRfcommProfileSettings,
122 ) -> Result<crate::BluetoothRfcommProfile, String> {
123 self.session
124 .register_profile(settings.try_into()?)
125 .await
126 .map(|a| super::BluetoothRfcommProfile::Bluez(a.into()))
127 .map_err(|e| e.to_string())
128 }
129
130 fn start_discovery(&self) -> crate::BluetoothDiscovery {
131 BluetoothDiscovery::new().into()
132 }
133
134 fn get_paired_devices(&self) -> Option<Vec<crate::BluetoothDevice>> {
135 let list = Vec::new();
136 for adapter in &self.adapters {
137 todo!();
138 }
139 Some(list)
140 }
141
142 async fn addresses(&self) -> Vec<[u8;6]> {
143 let mut a = Vec::new();
144 for adapter in &self.adapters {
145 if let Ok(adr) = adapter.address().await {
146 a.push(adr.0);
147 }
148 }
149 a
150 }
151
152 async fn set_discoverable(&self, d: bool) -> Result<(), ()> {
153 for adapter in &self.adapters {
154 adapter.set_discoverable(d).await.map_err(|_|())?;
155 }
156 Ok(())
157 }
158}
159
160impl BluetoothHandler {
161 pub async fn addresses(&self) -> Vec<bluer::Address> {
163 let mut addrs = Vec::new();
164 for a in &self.adapters {
165 if let Ok(addr) = a.address().await {
166 addrs.push(addr);
167 }
168 }
169 addrs
170 }
171
172 pub async fn new(
174 s: tokio::sync::mpsc::Sender<super::MessageToBluetoothHost>,
175 ) -> Result<Self, String> {
176 let session = bluer::Session::new().await.map_err(|e| e.to_string())?;
177
178 let adapter_names = session.adapter_names().await.map_err(|e| e.to_string())?;
179 let adapters: Vec<bluer::Adapter> = adapter_names
180 .iter()
181 .filter_map(|n| session.adapter(n).ok())
182 .collect();
183
184 let blue_agent = Self::build_agent(s);
185 let blue_agent_handle = session.register_agent(blue_agent).await;
186 println!("Registered a bluetooth agent {}", blue_agent_handle.is_ok());
187 Ok(Self {
188 session,
189 adapters,
190 _blue_agent_handle: blue_agent_handle.map_err(|e| e.to_string())?,
191 })
192 }
193
194 async fn enable(&mut self) {
196 for adapter in &self.adapters {
197 adapter.set_powered(true).await.unwrap();
198 adapter.set_pairable(true).await.unwrap();
199 }
200 }
201
202 async fn disable(&mut self) {
204 self.set_discoverable(false).await;
205 for adapter in &self.adapters {
206 adapter.set_powered(false).await.unwrap();
207 adapter.set_pairable(false).await.unwrap();
208 }
209 }
210
211 pub async fn set_discoverable(&mut self, d: bool) {
213 for adapter in &self.adapters {
214 adapter.set_discoverable(d).await.unwrap();
215 }
216 }
217
218 pub async fn register_rfcomm_profile(
220 &mut self,
221 profile: bluer::rfcomm::Profile,
222 ) -> Result<bluer::rfcomm::ProfileHandle, bluer::Error> {
223 self.session.register_profile(profile).await
224 }
225
226 fn build_agent(
228 s: tokio::sync::mpsc::Sender<super::MessageToBluetoothHost>,
229 ) -> bluer::agent::Agent {
230 let mut blue_agent = bluer::agent::Agent::default();
231 blue_agent.request_default = true;
232 blue_agent.request_pin_code = None;
233 blue_agent.request_passkey = None;
234 let s2 = s.clone();
235 blue_agent.display_passkey = Some(Box::new(move |mut a| {
236 println!("Running process for display_passkey: {:?}", a);
237 let s3 = s2.clone();
238 async move {
239 let mut chan = tokio::sync::mpsc::channel(5);
240 let _ = s3.send(super::MessageToBluetoothHost::DisplayPasskey(a.passkey, chan.0)).await;
241 loop {
242 let f = tokio::time::timeout(std::time::Duration::from_secs(5), chan.1.recv());
243 tokio::select! {
244 asdf = f => {
245 match asdf {
246 Ok(Some(m)) => {
247 match m {
248 super::ResponseToPasskey::Yes => {
249 let _ = s3.send(super::MessageToBluetoothHost::CancelDisplayPasskey).await;
250 return Ok(());
251 }
252 super::ResponseToPasskey::No => {
253 let _ = s3.send(super::MessageToBluetoothHost::CancelDisplayPasskey).await;
254 return Err(bluer::agent::ReqError::Rejected);
255 }
256 super::ResponseToPasskey::Cancel => {
257 let _ = s3.send(super::MessageToBluetoothHost::CancelDisplayPasskey).await;
258 return Err(bluer::agent::ReqError::Canceled);
259 }
260 super::ResponseToPasskey::Waiting => {}
261 }
262 }
263 Ok(None) => {}
264 _ => {
265 let _ = s3.send(super::MessageToBluetoothHost::CancelDisplayPasskey).await;
266 return Err(bluer::agent::ReqError::Canceled);
267 }
268 }
269 }
270 _ = &mut a.cancel => {
271 let _ = s3.send(super::MessageToBluetoothHost::CancelDisplayPasskey).await;
272 break Err(bluer::agent::ReqError::Canceled);
273 }
274 }
275 }
276 }
277 .boxed()
278 }));
279 blue_agent.display_pin_code = Some(Box::new(|a| {
280 async move {
281 println!("Need to display pin code {:?}", a);
282 a.cancel.await.unwrap();
283 Ok(())
284 }
285 .boxed()
286 }));
287 let s2 = s.clone();
288 blue_agent.request_confirmation = Some(Box::new(move |a| {
289 println!("Need to confirm {:?}", a);
290 let s3 = s2.clone();
291 async move {
292 let mut chan = tokio::sync::mpsc::channel(5);
293 let _ = s3
294 .send(super::MessageToBluetoothHost::ConfirmPasskey(
295 a.passkey, chan.0,
296 ))
297 .await;
298 loop {
299 let f = tokio::time::timeout(std::time::Duration::from_secs(5), chan.1.recv());
300 let asdf = f.await;
301 match asdf {
302 Ok(Some(m)) => match m {
303 super::ResponseToPasskey::Yes => {
304 let _ = s3
305 .send(super::MessageToBluetoothHost::CancelDisplayPasskey)
306 .await;
307 return Ok(());
308 }
309 super::ResponseToPasskey::No => {
310 let _ = s3
311 .send(super::MessageToBluetoothHost::CancelDisplayPasskey)
312 .await;
313 return Err(bluer::agent::ReqError::Rejected);
314 }
315 super::ResponseToPasskey::Cancel => {
316 let _ = s3
317 .send(super::MessageToBluetoothHost::CancelDisplayPasskey)
318 .await;
319 return Err(bluer::agent::ReqError::Canceled);
320 }
321 super::ResponseToPasskey::Waiting => {}
322 },
323 Ok(None) => {}
324 _ => {
325 let _ = s3
326 .send(super::MessageToBluetoothHost::CancelDisplayPasskey)
327 .await;
328 return Err(bluer::agent::ReqError::Canceled);
329 }
330 }
331 }
332 }
333 .boxed()
334 }));
335 blue_agent.request_authorization = Some(Box::new(|a| {
336 async move {
337 println!("Need to authorize {:?}", a);
338 Ok(())
339 }
340 .boxed()
341 }));
342 blue_agent.authorize_service = Some(Box::new(|a| {
343 async move {
344 println!("Need to authorize service {:?}", a);
345 Ok(())
346 }
347 .boxed()
348 }));
349 blue_agent
350 }
351
352 pub async fn issue_command(
354 &mut self,
355 cmd: super::BluetoothCommand,
356 ) -> Option<super::BluetoothResponse> {
357 match cmd {
358 super::BluetoothCommand::QueryNumAdapters => {
359 Some(super::BluetoothResponse::Adapters(0))
360 }
361 _ => None,
362 }
363 }
364
365 pub async fn scan<'a>(
367 &'a mut self,
368 bluetooth_devices: &mut HashMap<
369 bluer::Address,
370 (&'a bluer::Adapter, Option<bluer::Device>),
371 >,
372 ) {
373 let mut adapter_scanner = Vec::new();
374 for a in &self.adapters {
375 let da = a.discover_devices_with_changes().await.unwrap();
376 adapter_scanner.push((a, da));
377 }
378
379 for (adapt, da) in &mut adapter_scanner {
380 if let Some(e) = da.next().await {
381 match e {
382 AdapterEvent::DeviceAdded(addr) => {
383 println!("Device added {:?}", addr);
384 bluetooth_devices.insert(addr, (adapt, None));
385 }
386 AdapterEvent::DeviceRemoved(addr) => {
387 println!("Device removed {:?}", addr);
388 bluetooth_devices.remove_entry(&addr);
389 }
390 AdapterEvent::PropertyChanged(prop) => {
391 println!("Property changed {:?}", prop);
392 }
393 }
394 }
395 }
396 for (addr, (adapter, dev)) in bluetooth_devices {
397 if dev.is_none() {
398 if let Ok(d) = adapter.device(*addr) {
399 if let Ok(ps) = d.all_properties().await {
400 for p in ps {}
401 }
402 *dev = Some(d);
403 }
404 }
405 }
406 }
407}