bluetooth/
bluetooth.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5use std::collections::HashMap;
6use std::error::Error;
7use std::sync::Arc;
8
9#[cfg(all(target_os = "android", feature = "native-bluetooth"))]
10use blurdroid::bluetooth_device::Device as BluetoothDeviceAndroid;
11#[cfg(all(target_os = "android", feature = "native-bluetooth"))]
12use blurdroid::bluetooth_discovery_session::DiscoverySession as BluetoothDiscoverySessionAndroid;
13#[cfg(all(target_os = "android", feature = "native-bluetooth"))]
14use blurdroid::bluetooth_gatt_characteristic::Characteristic as BluetoothGATTCharacteristicAndroid;
15#[cfg(all(target_os = "android", feature = "native-bluetooth"))]
16use blurdroid::bluetooth_gatt_descriptor::Descriptor as BluetoothGATTDescriptorAndroid;
17#[cfg(all(target_os = "android", feature = "native-bluetooth"))]
18use blurdroid::bluetooth_gatt_service::Service as BluetoothGATTServiceAndroid;
19#[cfg(all(target_os = "macos", feature = "native-bluetooth"))]
20use blurmac::BluetoothDevice as BluetoothDeviceMac;
21#[cfg(all(target_os = "macos", feature = "native-bluetooth"))]
22use blurmac::BluetoothDiscoverySession as BluetoothDiscoverySessionMac;
23#[cfg(all(target_os = "macos", feature = "native-bluetooth"))]
24use blurmac::BluetoothGATTCharacteristic as BluetoothGATTCharacteristicMac;
25#[cfg(all(target_os = "macos", feature = "native-bluetooth"))]
26use blurmac::BluetoothGATTDescriptor as BluetoothGATTDescriptorMac;
27#[cfg(all(target_os = "macos", feature = "native-bluetooth"))]
28use blurmac::BluetoothGATTService as BluetoothGATTServiceMac;
29#[cfg(feature = "bluetooth-test")]
30use blurmock::fake_characteristic::FakeBluetoothGATTCharacteristic;
31#[cfg(feature = "bluetooth-test")]
32use blurmock::fake_descriptor::FakeBluetoothGATTDescriptor;
33#[cfg(feature = "bluetooth-test")]
34use blurmock::fake_device::FakeBluetoothDevice;
35#[cfg(feature = "bluetooth-test")]
36use blurmock::fake_discovery_session::FakeBluetoothDiscoverySession;
37#[cfg(feature = "bluetooth-test")]
38use blurmock::fake_service::FakeBluetoothGATTService;
39#[cfg(all(target_os = "linux", feature = "native-bluetooth"))]
40use blurz::bluetooth_device::BluetoothDevice as BluetoothDeviceBluez;
41#[cfg(all(target_os = "linux", feature = "native-bluetooth"))]
42use blurz::bluetooth_discovery_session::BluetoothDiscoverySession as BluetoothDiscoverySessionBluez;
43#[cfg(all(target_os = "linux", feature = "native-bluetooth"))]
44use blurz::bluetooth_gatt_characteristic::BluetoothGATTCharacteristic as BluetoothGATTCharacteristicBluez;
45#[cfg(all(target_os = "linux", feature = "native-bluetooth"))]
46use blurz::bluetooth_gatt_descriptor::BluetoothGATTDescriptor as BluetoothGATTDescriptorBluez;
47#[cfg(all(target_os = "linux", feature = "native-bluetooth"))]
48use blurz::bluetooth_gatt_service::BluetoothGATTService as BluetoothGATTServiceBluez;
49
50pub use super::adapter::BluetoothAdapter;
51#[cfg(not(any(
52    all(target_os = "linux", feature = "native-bluetooth"),
53    all(target_os = "android", feature = "native-bluetooth"),
54    all(target_os = "macos", feature = "native-bluetooth")
55)))]
56use super::empty::BluetoothDevice as BluetoothDeviceEmpty;
57#[cfg(not(any(
58    all(target_os = "linux", feature = "native-bluetooth"),
59    all(target_os = "android", feature = "native-bluetooth"),
60    all(target_os = "macos", feature = "native-bluetooth")
61)))]
62use super::empty::BluetoothDiscoverySession as BluetoothDiscoverySessionEmpty;
63#[cfg(not(any(
64    all(target_os = "linux", feature = "native-bluetooth"),
65    all(target_os = "android", feature = "native-bluetooth"),
66    all(target_os = "macos", feature = "native-bluetooth")
67)))]
68use super::empty::BluetoothGATTCharacteristic as BluetoothGATTCharacteristicEmpty;
69#[cfg(not(any(
70    all(target_os = "linux", feature = "native-bluetooth"),
71    all(target_os = "android", feature = "native-bluetooth"),
72    all(target_os = "macos", feature = "native-bluetooth")
73)))]
74use super::empty::BluetoothGATTDescriptor as BluetoothGATTDescriptorEmpty;
75#[cfg(not(any(
76    all(target_os = "linux", feature = "native-bluetooth"),
77    all(target_os = "android", feature = "native-bluetooth"),
78    all(target_os = "macos", feature = "native-bluetooth")
79)))]
80use super::empty::BluetoothGATTService as BluetoothGATTServiceEmpty;
81use super::macros::get_inner_and_call;
82#[cfg(feature = "bluetooth-test")]
83use super::macros::get_inner_and_call_test_func;
84
85#[cfg(feature = "bluetooth-test")]
86const NOT_SUPPORTED_ON_MOCK_ERROR: &str = "Error! The first parameter must be a mock structure!";
87
88#[derive(Debug)]
89pub enum BluetoothDiscoverySession {
90    #[cfg(all(target_os = "linux", feature = "native-bluetooth"))]
91    Bluez(Arc<BluetoothDiscoverySessionBluez>),
92    #[cfg(all(target_os = "android", feature = "native-bluetooth"))]
93    Android(Arc<BluetoothDiscoverySessionAndroid>),
94    #[cfg(all(target_os = "macos", feature = "native-bluetooth"))]
95    Mac(Arc<BluetoothDiscoverySessionMac>),
96    #[cfg(not(any(
97        all(target_os = "linux", feature = "native-bluetooth"),
98        all(target_os = "android", feature = "native-bluetooth"),
99        all(target_os = "macos", feature = "native-bluetooth")
100    )))]
101    Empty(Arc<BluetoothDiscoverySessionEmpty>),
102    #[cfg(feature = "bluetooth-test")]
103    Mock(Arc<FakeBluetoothDiscoverySession>),
104}
105
106#[derive(Clone, Debug)]
107pub enum BluetoothDevice {
108    #[cfg(all(target_os = "linux", feature = "native-bluetooth"))]
109    Bluez(Arc<BluetoothDeviceBluez>),
110    #[cfg(all(target_os = "android", feature = "native-bluetooth"))]
111    Android(Arc<BluetoothDeviceAndroid>),
112    #[cfg(all(target_os = "macos", feature = "native-bluetooth"))]
113    Mac(Arc<BluetoothDeviceMac>),
114    #[cfg(not(any(
115        all(target_os = "linux", feature = "native-bluetooth"),
116        all(target_os = "android", feature = "native-bluetooth"),
117        all(target_os = "macos", feature = "native-bluetooth")
118    )))]
119    Empty(Arc<BluetoothDeviceEmpty>),
120    #[cfg(feature = "bluetooth-test")]
121    Mock(Arc<FakeBluetoothDevice>),
122}
123
124#[derive(Clone, Debug)]
125pub enum BluetoothGATTService {
126    #[cfg(all(target_os = "linux", feature = "native-bluetooth"))]
127    Bluez(Arc<BluetoothGATTServiceBluez>),
128    #[cfg(all(target_os = "android", feature = "native-bluetooth"))]
129    Android(Arc<BluetoothGATTServiceAndroid>),
130    #[cfg(all(target_os = "macos", feature = "native-bluetooth"))]
131    Mac(Arc<BluetoothGATTServiceMac>),
132    #[cfg(not(any(
133        all(target_os = "linux", feature = "native-bluetooth"),
134        all(target_os = "android", feature = "native-bluetooth"),
135        all(target_os = "macos", feature = "native-bluetooth")
136    )))]
137    Empty(Arc<BluetoothGATTServiceEmpty>),
138    #[cfg(feature = "bluetooth-test")]
139    Mock(Arc<FakeBluetoothGATTService>),
140}
141
142#[derive(Clone, Debug)]
143pub enum BluetoothGATTCharacteristic {
144    #[cfg(all(target_os = "linux", feature = "native-bluetooth"))]
145    Bluez(Arc<BluetoothGATTCharacteristicBluez>),
146    #[cfg(all(target_os = "android", feature = "native-bluetooth"))]
147    Android(Arc<BluetoothGATTCharacteristicAndroid>),
148    #[cfg(all(target_os = "macos", feature = "native-bluetooth"))]
149    Mac(Arc<BluetoothGATTCharacteristicMac>),
150    #[cfg(not(any(
151        all(target_os = "linux", feature = "native-bluetooth"),
152        all(target_os = "android", feature = "native-bluetooth"),
153        all(target_os = "macos", feature = "native-bluetooth")
154    )))]
155    Empty(Arc<BluetoothGATTCharacteristicEmpty>),
156    #[cfg(feature = "bluetooth-test")]
157    Mock(Arc<FakeBluetoothGATTCharacteristic>),
158}
159
160#[derive(Clone, Debug)]
161pub enum BluetoothGATTDescriptor {
162    #[cfg(all(target_os = "linux", feature = "native-bluetooth"))]
163    Bluez(Arc<BluetoothGATTDescriptorBluez>),
164    #[cfg(all(target_os = "android", feature = "native-bluetooth"))]
165    Android(Arc<BluetoothGATTDescriptorAndroid>),
166    #[cfg(all(target_os = "macos", feature = "native-bluetooth"))]
167    Mac(Arc<BluetoothGATTDescriptorMac>),
168    #[cfg(not(any(
169        all(target_os = "linux", feature = "native-bluetooth"),
170        all(target_os = "android", feature = "native-bluetooth"),
171        all(target_os = "macos", feature = "native-bluetooth")
172    )))]
173    Empty(Arc<BluetoothGATTDescriptorEmpty>),
174    #[cfg(feature = "bluetooth-test")]
175    Mock(Arc<FakeBluetoothGATTDescriptor>),
176}
177
178impl BluetoothDiscoverySession {
179    pub fn start_discovery(&self) -> Result<(), Box<dyn Error>> {
180        get_inner_and_call!(self, BluetoothDiscoverySession, start_discovery)
181    }
182
183    pub fn stop_discovery(&self) -> Result<(), Box<dyn Error>> {
184        get_inner_and_call!(self, BluetoothDiscoverySession, stop_discovery)
185    }
186}
187
188impl BluetoothDevice {
189    pub fn get_id(&self) -> String {
190        get_inner_and_call!(self, BluetoothDevice, get_id)
191    }
192
193    #[cfg(feature = "bluetooth-test")]
194    pub fn set_id(&self, id: String) {
195        if let BluetoothDevice::Mock(fake_adapter) = self {
196            fake_adapter.set_id(id)
197        }
198    }
199
200    pub fn get_address(&self) -> Result<String, Box<dyn Error>> {
201        get_inner_and_call!(self, BluetoothDevice, get_address)
202    }
203
204    #[cfg(feature = "bluetooth-test")]
205    pub fn set_address(&self, address: String) -> Result<(), Box<dyn Error>> {
206        get_inner_and_call_test_func!(self, BluetoothDevice, set_address, address)
207    }
208
209    pub fn get_name(&self) -> Result<String, Box<dyn Error>> {
210        get_inner_and_call!(self, BluetoothDevice, get_name)
211    }
212
213    #[cfg(feature = "bluetooth-test")]
214    pub fn set_name(&self, name: Option<String>) -> Result<(), Box<dyn Error>> {
215        get_inner_and_call_test_func!(self, BluetoothDevice, set_name, name)
216    }
217
218    pub fn get_icon(&self) -> Result<String, Box<dyn Error>> {
219        get_inner_and_call!(self, BluetoothDevice, get_icon)
220    }
221
222    #[cfg(feature = "bluetooth-test")]
223    pub fn set_icon(&self, icon: String) -> Result<(), Box<dyn Error>> {
224        get_inner_and_call_test_func!(self, BluetoothDevice, set_icon, icon)
225    }
226
227    pub fn get_class(&self) -> Result<u32, Box<dyn Error>> {
228        get_inner_and_call!(self, BluetoothDevice, get_class)
229    }
230
231    #[cfg(feature = "bluetooth-test")]
232    pub fn set_class(&self, class: u32) -> Result<(), Box<dyn Error>> {
233        get_inner_and_call_test_func!(self, BluetoothDevice, set_class, class)
234    }
235
236    pub fn get_appearance(&self) -> Result<u16, Box<dyn Error>> {
237        get_inner_and_call!(self, BluetoothDevice, get_appearance)
238    }
239
240    #[cfg(feature = "bluetooth-test")]
241    pub fn set_appearance(&self, appearance: u16) -> Result<(), Box<dyn Error>> {
242        get_inner_and_call_test_func!(self, BluetoothDevice, set_appearance, Some(appearance))
243    }
244
245    pub fn get_uuids(&self) -> Result<Vec<String>, Box<dyn Error>> {
246        get_inner_and_call!(self, BluetoothDevice, get_uuids)
247    }
248
249    #[cfg(feature = "bluetooth-test")]
250    pub fn set_uuids(&self, uuids: Vec<String>) -> Result<(), Box<dyn Error>> {
251        get_inner_and_call_test_func!(self, BluetoothDevice, set_uuids, uuids)
252    }
253
254    pub fn is_paired(&self) -> Result<bool, Box<dyn Error>> {
255        get_inner_and_call!(self, BluetoothDevice, is_paired)
256    }
257
258    #[cfg(feature = "bluetooth-test")]
259    pub fn set_paired(&self, paired: bool) -> Result<(), Box<dyn Error>> {
260        get_inner_and_call_test_func!(self, BluetoothDevice, set_paired, paired)
261    }
262
263    pub fn is_connected(&self) -> Result<bool, Box<dyn Error>> {
264        get_inner_and_call!(self, BluetoothDevice, is_connected)
265    }
266
267    #[cfg(feature = "bluetooth-test")]
268    pub fn set_connected(&self, connected: bool) -> Result<(), Box<dyn Error>> {
269        get_inner_and_call_test_func!(self, BluetoothDevice, set_connected, connected)
270    }
271
272    #[cfg(feature = "bluetooth-test")]
273    pub fn is_connectable(&self) -> Result<bool, Box<dyn Error>> {
274        get_inner_and_call_test_func!(self, BluetoothDevice, is_connectable)
275    }
276
277    #[cfg(feature = "bluetooth-test")]
278    pub fn set_connectable(&self, connectable: bool) -> Result<(), Box<dyn Error>> {
279        get_inner_and_call_test_func!(self, BluetoothDevice, set_connectable, connectable)
280    }
281
282    pub fn is_trusted(&self) -> Result<bool, Box<dyn Error>> {
283        get_inner_and_call!(self, BluetoothDevice, is_trusted)
284    }
285
286    #[cfg(feature = "bluetooth-test")]
287    pub fn set_trusted(&self, trusted: bool) -> Result<(), Box<dyn Error>> {
288        get_inner_and_call_test_func!(self, BluetoothDevice, set_trusted, trusted)
289    }
290
291    pub fn is_blocked(&self) -> Result<bool, Box<dyn Error>> {
292        get_inner_and_call!(self, BluetoothDevice, is_blocked)
293    }
294
295    #[cfg(feature = "bluetooth-test")]
296    pub fn set_blocked(&self, blocked: bool) -> Result<(), Box<dyn Error>> {
297        get_inner_and_call_test_func!(self, BluetoothDevice, set_blocked, blocked)
298    }
299
300    pub fn get_alias(&self) -> Result<String, Box<dyn Error>> {
301        get_inner_and_call!(self, BluetoothDevice, get_alias)
302    }
303
304    #[cfg(feature = "bluetooth-test")]
305    pub fn set_alias(&self, alias: String) -> Result<(), Box<dyn Error>> {
306        get_inner_and_call_test_func!(self, BluetoothDevice, set_alias, alias)
307    }
308
309    pub fn is_legacy_pairing(&self) -> Result<bool, Box<dyn Error>> {
310        get_inner_and_call!(self, BluetoothDevice, is_legacy_pairing)
311    }
312
313    #[cfg(feature = "bluetooth-test")]
314    pub fn set_legacy_pairing(&self, legacy_pairing: bool) -> Result<(), Box<dyn Error>> {
315        get_inner_and_call_test_func!(self, BluetoothDevice, set_legacy_pairing, legacy_pairing)
316    }
317
318    pub fn get_vendor_id_source(&self) -> Result<String, Box<dyn Error>> {
319        get_inner_and_call!(self, BluetoothDevice, get_vendor_id_source)
320    }
321
322    pub fn get_vendor_id(&self) -> Result<u32, Box<dyn Error>> {
323        get_inner_and_call!(self, BluetoothDevice, get_vendor_id)
324    }
325
326    pub fn get_product_id(&self) -> Result<u32, Box<dyn Error>> {
327        get_inner_and_call!(self, BluetoothDevice, get_product_id)
328    }
329
330    pub fn get_device_id(&self) -> Result<u32, Box<dyn Error>> {
331        get_inner_and_call!(self, BluetoothDevice, get_device_id)
332    }
333
334    pub fn get_modalias(&self) -> Result<(String, u32, u32, u32), Box<dyn Error>> {
335        get_inner_and_call!(self, BluetoothDevice, get_modalias)
336    }
337
338    #[cfg(feature = "bluetooth-test")]
339    pub fn set_modalias(&self, modalias: String) -> Result<(), Box<dyn Error>> {
340        get_inner_and_call_test_func!(self, BluetoothDevice, set_modalias, modalias)
341    }
342
343    pub fn get_rssi(&self) -> Result<i16, Box<dyn Error>> {
344        get_inner_and_call!(self, BluetoothDevice, get_rssi)
345    }
346
347    #[cfg(feature = "bluetooth-test")]
348    pub fn set_rssi(&self, rssi: i16) -> Result<(), Box<dyn Error>> {
349        get_inner_and_call_test_func!(self, BluetoothDevice, set_rssi, Some(rssi))
350    }
351
352    pub fn get_tx_power(&self) -> Result<i16, Box<dyn Error>> {
353        get_inner_and_call!(self, BluetoothDevice, get_tx_power)
354    }
355
356    #[cfg(feature = "bluetooth-test")]
357    pub fn set_tx_power(&self, tx_power: i16) -> Result<(), Box<dyn Error>> {
358        get_inner_and_call_test_func!(self, BluetoothDevice, set_tx_power, Some(tx_power))
359    }
360
361    pub fn get_manufacturer_data(&self) -> Result<HashMap<u16, Vec<u8>>, Box<dyn Error>> {
362        get_inner_and_call!(self, BluetoothDevice, get_manufacturer_data)
363    }
364
365    #[cfg(feature = "bluetooth-test")]
366    pub fn set_manufacturer_data(
367        &self,
368        manufacturer_data: HashMap<u16, Vec<u8>>,
369    ) -> Result<(), Box<dyn Error>> {
370        get_inner_and_call_test_func!(
371            self,
372            BluetoothDevice,
373            set_manufacturer_data,
374            Some(manufacturer_data)
375        )
376    }
377
378    pub fn get_service_data(&self) -> Result<HashMap<String, Vec<u8>>, Box<dyn Error>> {
379        get_inner_and_call!(self, BluetoothDevice, get_service_data)
380    }
381
382    #[cfg(feature = "bluetooth-test")]
383    pub fn set_service_data(
384        &self,
385        service_data: HashMap<String, Vec<u8>>,
386    ) -> Result<(), Box<dyn Error>> {
387        get_inner_and_call_test_func!(self, BluetoothDevice, set_service_data, Some(service_data))
388    }
389
390    pub fn get_gatt_services(&self) -> Result<Vec<BluetoothGATTService>, Box<dyn Error>> {
391        let services = get_inner_and_call!(self, BluetoothDevice, get_gatt_services)?;
392        Ok(services
393            .into_iter()
394            .map(|service| BluetoothGATTService::create_service(self.clone(), service))
395            .collect())
396    }
397
398    pub fn connect(&self) -> Result<(), Box<dyn Error>> {
399        get_inner_and_call!(self, BluetoothDevice, connect)
400    }
401
402    pub fn disconnect(&self) -> Result<(), Box<dyn Error>> {
403        get_inner_and_call!(self, BluetoothDevice, disconnect)
404    }
405
406    pub fn connect_profile(&self, uuid: String) -> Result<(), Box<dyn Error>> {
407        get_inner_and_call!(self, BluetoothDevice, connect_profile, uuid)
408    }
409
410    pub fn disconnect_profile(&self, uuid: String) -> Result<(), Box<dyn Error>> {
411        get_inner_and_call!(self, BluetoothDevice, disconnect_profile, uuid)
412    }
413
414    pub fn pair(&self) -> Result<(), Box<dyn Error>> {
415        get_inner_and_call!(self, BluetoothDevice, pair)
416    }
417
418    pub fn cancel_pairing(&self) -> Result<(), Box<dyn Error>> {
419        get_inner_and_call!(self, BluetoothDevice, cancel_pairing)
420    }
421}
422
423impl BluetoothGATTService {
424    fn create_service(device: BluetoothDevice, service: String) -> BluetoothGATTService {
425        match device {
426            #[cfg(all(target_os = "linux", feature = "native-bluetooth"))]
427            BluetoothDevice::Bluez(_bluez_device) => {
428                BluetoothGATTService::Bluez(Arc::new(BluetoothGATTServiceBluez::new(service)))
429            },
430            #[cfg(all(target_os = "android", feature = "native-bluetooth"))]
431            BluetoothDevice::Android(android_device) => BluetoothGATTService::Android(Arc::new(
432                BluetoothGATTServiceAndroid::new(android_device, service),
433            )),
434            #[cfg(all(target_os = "macos", feature = "native-bluetooth"))]
435            BluetoothDevice::Mac(mac_device) => BluetoothGATTService::Mac(Arc::new(
436                BluetoothGATTServiceMac::new(mac_device, service),
437            )),
438            #[cfg(not(any(
439                all(target_os = "linux", feature = "native-bluetooth"),
440                all(target_os = "android", feature = "native-bluetooth"),
441                all(target_os = "macos", feature = "native-bluetooth")
442            )))]
443            BluetoothDevice::Empty(_device) => {
444                BluetoothGATTService::Empty(Arc::new(BluetoothGATTServiceEmpty::new(service)))
445            },
446            #[cfg(feature = "bluetooth-test")]
447            BluetoothDevice::Mock(fake_device) => BluetoothGATTService::Mock(
448                FakeBluetoothGATTService::new_empty(fake_device, service),
449            ),
450        }
451    }
452
453    #[cfg(feature = "bluetooth-test")]
454    pub fn create_mock_service(
455        device: BluetoothDevice,
456        service: String,
457    ) -> Result<BluetoothGATTService, Box<dyn Error>> {
458        match device {
459            BluetoothDevice::Mock(fake_device) => Ok(BluetoothGATTService::Mock(
460                FakeBluetoothGATTService::new_empty(fake_device, service),
461            )),
462            _ => Err(Box::from(
463                "Error! The first parameter must be a mock structure!",
464            )),
465        }
466    }
467
468    pub fn get_id(&self) -> String {
469        get_inner_and_call!(self, BluetoothGATTService, get_id)
470    }
471
472    #[cfg(feature = "bluetooth-test")]
473    pub fn set_id(&self, id: String) {
474        if let BluetoothGATTService::Mock(fake_service) = self {
475            fake_service.set_id(id)
476        }
477    }
478
479    pub fn get_uuid(&self) -> Result<String, Box<dyn Error>> {
480        get_inner_and_call!(self, BluetoothGATTService, get_uuid)
481    }
482
483    #[cfg(feature = "bluetooth-test")]
484    pub fn set_uuid(&self, uuid: String) -> Result<(), Box<dyn Error>> {
485        get_inner_and_call_test_func!(self, BluetoothGATTService, set_uuid, uuid)
486    }
487
488    pub fn is_primary(&self) -> Result<bool, Box<dyn Error>> {
489        get_inner_and_call!(self, BluetoothGATTService, is_primary)
490    }
491
492    #[cfg(feature = "bluetooth-test")]
493    pub fn set_primary(&self, primary: bool) -> Result<(), Box<dyn Error>> {
494        get_inner_and_call_test_func!(self, BluetoothGATTService, set_is_primary, primary)
495    }
496
497    pub fn get_includes(
498        &self,
499        device: BluetoothDevice,
500    ) -> Result<Vec<BluetoothGATTService>, Box<dyn Error>> {
501        let services = get_inner_and_call!(self, BluetoothGATTService, get_includes)?;
502        Ok(services
503            .into_iter()
504            .map(|service| BluetoothGATTService::create_service(device.clone(), service))
505            .collect())
506    }
507
508    pub fn get_gatt_characteristics(
509        &self,
510    ) -> Result<Vec<BluetoothGATTCharacteristic>, Box<dyn Error>> {
511        let characteristics =
512            get_inner_and_call!(self, BluetoothGATTService, get_gatt_characteristics)?;
513        Ok(characteristics
514            .into_iter()
515            .map(|characteristic| {
516                BluetoothGATTCharacteristic::create_characteristic(self.clone(), characteristic)
517            })
518            .collect())
519    }
520}
521
522impl BluetoothGATTCharacteristic {
523    fn create_characteristic(
524        service: BluetoothGATTService,
525        characteristic: String,
526    ) -> BluetoothGATTCharacteristic {
527        match service {
528            #[cfg(all(target_os = "linux", feature = "native-bluetooth"))]
529            BluetoothGATTService::Bluez(_bluez_service) => BluetoothGATTCharacteristic::Bluez(
530                Arc::new(BluetoothGATTCharacteristicBluez::new(characteristic)),
531            ),
532            #[cfg(all(target_os = "android", feature = "native-bluetooth"))]
533            BluetoothGATTService::Android(android_service) => {
534                BluetoothGATTCharacteristic::Android(Arc::new(
535                    BluetoothGATTCharacteristicAndroid::new(android_service, characteristic),
536                ))
537            },
538            #[cfg(all(target_os = "macos", feature = "native-bluetooth"))]
539            BluetoothGATTService::Mac(mac_service) => BluetoothGATTCharacteristic::Mac(Arc::new(
540                BluetoothGATTCharacteristicMac::new(mac_service, characteristic),
541            )),
542            #[cfg(not(any(
543                all(target_os = "linux", feature = "native-bluetooth"),
544                all(target_os = "android", feature = "native-bluetooth"),
545                all(target_os = "macos", feature = "native-bluetooth")
546            )))]
547            BluetoothGATTService::Empty(_service) => BluetoothGATTCharacteristic::Empty(Arc::new(
548                BluetoothGATTCharacteristicEmpty::new(characteristic),
549            )),
550            #[cfg(feature = "bluetooth-test")]
551            BluetoothGATTService::Mock(fake_service) => BluetoothGATTCharacteristic::Mock(
552                FakeBluetoothGATTCharacteristic::new_empty(fake_service, characteristic),
553            ),
554        }
555    }
556
557    #[cfg(feature = "bluetooth-test")]
558    pub fn create_mock_characteristic(
559        service: BluetoothGATTService,
560        characteristic: String,
561    ) -> Result<BluetoothGATTCharacteristic, Box<dyn Error>> {
562        match service {
563            BluetoothGATTService::Mock(fake_service) => Ok(BluetoothGATTCharacteristic::Mock(
564                FakeBluetoothGATTCharacteristic::new_empty(fake_service, characteristic),
565            )),
566            _ => Err(Box::from(
567                "Error! The first parameter must be a mock structure!",
568            )),
569        }
570    }
571
572    pub fn get_id(&self) -> String {
573        get_inner_and_call!(self, BluetoothGATTCharacteristic, get_id)
574    }
575
576    #[cfg(feature = "bluetooth-test")]
577    pub fn set_id(&self, id: String) {
578        if let BluetoothGATTCharacteristic::Mock(fake_characteristic) = self {
579            fake_characteristic.set_id(id)
580        }
581    }
582
583    pub fn get_uuid(&self) -> Result<String, Box<dyn Error>> {
584        get_inner_and_call!(self, BluetoothGATTCharacteristic, get_uuid)
585    }
586
587    #[cfg(feature = "bluetooth-test")]
588    pub fn set_uuid(&self, uuid: String) -> Result<(), Box<dyn Error>> {
589        get_inner_and_call_test_func!(self, BluetoothGATTCharacteristic, set_uuid, uuid)
590    }
591
592    pub fn get_value(&self) -> Result<Vec<u8>, Box<dyn Error>> {
593        get_inner_and_call!(self, BluetoothGATTCharacteristic, get_value)
594    }
595
596    #[cfg(feature = "bluetooth-test")]
597    pub fn set_value(&self, value: Vec<u8>) -> Result<(), Box<dyn Error>> {
598        get_inner_and_call_test_func!(self, BluetoothGATTCharacteristic, set_value, Some(value))
599    }
600
601    pub fn is_notifying(&self) -> Result<bool, Box<dyn Error>> {
602        get_inner_and_call!(self, BluetoothGATTCharacteristic, is_notifying)
603    }
604
605    #[cfg(feature = "bluetooth-test")]
606    pub fn set_notifying(&self, notifying: bool) -> Result<(), Box<dyn Error>> {
607        get_inner_and_call_test_func!(self, BluetoothGATTCharacteristic, set_notifying, notifying)
608    }
609
610    pub fn get_flags(&self) -> Result<Vec<String>, Box<dyn Error>> {
611        get_inner_and_call!(self, BluetoothGATTCharacteristic, get_flags)
612    }
613
614    #[cfg(feature = "bluetooth-test")]
615    pub fn set_flags(&self, flags: Vec<String>) -> Result<(), Box<dyn Error>> {
616        get_inner_and_call_test_func!(self, BluetoothGATTCharacteristic, set_flags, flags)
617    }
618
619    pub fn get_gatt_descriptors(&self) -> Result<Vec<BluetoothGATTDescriptor>, Box<dyn Error>> {
620        let descriptors =
621            get_inner_and_call!(self, BluetoothGATTCharacteristic, get_gatt_descriptors)?;
622        Ok(descriptors
623            .into_iter()
624            .map(|descriptor| BluetoothGATTDescriptor::create_descriptor(self.clone(), descriptor))
625            .collect())
626    }
627
628    pub fn read_value(&self) -> Result<Vec<u8>, Box<dyn Error>> {
629        get_inner_and_call!(@with_bluez_offset, self, BluetoothGATTCharacteristic, read_value)
630    }
631
632    pub fn write_value(&self, values: Vec<u8>) -> Result<(), Box<dyn Error>> {
633        get_inner_and_call!(@with_bluez_offset, self, BluetoothGATTCharacteristic, write_value, values)
634    }
635
636    pub fn start_notify(&self) -> Result<(), Box<dyn Error>> {
637        get_inner_and_call!(self, BluetoothGATTCharacteristic, start_notify)
638    }
639
640    pub fn stop_notify(&self) -> Result<(), Box<dyn Error>> {
641        get_inner_and_call!(self, BluetoothGATTCharacteristic, stop_notify)
642    }
643}
644
645impl BluetoothGATTDescriptor {
646    fn create_descriptor(
647        characteristic: BluetoothGATTCharacteristic,
648        descriptor: String,
649    ) -> BluetoothGATTDescriptor {
650        match characteristic {
651            #[cfg(all(target_os = "linux", feature = "native-bluetooth"))]
652            BluetoothGATTCharacteristic::Bluez(_bluez_characteristic) => {
653                BluetoothGATTDescriptor::Bluez(Arc::new(BluetoothGATTDescriptorBluez::new(
654                    descriptor,
655                )))
656            },
657            #[cfg(all(target_os = "android", feature = "native-bluetooth"))]
658            BluetoothGATTCharacteristic::Android(android_characteristic) => {
659                BluetoothGATTDescriptor::Android(Arc::new(BluetoothGATTDescriptorAndroid::new(
660                    android_characteristic,
661                    descriptor,
662                )))
663            },
664            #[cfg(all(target_os = "macos", feature = "native-bluetooth"))]
665            BluetoothGATTCharacteristic::Mac(_mac_characteristic) => {
666                BluetoothGATTDescriptor::Mac(Arc::new(BluetoothGATTDescriptorMac::new(descriptor)))
667            },
668            #[cfg(not(any(
669                all(target_os = "linux", feature = "native-bluetooth"),
670                all(target_os = "android", feature = "native-bluetooth"),
671                all(target_os = "macos", feature = "native-bluetooth")
672            )))]
673            BluetoothGATTCharacteristic::Empty(_characteristic) => BluetoothGATTDescriptor::Empty(
674                Arc::new(BluetoothGATTDescriptorEmpty::new(descriptor)),
675            ),
676            #[cfg(feature = "bluetooth-test")]
677            BluetoothGATTCharacteristic::Mock(fake_characteristic) => {
678                BluetoothGATTDescriptor::Mock(FakeBluetoothGATTDescriptor::new_empty(
679                    fake_characteristic,
680                    descriptor,
681                ))
682            },
683        }
684    }
685
686    #[cfg(feature = "bluetooth-test")]
687    pub fn create_mock_descriptor(
688        characteristic: BluetoothGATTCharacteristic,
689        descriptor: String,
690    ) -> Result<BluetoothGATTDescriptor, Box<dyn Error>> {
691        match characteristic {
692            BluetoothGATTCharacteristic::Mock(fake_characteristic) => {
693                Ok(BluetoothGATTDescriptor::Mock(
694                    FakeBluetoothGATTDescriptor::new_empty(fake_characteristic, descriptor),
695                ))
696            },
697            _ => Err(Box::from(NOT_SUPPORTED_ON_MOCK_ERROR)),
698        }
699    }
700
701    pub fn get_id(&self) -> String {
702        get_inner_and_call!(self, BluetoothGATTDescriptor, get_id)
703    }
704
705    #[cfg(feature = "bluetooth-test")]
706    pub fn set_id(&self, id: String) {
707        if let BluetoothGATTDescriptor::Mock(fake_descriptor) = self {
708            fake_descriptor.set_id(id)
709        }
710    }
711
712    pub fn get_uuid(&self) -> Result<String, Box<dyn Error>> {
713        get_inner_and_call!(self, BluetoothGATTDescriptor, get_uuid)
714    }
715
716    #[cfg(feature = "bluetooth-test")]
717    pub fn set_uuid(&self, uuid: String) -> Result<(), Box<dyn Error>> {
718        get_inner_and_call_test_func!(self, BluetoothGATTDescriptor, set_uuid, uuid)
719    }
720
721    pub fn get_value(&self) -> Result<Vec<u8>, Box<dyn Error>> {
722        get_inner_and_call!(self, BluetoothGATTDescriptor, get_value)
723    }
724
725    #[cfg(feature = "bluetooth-test")]
726    pub fn set_value(&self, value: Vec<u8>) -> Result<(), Box<dyn Error>> {
727        get_inner_and_call_test_func!(self, BluetoothGATTDescriptor, set_value, Some(value))
728    }
729
730    pub fn get_flags(&self) -> Result<Vec<String>, Box<dyn Error>> {
731        get_inner_and_call!(self, BluetoothGATTDescriptor, get_flags)
732    }
733
734    #[cfg(feature = "bluetooth-test")]
735    pub fn set_flags(&self, flags: Vec<String>) -> Result<(), Box<dyn Error>> {
736        get_inner_and_call_test_func!(self, BluetoothGATTDescriptor, set_flags, flags)
737    }
738
739    pub fn read_value(&self) -> Result<Vec<u8>, Box<dyn Error>> {
740        get_inner_and_call!(@with_bluez_offset, self, BluetoothGATTDescriptor, read_value)
741    }
742
743    pub fn write_value(&self, values: Vec<u8>) -> Result<(), Box<dyn Error>> {
744        get_inner_and_call!(@with_bluez_offset, self, BluetoothGATTDescriptor, write_value, values)
745    }
746}