|
| 1 | +use futures::future::join; |
| 2 | +use std::time::Duration; |
| 3 | +use tokio::select; |
| 4 | +use trouble_example_tests::{TestContext, serial}; |
| 5 | +use trouble_host::prelude::*; |
| 6 | + |
| 7 | +#[tokio::test] |
| 8 | +async fn ble_bas_peripheral_nrf52() { |
| 9 | + let _ = pretty_env_logger::try_init(); |
| 10 | + let firmware = "bins/nrf-sdc/ble_bas_peripheral"; |
| 11 | + let local = tokio::task::LocalSet::new(); |
| 12 | + local |
| 13 | + .run_until(run_bas_peripheral_test( |
| 14 | + &[("target", "nrf52"), ("board", "microbit")], |
| 15 | + firmware, |
| 16 | + )) |
| 17 | + .await; |
| 18 | +} |
| 19 | + |
| 20 | +async fn run_bas_peripheral_test(labels: &[(&str, &str)], firmware: &str) { |
| 21 | + let ctx = TestContext::new(); |
| 22 | + let central = ctx.serial_adapters[0].clone(); |
| 23 | + |
| 24 | + let dut = ctx.find_dut(labels).unwrap(); |
| 25 | + let token = dut.token(); |
| 26 | + let token2 = token.clone(); |
| 27 | + |
| 28 | + // Spawn a runner for the target |
| 29 | + let mut dut = tokio::task::spawn_local(dut.run(firmware.to_string())); |
| 30 | + |
| 31 | + // Run the central in the test using the serial adapter to verify |
| 32 | + let peripheral_address: Address = Address::random([0xff, 0x8f, 0x1a, 0x05, 0xe4, 0xff]); |
| 33 | + let central = tokio::task::spawn_local(async move { |
| 34 | + let controller_central = serial::create_controller(¢ral).await; |
| 35 | + let mut resources: HostResources<DefaultPacketPool, 2, 4> = HostResources::new(); |
| 36 | + let stack = trouble_host::new(controller_central, &mut resources); |
| 37 | + let Host { |
| 38 | + mut central, |
| 39 | + mut runner, |
| 40 | + .. |
| 41 | + } = stack.build(); |
| 42 | + select! { |
| 43 | + r = runner.run() => { |
| 44 | + r |
| 45 | + } |
| 46 | + r = async { |
| 47 | + let config = ConnectConfig { |
| 48 | + connect_params: Default::default(), |
| 49 | + scan_config: ScanConfig { |
| 50 | + active: true, |
| 51 | + filter_accept_list: &[(peripheral_address.kind, &peripheral_address.addr)], |
| 52 | + ..Default::default() |
| 53 | + }, |
| 54 | + }; |
| 55 | + |
| 56 | + log::info!("[central] connecting"); |
| 57 | + loop { |
| 58 | + let conn = central.connect(&config).await.unwrap(); |
| 59 | + log::info!("[central] connected"); |
| 60 | + let client = GattClient::<serial::Controller, DefaultPacketPool, 10>::new(&stack, &conn).await.unwrap(); |
| 61 | + select! { |
| 62 | + _r = async { |
| 63 | + client.task().await.unwrap(); |
| 64 | + } => { |
| 65 | + token.cancel(); |
| 66 | + break; |
| 67 | + } |
| 68 | + _r = async { |
| 69 | + println!("[central] discovering services"); |
| 70 | + const VALUE_UUID: Uuid = Uuid::new_long([ |
| 71 | + 0x00, 0x00, 0x10, 0x01, 0xb0, 0xcd, 0x11, 0xec, 0x87, 0x1f, 0xd4, 0x5d, 0xdf, 0x13, 0x88, 0x40, |
| 72 | + ]); |
| 73 | + let uuid = service::BATTERY.into(); |
| 74 | + let services = client.services_by_uuid(&uuid).await.unwrap(); |
| 75 | + |
| 76 | + let service = services.first().unwrap().clone(); |
| 77 | + |
| 78 | + println!("[central] service discovered successfully"); |
| 79 | + let c: Characteristic<u8> = client.characteristic_by_uuid(&service, &VALUE_UUID).await.unwrap(); |
| 80 | + |
| 81 | + let mut data = [0; 1]; |
| 82 | + client.read_characteristic(&c, &mut data[..]).await.unwrap(); |
| 83 | + println!("[central] read value: {}", data[0]); |
| 84 | + data[0] = data[0].wrapping_add(1); |
| 85 | + println!("[central] write value: {}", data[0]); |
| 86 | + client.write_characteristic(&c, &data[..]).await.unwrap(); |
| 87 | + data[0] = data[0].wrapping_add(1); |
| 88 | + println!("[central] write value: {}", data[0]); |
| 89 | + client.write_characteristic(&c, &data[..]).await.unwrap(); |
| 90 | + println!("[central] write done"); |
| 91 | + } => { |
| 92 | + token.cancel(); |
| 93 | + break; |
| 94 | + } |
| 95 | + } |
| 96 | + } |
| 97 | + Ok(()) |
| 98 | + } => { |
| 99 | + r |
| 100 | + } |
| 101 | + } |
| 102 | + }); |
| 103 | + |
| 104 | + match tokio::time::timeout(Duration::from_secs(30), join(&mut dut, central)).await { |
| 105 | + Err(_) => { |
| 106 | + println!("Test timed out"); |
| 107 | + token2.cancel(); |
| 108 | + let _ = tokio::time::timeout(Duration::from_secs(1), dut).await; |
| 109 | + assert!(false); |
| 110 | + } |
| 111 | + Ok((p, c)) => { |
| 112 | + p.expect("peripheral failed").unwrap(); |
| 113 | + c.expect("central failed").unwrap(); |
| 114 | + } |
| 115 | + } |
| 116 | +} |
0 commit comments