1use std::borrow::ToOwned;
6use std::cell::RefCell;
7use std::collections::{HashMap, HashSet};
8use std::error::Error;
9use std::string::String;
10
11use uuid::Uuid;
12
13use crate::BluetoothManager;
14use crate::bluetooth::{
15 BluetoothAdapter, BluetoothDevice, BluetoothGATTCharacteristic, BluetoothGATTDescriptor,
16 BluetoothGATTService,
17};
18
19thread_local!(pub static CACHED_IDS: RefCell<HashSet<Uuid>> = RefCell::new(HashSet::new()));
20
21const ADAPTER_ERROR: &str = "No adapter found";
22const WRONG_DATA_SET_ERROR: &str = "Wrong data set name was provided";
23const READ_FLAG: &str = "read";
24const WRITE_FLAG: &str = "write";
25const NOTIFY_FLAG: &str = "notify";
26
27const NOT_PRESENT_ADAPTER: &str = "NotPresentAdapter";
30const NOT_POWERED_ADAPTER: &str = "NotPoweredAdapter";
32const EMPTY_ADAPTER: &str = "EmptyAdapter";
34const GLUCOSE_HEART_RATE_ADAPTER: &str = "GlucoseHeartRateAdapter";
36const UNICODE_DEVICE_ADAPTER: &str = "UnicodeDeviceAdapter";
38const MISSING_SERVICE_HEART_RATE_ADAPTER: &str = "MissingServiceHeartRateAdapter";
40const MISSING_CHARACTERISTIC_HEART_RATE_ADAPTER: &str = "MissingCharacteristicHeartRateAdapter";
42const MISSING_DESCRIPTOR_HEART_RATE_ADAPTER: &str = "MissingDescriptorHeartRateAdapter";
43const HEART_RATE_ADAPTER: &str = "HeartRateAdapter";
45const EMPTY_NAME_HEART_RATE_ADAPTER: &str = "EmptyNameHeartRateAdapter";
47const NO_NAME_HEART_RATE_ADAPTER: &str = "NoNameHeartRateAdapter";
49const TWO_HEART_RATE_SERVICES_ADAPTER: &str = "TwoHeartRateServicesAdapter";
51const BLOCKLIST_TEST_ADAPTER: &str = "BlocklistTestAdapter";
52
53const CONNECTABLE_DEVICE_NAME: &str = "Connectable Device";
55const EMPTY_DEVICE_NAME: &str = "";
56const GLUCOSE_DEVICE_NAME: &str = "Glucose Device";
58const HEART_RATE_DEVICE_NAME: &str = "Heart Rate Device";
60const UNICODE_DEVICE_NAME: &str = "❤❤❤❤❤❤❤❤❤";
61
62const CONNECTABLE_DEVICE_ADDRESS: &str = "00:00:00:00:00:04";
64const GLUCOSE_DEVICE_ADDRESS: &str = "00:00:00:00:00:02";
66const HEART_RATE_DEVICE_ADDRESS: &str = "00:00:00:00:00:03";
68const UNICODE_DEVICE_ADDRESS: &str = "00:00:00:00:00:01";
69
70const BLOCKLIST_TEST_SERVICE_UUID: &str = "611c954a-263b-4f4a-aab6-01ddb953f985";
72const DEVICE_INFORMATION_UUID: &str = "0000180a-0000-1000-8000-00805f9b34fb";
74const GENERIC_ACCESS_SERVICE_UUID: &str = "00001800-0000-1000-8000-00805f9b34fb";
76const GLUCOSE_SERVICE_UUID: &str = "00001808-0000-1000-8000-00805f9b34fb";
78const HEART_RATE_SERVICE_UUID: &str = "0000180d-0000-1000-8000-00805f9b34fb";
80const HUMAN_INTERFACE_DEVICE_SERVICE_UUID: &str = "00001812-0000-1000-8000-00805f9b34fb";
83const TX_POWER_SERVICE_UUID: &str = "00001804-0000-1000-8000-00805f9b34fb";
85
86const BLOCKLIST_EXCLUDE_READS_CHARACTERISTIC_UUID: &str = "bad1c9a2-9a5b-4015-8b60-1579bbbf2135";
88const BODY_SENSOR_LOCATION_CHARACTERISTIC_UUID: &str = "00002a38-0000-1000-8000-00805f9b34fb";
91const DEVICE_NAME_CHARACTERISTIC_UUID: &str = "00002a00-0000-1000-8000-00805f9b34fb";
94const HEART_RATE_MEASUREMENT_CHARACTERISTIC_UUID: &str = "00002a37-0000-1000-8000-00805f9b34fb";
97const PERIPHERAL_PRIVACY_FLAG_CHARACTERISTIC_UUID: &str = "00002a02-0000-1000-8000-00805f9b34fb";
100const SERIAL_NUMBER_STRING_UUID: &str = "00002a25-0000-1000-8000-00805f9b34fb";
103
104const BLOCKLIST_EXCLUDE_READS_DESCRIPTOR_UUID: &str = "aaaaaaaa-aaaa-1181-0510-810819516110";
106const BLOCKLIST_DESCRIPTOR_UUID: &str = "07711111-6104-0970-7011-1107105110aa";
107const CHARACTERISTIC_USER_DESCRIPTION_UUID: &str = "00002901-0000-1000-8000-00805f9b34fb";
110const CLIENT_CHARACTERISTIC_CONFIGURATION_UUID: &str = "00002902-0000-1000-8000-00805f9b34fb";
113const NUMBER_OF_DIGITALS_UUID: &str = "00002909-0000-1000-8000-00805f9b34fb";
116
117const HEART_RATE_DEVICE_NAME_DESCRIPTION: &str = "The name of this device.";
118
119fn generate_id() -> Uuid {
120 let mut id = Uuid::nil();
121 let mut generated = false;
122 while !generated {
123 id = Uuid::new_v4();
124 CACHED_IDS.with(|cache| {
125 if !cache.borrow().contains(&id) {
126 cache.borrow_mut().insert(id);
127 generated = true;
128 }
129 });
130 }
131 id
132}
133
134fn set_adapter(adapter: &BluetoothAdapter, adapter_name: String) -> Result<(), Box<dyn Error>> {
136 adapter.set_name(adapter_name)?;
137 adapter.set_powered(true)?;
138 adapter.set_discoverable(true)?;
139 Ok(())
140}
141
142fn create_device(
144 adapter: &BluetoothAdapter,
145 name: String,
146 address: String,
147) -> Result<BluetoothDevice, Box<dyn Error>> {
148 let device = adapter.create_mock_device(generate_id().to_string())?;
149 device.set_name(Some(name))?;
150 device.set_address(address)?;
151 device.set_connectable(true)?;
152 Ok(device)
153}
154
155fn create_device_with_uuids(
157 adapter: &BluetoothAdapter,
158 name: String,
159 address: String,
160 uuids: Vec<String>,
161) -> Result<BluetoothDevice, Box<dyn Error>> {
162 let device = create_device(adapter, name, address)?;
163 device.set_uuids(uuids)?;
164 Ok(device)
165}
166
167fn create_service(
169 device: &BluetoothDevice,
170 uuid: String,
171) -> Result<BluetoothGATTService, Box<dyn Error>> {
172 let service =
173 BluetoothGATTService::create_mock_service(device.clone(), generate_id().to_string())?;
174 service.set_uuid(uuid)?;
175 Ok(service)
176}
177
178fn create_characteristic(
180 service: &BluetoothGATTService,
181 uuid: String,
182) -> Result<BluetoothGATTCharacteristic, Box<dyn Error>> {
183 let characteristic = BluetoothGATTCharacteristic::create_mock_characteristic(
184 service.clone(),
185 generate_id().to_string(),
186 )?;
187 characteristic.set_uuid(uuid)?;
188 Ok(characteristic)
189}
190
191fn create_characteristic_with_value(
193 service: &BluetoothGATTService,
194 uuid: String,
195 value: Vec<u8>,
196) -> Result<BluetoothGATTCharacteristic, Box<dyn Error>> {
197 let characteristic = create_characteristic(service, uuid)?;
198 characteristic.set_value(value)?;
199 Ok(characteristic)
200}
201
202fn create_descriptor(
204 characteristic: &BluetoothGATTCharacteristic,
205 uuid: String,
206) -> Result<BluetoothGATTDescriptor, Box<dyn Error>> {
207 let descriptor = BluetoothGATTDescriptor::create_mock_descriptor(
208 characteristic.clone(),
209 generate_id().to_string(),
210 )?;
211 descriptor.set_uuid(uuid)?;
212 Ok(descriptor)
213}
214
215fn create_descriptor_with_value(
217 characteristic: &BluetoothGATTCharacteristic,
218 uuid: String,
219 value: Vec<u8>,
220) -> Result<BluetoothGATTDescriptor, Box<dyn Error>> {
221 let descriptor = create_descriptor(characteristic, uuid)?;
222 descriptor.set_value(value)?;
223 Ok(descriptor)
224}
225
226fn create_heart_rate_service(
227 device: &BluetoothDevice,
228 empty: bool,
229) -> Result<BluetoothGATTService, Box<dyn Error>> {
230 let heart_rate_service = create_service(device, HEART_RATE_SERVICE_UUID.to_owned())?;
232
233 if empty {
234 return Ok(heart_rate_service);
235 }
236
237 let heart_rate_measurement_characteristic = create_characteristic_with_value(
239 &heart_rate_service,
240 HEART_RATE_MEASUREMENT_CHARACTERISTIC_UUID.to_owned(),
241 vec![0],
242 )?;
243 heart_rate_measurement_characteristic.set_flags(vec![
244 NOTIFY_FLAG.to_string(),
245 READ_FLAG.to_string(),
246 WRITE_FLAG.to_string(),
247 ])?;
248
249 let body_sensor_location_characteristic_1 = create_characteristic_with_value(
251 &heart_rate_service,
252 BODY_SENSOR_LOCATION_CHARACTERISTIC_UUID.to_owned(),
253 vec![49],
254 )?;
255 body_sensor_location_characteristic_1
256 .set_flags(vec![READ_FLAG.to_string(), WRITE_FLAG.to_string()])?;
257
258 let body_sensor_location_characteristic_2 = create_characteristic_with_value(
260 &heart_rate_service,
261 BODY_SENSOR_LOCATION_CHARACTERISTIC_UUID.to_owned(),
262 vec![50],
263 )?;
264 body_sensor_location_characteristic_2
265 .set_flags(vec![READ_FLAG.to_string(), WRITE_FLAG.to_string()])?;
266 Ok(heart_rate_service)
267}
268
269fn create_generic_access_service(
270 device: &BluetoothDevice,
271 empty: bool,
272) -> Result<BluetoothGATTService, Box<dyn Error>> {
273 let generic_access_service = create_service(device, GENERIC_ACCESS_SERVICE_UUID.to_owned())?;
275
276 if empty {
277 return Ok(generic_access_service);
278 }
279
280 let device_name_characteristic = create_characteristic_with_value(
282 &generic_access_service,
283 DEVICE_NAME_CHARACTERISTIC_UUID.to_owned(),
284 HEART_RATE_DEVICE_NAME.as_bytes().to_vec(),
285 )?;
286 device_name_characteristic.set_flags(vec![READ_FLAG.to_string(), WRITE_FLAG.to_string()])?;
287
288 let number_of_digitals_descriptor_1 = create_descriptor_with_value(
290 &device_name_characteristic,
291 NUMBER_OF_DIGITALS_UUID.to_owned(),
292 vec![49],
293 )?;
294 number_of_digitals_descriptor_1
295 .set_flags(vec![READ_FLAG.to_string(), WRITE_FLAG.to_string()])?;
296
297 let number_of_digitals_descriptor_2 = create_descriptor_with_value(
298 &device_name_characteristic,
299 NUMBER_OF_DIGITALS_UUID.to_owned(),
300 vec![50],
301 )?;
302 number_of_digitals_descriptor_2
303 .set_flags(vec![READ_FLAG.to_string(), WRITE_FLAG.to_string()])?;
304
305 let _characteristic_user_description = create_descriptor_with_value(
307 &device_name_characteristic,
308 CHARACTERISTIC_USER_DESCRIPTION_UUID.to_owned(),
309 HEART_RATE_DEVICE_NAME_DESCRIPTION.as_bytes().to_vec(),
310 )?;
311
312 let _client_characteristic_configuration = create_descriptor_with_value(
314 &device_name_characteristic,
315 CLIENT_CHARACTERISTIC_CONFIGURATION_UUID.to_owned(),
316 vec![0],
317 )?;
318
319 let peripheral_privacy_flag_characteristic = create_characteristic(
321 &generic_access_service,
322 PERIPHERAL_PRIVACY_FLAG_CHARACTERISTIC_UUID.to_owned(),
323 )?;
324 peripheral_privacy_flag_characteristic
325 .set_flags(vec![READ_FLAG.to_string(), WRITE_FLAG.to_string()])?;
326 Ok(generic_access_service)
327}
328
329fn create_heart_rate_device(
331 adapter: &BluetoothAdapter,
332 empty: bool,
333) -> Result<BluetoothDevice, Box<dyn Error>> {
334 let heart_rate_device = create_device_with_uuids(
336 adapter,
337 HEART_RATE_DEVICE_NAME.to_owned(),
338 HEART_RATE_DEVICE_ADDRESS.to_owned(),
339 vec![
340 GENERIC_ACCESS_SERVICE_UUID.to_owned(),
341 HEART_RATE_SERVICE_UUID.to_owned(),
342 ],
343 )?;
344
345 if empty {
346 return Ok(heart_rate_device);
347 }
348
349 let _generic_access_service = create_generic_access_service(&heart_rate_device, false)?;
351
352 let _heart_rate_service = create_heart_rate_service(&heart_rate_device, false)?;
354
355 Ok(heart_rate_device)
356}
357
358fn create_missing_characterisitc_heart_rate_device(
359 adapter: &BluetoothAdapter,
360) -> Result<(), Box<dyn Error>> {
361 let heart_rate_device_empty = create_heart_rate_device(adapter, true)?;
362
363 let _generic_access_service_empty =
364 create_generic_access_service(&heart_rate_device_empty, true)?;
365
366 let _heart_rate_service_empty = create_heart_rate_service(&heart_rate_device_empty, true)?;
367
368 Ok(())
369}
370
371fn create_missing_descriptor_heart_rate_device(
372 adapter: &BluetoothAdapter,
373) -> Result<(), Box<dyn Error>> {
374 let heart_rate_device_empty = create_heart_rate_device(adapter, true)?;
375
376 let generic_access_service_empty =
377 create_generic_access_service(&heart_rate_device_empty, true)?;
378
379 let _device_name_characteristic = create_characteristic_with_value(
380 &generic_access_service_empty,
381 DEVICE_NAME_CHARACTERISTIC_UUID.to_owned(),
382 HEART_RATE_DEVICE_NAME.as_bytes().to_vec(),
383 )?;
384
385 let peripheral_privacy_flag_characteristic = create_characteristic(
386 &generic_access_service_empty,
387 PERIPHERAL_PRIVACY_FLAG_CHARACTERISTIC_UUID.to_owned(),
388 )?;
389 peripheral_privacy_flag_characteristic
390 .set_flags(vec![READ_FLAG.to_string(), WRITE_FLAG.to_string()])?;
391
392 let _heart_rate_service = create_heart_rate_service(&heart_rate_device_empty, false)?;
393
394 Ok(())
395}
396
397fn create_two_heart_rate_services_device(adapter: &BluetoothAdapter) -> Result<(), Box<dyn Error>> {
398 let heart_rate_device_empty = create_heart_rate_device(adapter, true)?;
399
400 heart_rate_device_empty.set_uuids(vec![
401 GENERIC_ACCESS_SERVICE_UUID.to_owned(),
402 HEART_RATE_SERVICE_UUID.to_owned(),
403 HEART_RATE_SERVICE_UUID.to_owned(),
404 ])?;
405
406 let _generic_access_service = create_generic_access_service(&heart_rate_device_empty, false)?;
407
408 let heart_rate_service_empty_1 = create_heart_rate_service(&heart_rate_device_empty, true)?;
409
410 let heart_rate_service_empty_2 = create_heart_rate_service(&heart_rate_device_empty, true)?;
411
412 let heart_rate_measurement_characteristic = create_characteristic_with_value(
413 &heart_rate_service_empty_1,
414 HEART_RATE_MEASUREMENT_CHARACTERISTIC_UUID.to_owned(),
415 vec![0],
416 )?;
417 heart_rate_measurement_characteristic.set_flags(vec![NOTIFY_FLAG.to_string()])?;
418
419 let _body_sensor_location_characteristic_1 = create_characteristic_with_value(
420 &heart_rate_service_empty_1,
421 BODY_SENSOR_LOCATION_CHARACTERISTIC_UUID.to_owned(),
422 vec![49],
423 )?;
424
425 let _body_sensor_location_characteristic_2 = create_characteristic_with_value(
426 &heart_rate_service_empty_2,
427 BODY_SENSOR_LOCATION_CHARACTERISTIC_UUID.to_owned(),
428 vec![50],
429 )?;
430 Ok(())
431}
432
433fn create_blocklisted_device(adapter: &BluetoothAdapter) -> Result<(), Box<dyn Error>> {
434 let connectable_device = create_device_with_uuids(
435 adapter,
436 CONNECTABLE_DEVICE_NAME.to_owned(),
437 CONNECTABLE_DEVICE_ADDRESS.to_owned(),
438 vec![
439 BLOCKLIST_TEST_SERVICE_UUID.to_owned(),
440 DEVICE_INFORMATION_UUID.to_owned(),
441 GENERIC_ACCESS_SERVICE_UUID.to_owned(),
442 HEART_RATE_SERVICE_UUID.to_owned(),
443 HUMAN_INTERFACE_DEVICE_SERVICE_UUID.to_owned(),
444 ],
445 )?;
446
447 let blocklist_test_service =
448 create_service(&connectable_device, BLOCKLIST_TEST_SERVICE_UUID.to_owned())?;
449
450 let blocklist_exclude_reads_characteristic = create_characteristic(
451 &blocklist_test_service,
452 BLOCKLIST_EXCLUDE_READS_CHARACTERISTIC_UUID.to_owned(),
453 )?;
454 blocklist_exclude_reads_characteristic
455 .set_flags(vec![READ_FLAG.to_string(), WRITE_FLAG.to_string()])?;
456
457 let _blocklist_exclude_reads_descriptor = create_descriptor_with_value(
458 &blocklist_exclude_reads_characteristic,
459 BLOCKLIST_EXCLUDE_READS_DESCRIPTOR_UUID.to_owned(),
460 vec![54; 3],
461 )?;
462
463 let _blocklist_descriptor = create_descriptor_with_value(
464 &blocklist_exclude_reads_characteristic,
465 BLOCKLIST_DESCRIPTOR_UUID.to_owned(),
466 vec![54; 3],
467 )?;
468
469 let device_information_service =
470 create_service(&connectable_device, DEVICE_INFORMATION_UUID.to_owned())?;
471
472 let _serial_number_string_characteristic = create_characteristic(
473 &device_information_service,
474 SERIAL_NUMBER_STRING_UUID.to_owned(),
475 )?;
476
477 let _generic_access_service = create_generic_access_service(&connectable_device, false)?;
478
479 let _heart_rate_service = create_heart_rate_service(&connectable_device, false)?;
480
481 let _human_interface_device_service = create_service(
482 &connectable_device,
483 HUMAN_INTERFACE_DEVICE_SERVICE_UUID.to_owned(),
484 )?;
485 Ok(())
486}
487
488fn create_glucose_heart_rate_devices(adapter: &BluetoothAdapter) -> Result<(), Box<dyn Error>> {
489 let glucose_devie = create_device_with_uuids(
490 adapter,
491 GLUCOSE_DEVICE_NAME.to_owned(),
492 GLUCOSE_DEVICE_ADDRESS.to_owned(),
493 vec![
494 GLUCOSE_SERVICE_UUID.to_owned(),
495 TX_POWER_SERVICE_UUID.to_owned(),
496 ],
497 )?;
498
499 let heart_rate_device_empty = create_heart_rate_device(adapter, true)?;
500
501 let mut manufacturer_dta = HashMap::new();
502 manufacturer_dta.insert(17, vec![1, 2, 3]);
503 glucose_devie.set_manufacturer_data(manufacturer_dta)?;
504
505 let mut service_data = HashMap::new();
506 service_data.insert(GLUCOSE_SERVICE_UUID.to_owned(), vec![1, 2, 3]);
507 glucose_devie.set_service_data(service_data)?;
508
509 service_data = HashMap::new();
510 service_data.insert(HEART_RATE_SERVICE_UUID.to_owned(), vec![1, 2, 3]);
511 heart_rate_device_empty.set_service_data(service_data)?;
512 Ok(())
513}
514
515pub fn test(manager: &mut BluetoothManager, data_set_name: String) -> Result<(), Box<dyn Error>> {
516 let may_existing_adapter = manager.get_or_create_adapter();
517 let adapter = match may_existing_adapter.as_ref() {
518 Some(adapter) => adapter,
519 None => return Err(Box::from(ADAPTER_ERROR.to_string())),
520 };
521 match data_set_name.as_str() {
522 NOT_PRESENT_ADAPTER => {
523 set_adapter(adapter, NOT_PRESENT_ADAPTER.to_owned())?;
524 adapter.set_present(false)?;
525 },
526 NOT_POWERED_ADAPTER => {
527 set_adapter(adapter, NOT_POWERED_ADAPTER.to_owned())?;
528 adapter.set_powered(false)?;
529 },
530 EMPTY_ADAPTER => {
531 set_adapter(adapter, EMPTY_ADAPTER.to_owned())?;
532 },
533 GLUCOSE_HEART_RATE_ADAPTER => {
534 set_adapter(adapter, GLUCOSE_HEART_RATE_ADAPTER.to_owned())?;
535 create_glucose_heart_rate_devices(adapter)?;
536 },
537 UNICODE_DEVICE_ADAPTER => {
538 set_adapter(adapter, UNICODE_DEVICE_ADAPTER.to_owned())?;
539
540 let _unicode_device = create_device(
541 adapter,
542 UNICODE_DEVICE_NAME.to_owned(),
543 UNICODE_DEVICE_ADDRESS.to_owned(),
544 )?;
545 },
546 MISSING_SERVICE_HEART_RATE_ADAPTER => {
547 set_adapter(adapter, MISSING_SERVICE_HEART_RATE_ADAPTER.to_owned())?;
548
549 let _heart_rate_device_empty = create_heart_rate_device(adapter, true)?;
550 },
551 MISSING_CHARACTERISTIC_HEART_RATE_ADAPTER => {
552 set_adapter(
553 adapter,
554 MISSING_CHARACTERISTIC_HEART_RATE_ADAPTER.to_owned(),
555 )?;
556
557 create_missing_characterisitc_heart_rate_device(adapter)?;
558 },
559 MISSING_DESCRIPTOR_HEART_RATE_ADAPTER => {
560 set_adapter(adapter, MISSING_DESCRIPTOR_HEART_RATE_ADAPTER.to_owned())?;
561
562 create_missing_descriptor_heart_rate_device(adapter)?;
563 },
564 HEART_RATE_ADAPTER => {
565 set_adapter(adapter, HEART_RATE_ADAPTER.to_owned())?;
566
567 let _heart_rate_device = create_heart_rate_device(adapter, false)?;
568 },
569 EMPTY_NAME_HEART_RATE_ADAPTER => {
570 set_adapter(adapter, EMPTY_NAME_HEART_RATE_ADAPTER.to_owned())?;
571
572 let heart_rate_device = create_heart_rate_device(adapter, false)?;
573 heart_rate_device.set_name(Some(EMPTY_DEVICE_NAME.to_owned()))?;
574 },
575 NO_NAME_HEART_RATE_ADAPTER => {
576 set_adapter(adapter, NO_NAME_HEART_RATE_ADAPTER.to_owned())?;
577
578 let heart_rate_device = create_heart_rate_device(adapter, false)?;
579 heart_rate_device.set_name(None)?;
580 },
581 TWO_HEART_RATE_SERVICES_ADAPTER => {
582 set_adapter(adapter, TWO_HEART_RATE_SERVICES_ADAPTER.to_owned())?;
583
584 create_two_heart_rate_services_device(adapter)?;
585 },
586 BLOCKLIST_TEST_ADAPTER => {
587 set_adapter(adapter, BLOCKLIST_TEST_ADAPTER.to_owned())?;
588
589 create_blocklisted_device(adapter)?;
590 },
591 _ => return Err(Box::from(WRONG_DATA_SET_ERROR.to_string())),
592 }
593 Ok(())
594}