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