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
153impl BluetoothHandler {
154 pub async fn addresses(&self) -> Vec<bluer::Address> {
156 let mut addrs = Vec::new();
157 for a in &self.adapters {
158 if let Ok(addr) = a.address().await {
159 addrs.push(addr);
160 }
161 }
162 addrs
163 }
164
165 pub async fn new(
167 s: tokio::sync::mpsc::Sender<super::MessageToBluetoothHost>,
168 ) -> Result<Self, String> {
169 let session = bluer::Session::new().await.map_err(|e| e.to_string())?;
170
171 let adapter_names = session.adapter_names().await.map_err(|e| e.to_string())?;
172 let adapters: Vec<bluer::Adapter> = adapter_names
173 .iter()
174 .filter_map(|n| session.adapter(n).ok())
175 .collect();
176
177 let blue_agent = Self::build_agent(s);
178 let blue_agent_handle = session.register_agent(blue_agent).await;
179 println!("Registered a bluetooth agent {}", blue_agent_handle.is_ok());
180 Ok(Self {
181 session,
182 adapters,
183 _blue_agent_handle: blue_agent_handle.map_err(|e| e.to_string())?,
184 })
185 }
186
187 async fn enable(&mut self) {
189 for adapter in &self.adapters {
190 adapter.set_powered(true).await.unwrap();
191 adapter.set_pairable(true).await.unwrap();
192 }
193 }
194
195 async fn disable(&mut self) {
197 self.set_discoverable(false).await;
198 for adapter in &self.adapters {
199 adapter.set_powered(false).await.unwrap();
200 adapter.set_pairable(false).await.unwrap();
201 }
202 }
203
204 pub async fn set_discoverable(&mut self, d: bool) {
206 for adapter in &self.adapters {
207 adapter.set_discoverable(d).await.unwrap();
208 }
209 }
210
211 pub async fn register_rfcomm_profile(
213 &mut self,
214 profile: bluer::rfcomm::Profile,
215 ) -> Result<bluer::rfcomm::ProfileHandle, bluer::Error> {
216 self.session.register_profile(profile).await
217 }
218
219 fn build_agent(
221 s: tokio::sync::mpsc::Sender<super::MessageToBluetoothHost>,
222 ) -> bluer::agent::Agent {
223 let mut blue_agent = bluer::agent::Agent::default();
224 blue_agent.request_default = true;
225 blue_agent.request_pin_code = None;
226 blue_agent.request_passkey = None;
227 let s2 = s.clone();
228 blue_agent.display_passkey = Some(Box::new(move |mut a| {
229 println!("Running process for display_passkey: {:?}", a);
230 let s3 = s2.clone();
231 async move {
232 let mut chan = tokio::sync::mpsc::channel(5);
233 let _ = s3.send(super::MessageToBluetoothHost::DisplayPasskey(a.passkey, chan.0)).await;
234 loop {
235 let f = tokio::time::timeout(std::time::Duration::from_secs(5), chan.1.recv());
236 tokio::select! {
237 asdf = f => {
238 match asdf {
239 Ok(Some(m)) => {
240 match m {
241 super::ResponseToPasskey::Yes => {
242 let _ = s3.send(super::MessageToBluetoothHost::CancelDisplayPasskey).await;
243 return Ok(());
244 }
245 super::ResponseToPasskey::No => {
246 let _ = s3.send(super::MessageToBluetoothHost::CancelDisplayPasskey).await;
247 return Err(bluer::agent::ReqError::Rejected);
248 }
249 super::ResponseToPasskey::Cancel => {
250 let _ = s3.send(super::MessageToBluetoothHost::CancelDisplayPasskey).await;
251 return Err(bluer::agent::ReqError::Canceled);
252 }
253 super::ResponseToPasskey::Waiting => {}
254 }
255 }
256 Ok(None) => {}
257 _ => {
258 let _ = s3.send(super::MessageToBluetoothHost::CancelDisplayPasskey).await;
259 return Err(bluer::agent::ReqError::Canceled);
260 }
261 }
262 }
263 _ = &mut a.cancel => {
264 let _ = s3.send(super::MessageToBluetoothHost::CancelDisplayPasskey).await;
265 break Err(bluer::agent::ReqError::Canceled);
266 }
267 }
268 }
269 }
270 .boxed()
271 }));
272 blue_agent.display_pin_code = Some(Box::new(|a| {
273 async move {
274 println!("Need to display pin code {:?}", a);
275 a.cancel.await.unwrap();
276 Ok(())
277 }
278 .boxed()
279 }));
280 let s2 = s.clone();
281 blue_agent.request_confirmation = Some(Box::new(move |a| {
282 println!("Need to confirm {:?}", a);
283 let s3 = s2.clone();
284 async move {
285 let mut chan = tokio::sync::mpsc::channel(5);
286 let _ = s3
287 .send(super::MessageToBluetoothHost::ConfirmPasskey(
288 a.passkey, chan.0,
289 ))
290 .await;
291 loop {
292 let f = tokio::time::timeout(std::time::Duration::from_secs(5), chan.1.recv());
293 let asdf = f.await;
294 match asdf {
295 Ok(Some(m)) => match m {
296 super::ResponseToPasskey::Yes => {
297 let _ = s3
298 .send(super::MessageToBluetoothHost::CancelDisplayPasskey)
299 .await;
300 return Ok(());
301 }
302 super::ResponseToPasskey::No => {
303 let _ = s3
304 .send(super::MessageToBluetoothHost::CancelDisplayPasskey)
305 .await;
306 return Err(bluer::agent::ReqError::Rejected);
307 }
308 super::ResponseToPasskey::Cancel => {
309 let _ = s3
310 .send(super::MessageToBluetoothHost::CancelDisplayPasskey)
311 .await;
312 return Err(bluer::agent::ReqError::Canceled);
313 }
314 super::ResponseToPasskey::Waiting => {}
315 },
316 Ok(None) => {}
317 _ => {
318 let _ = s3
319 .send(super::MessageToBluetoothHost::CancelDisplayPasskey)
320 .await;
321 return Err(bluer::agent::ReqError::Canceled);
322 }
323 }
324 }
325 }
326 .boxed()
327 }));
328 blue_agent.request_authorization = Some(Box::new(|a| {
329 async move {
330 println!("Need to authorize {:?}", a);
331 Ok(())
332 }
333 .boxed()
334 }));
335 blue_agent.authorize_service = Some(Box::new(|a| {
336 async move {
337 println!("Need to authorize service {:?}", a);
338 Ok(())
339 }
340 .boxed()
341 }));
342 blue_agent
343 }
344
345 pub async fn issue_command(
347 &mut self,
348 cmd: super::BluetoothCommand,
349 ) -> Option<super::BluetoothResponse> {
350 match cmd {
351 super::BluetoothCommand::QueryNumAdapters => {
352 Some(super::BluetoothResponse::Adapters(0))
353 }
354 _ => None,
355 }
356 }
357
358 pub async fn scan<'a>(
360 &'a mut self,
361 bluetooth_devices: &mut HashMap<
362 bluer::Address,
363 (&'a bluer::Adapter, Option<bluer::Device>),
364 >,
365 ) {
366 let mut adapter_scanner = Vec::new();
367 for a in &self.adapters {
368 let da = a.discover_devices_with_changes().await.unwrap();
369 adapter_scanner.push((a, da));
370 }
371
372 for (adapt, da) in &mut adapter_scanner {
373 if let Some(e) = da.next().await {
374 match e {
375 AdapterEvent::DeviceAdded(addr) => {
376 println!("Device added {:?}", addr);
377 bluetooth_devices.insert(addr, (adapt, None));
378 }
379 AdapterEvent::DeviceRemoved(addr) => {
380 println!("Device removed {:?}", addr);
381 bluetooth_devices.remove_entry(&addr);
382 }
383 AdapterEvent::PropertyChanged(prop) => {
384 println!("Property changed {:?}", prop);
385 }
386 }
387 }
388 }
389 for (addr, (adapter, dev)) in bluetooth_devices {
390 if dev.is_none() {
391 if let Ok(d) = adapter.device(*addr) {
392 if let Ok(ps) = d.all_properties().await {
393 for p in ps {}
394 }
395 *dev = Some(d);
396 }
397 }
398 }
399 }
400}