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