use std::error::Error; use std::time::Duration; use bluest::{Adapter, Uuid}; use futures_lite::{future, StreamExt}; use tracing::metadata::LevelFilter; use tracing::{error, info}; const NORDIC_LED_AND_BUTTON_SERVICE: Uuid = Uuid::from_u128(0x00001523_1212_efde_1523_785feabcd123); const BLINKY_BUTTON_STATE_CHARACTERISTIC: Uuid = Uuid::from_u128(0x00001524_1212_efde_1523_785feabcd123); const BLINKY_LED_STATE_CHARACTERISTIC: Uuid = Uuid::from_u128(0x00001525_1212_efde_1523_785feabcd123); #[tokio::main] async fn main() -> Result<(), Box> { use tracing_subscriber::prelude::*; use tracing_subscriber::{fmt, EnvFilter}; tracing_subscriber::registry() .with(fmt::layer()) .with( EnvFilter::builder() .with_default_directive(LevelFilter::INFO.into()) .from_env_lossy(), ) .init(); let adapter = Adapter::default().await.ok_or("Bluetooth adapter not found")?; adapter.wait_available().await?; info!("looking for device"); let device = adapter .discover_devices(&[NORDIC_LED_AND_BUTTON_SERVICE]) .await? .next() .await .ok_or("Failed to discover device")??; info!( "found device: {} ({:?})", device.name().as_deref().unwrap_or("(unknown)"), device.id() ); adapter.connect_device(&device).await?; info!("connected!"); let service = match device .discover_services_with_uuid(NORDIC_LED_AND_BUTTON_SERVICE) .await? .first() { Some(service) => service.clone(), None => return Err("service not found".into()), }; info!("found LED and button service"); let characteristics = service.characteristics().await?; info!("discovered characteristics"); let button_characteristic = characteristics .iter() .find(|x| x.uuid() == BLINKY_BUTTON_STATE_CHARACTERISTIC) .ok_or("button characteristic not found")?; let button_fut = async { info!("enabling button notifications"); let mut updates = button_characteristic.notify().await?; info!("waiting for button changes"); while let Some(val) = updates.next().await { info!("Button state changed: {:?}", val?); } Ok(()) }; let led_characteristic = characteristics .iter() .find(|x| x.uuid() == BLINKY_LED_STATE_CHARACTERISTIC) .ok_or("led characteristic not found")?; let blink_fut = async { info!("blinking LED"); tokio::time::sleep(Duration::from_secs(1)).await; loop { led_characteristic.write(&[0x01]).await?; info!("LED on"); tokio::time::sleep(Duration::from_secs(1)).await; led_characteristic.write(&[0x00]).await?; info!("LED off"); tokio::time::sleep(Duration::from_secs(1)).await; } }; type R = Result<(), Box>; let button_fut = async move { let res: R = button_fut.await; error!("Button task exited: {:?}", res); }; let blink_fut = async move { let res: R = blink_fut.await; error!("Blink task exited: {:?}", res); }; future::zip(blink_fut, button_fut).await; Ok(()) }