use blew::Peripheral;
use blew::gatt::props::{AttributePermissions, CharacteristicProperties};
use blew::gatt::service::{GattCharacteristic, GattService};
use blew::peripheral::{AdvertisingConfig, PeripheralEvent};
use tokio_stream::StreamExt as _;
use uuid::Uuid;
const SVC_UUID: Uuid = Uuid::from_u128(0x12345678_1234_1234_1234_123456789abc);
const CHAR_UUID: Uuid = Uuid::from_u128(0x12345678_1234_1234_1234_123456789abd);
#[tokio::main(flavor = "current_thread")]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
tracing_subscriber::fmt()
.with_env_filter(tracing_subscriber::EnvFilter::from_default_env())
.init();
let peripheral: Peripheral = Peripheral::new().await?;
peripheral
.add_service(&GattService {
uuid: SVC_UUID,
primary: true,
characteristics: vec![GattCharacteristic {
uuid: CHAR_UUID,
properties: CharacteristicProperties::READ | CharacteristicProperties::WRITE,
permissions: AttributePermissions::READ | AttributePermissions::WRITE,
value: vec![],
descriptors: vec![],
}],
})
.await?;
let mut events = peripheral.events();
peripheral
.start_advertising(&AdvertisingConfig {
local_name: "blew-example".into(),
service_uuids: vec![SVC_UUID],
})
.await?;
println!("Advertising as \"blew-example\" for 30 s ... (Ctrl-C to stop early)");
let deadline = tokio::time::Instant::now() + std::time::Duration::from_secs(30);
loop {
match tokio::time::timeout_at(deadline, events.next()).await {
Ok(Some(event)) => match event {
PeripheralEvent::AdapterStateChanged { powered } => {
println!(" adapter state: powered={powered}");
}
PeripheralEvent::SubscriptionChanged {
client_id,
char_uuid,
subscribed,
} => {
println!(
" subscription: client={client_id} char={char_uuid} \
subscribed={subscribed}"
);
}
PeripheralEvent::ReadRequest {
client_id,
char_uuid,
offset,
responder,
..
} => {
println!(" read: client={client_id} char={char_uuid} offset={offset}");
let reply = b"hello from blew".to_vec();
responder.respond(reply);
}
PeripheralEvent::WriteRequest {
client_id,
char_uuid,
value,
responder,
..
} => {
println!(
" write: client={client_id} char={char_uuid} \
value={:?}",
String::from_utf8_lossy(&value)
);
if let Some(r) = responder {
r.success();
}
}
},
Ok(None) => break, Err(_) => break, }
}
peripheral.stop_advertising().await?;
println!("Done.");
Ok(())
}