I have set up GATT server on Raspberry Pi, and I am experiencing huge delay of about, 1200ms. To check delay, I am using nRF Connect on iPhone. I am using Raspberry Pi zero w and bluez bindings for rust.
I have bluez 5.65.
In my Bluetooth config, I have only edited few lines like this:
[GATT]
Cache = no
Channels = 1
Rust GATT server (it only starts advertisement and if it receives data it prints it to console) it is sample code from GitHub(https://github.com/bluez/bluer/blob/master/bluer/examples/gatt_server_io.rs):
pub async fn init() -> bluer::Result<()> {
let session = bluer::Session::new().await?;
let adapter = session.default_adapter().await?;
adapter.set_powered(true).await?;
println!(
"Advertising on Bluetooth adapter {} with address {}",
adapter.name(),
adapter.address().await?
);
let mut manufacturer_data = BTreeMap::new();
manufacturer_data.insert(MANUFACTURER_ID, vec![0x21, 0x22, 0x23, 0x24]);
let le_advertisement = Advertisement {
service_uuids: vec![SERVICE_UUID].into_iter().collect(),
manufacturer_data,
discoverable: Some(true),
local_name: Some("mnxd".to_string()),
..Default::default()
};
let adv_handle = adapter.advertise(le_advertisement).await?;
println!(
"Serving GATT service on Bluetooth adapter {}",
adapter.name()
);
let (service_control, service_handle) = service_control();
let (char_control, char_handle) = characteristic_control();
let app = Application {
services: vec![Service {
uuid: SERVICE_UUID,
primary: true,
characteristics: vec![Characteristic {
uuid: CHARACTERISTIC_UUID,
write: Some(CharacteristicWrite {
write: true,
write_without_response: true,
method: CharacteristicWriteMethod::Io,
..Default::default()
}),
notify: Some(CharacteristicNotify {
notify: true,
method: CharacteristicNotifyMethod::Io,
..Default::default()
}),
control_handle: char_handle,
..Default::default()
}],
control_handle: service_handle,
..Default::default()
}],
..Default::default()
};
let app_handle = adapter.serve_gatt_application(app).await?;
println!("Service handle is 0x{:x}", service_control.handle()?);
println!("Characteristic handle is 0x{:x}", char_control.handle()?);
println!("Service ready. Press enter to quit.");
let stdin = BufReader::new(tokio::io::stdin());
let mut lines = stdin.lines();
let mut value: Vec<u8> = vec![0x10, 0x01, 0x01, 0x10];
let mut read_buf = Vec::new();
let mut reader_opt: Option<CharacteristicReader> = None;
let mut writer_opt: Option<CharacteristicWriter> = None;
pin_mut!(char_control);
loop {
tokio::select! {
_ = lines.next_line() => break,
evt = char_control.next() => {
match evt {
Some(CharacteristicControlEvent::Write(req)) => {
println!("Accepting write event with MTU {}", req.mtu());
read_buf = vec![0; req.mtu()];
reader_opt = Some(req.accept()?);
},
Some(CharacteristicControlEvent::Notify(notifier)) => {
println!("Accepting notify request event with MTU {}", notifier.mtu());
writer_opt = Some(notifier);
},
None => break,
}
}
read_res = async {
match &mut reader_opt {
Some(reader) => reader.read(&mut read_buf).await,
None => future::pending().await,
}
} => {
match read_res {
Ok(0) => {
warn!("Write stream ended");
reader_opt = None;
}
Ok(n) => {
value = read_buf[0..n].to_vec();
let value_s = String::from_utf8_lossy(&value);
//TODO better names for variables
let mut value_vec: Vec<&str> = value_s.split_whitespace().collect();
match value_vec.len(){
1 => error!("Missing wifi name or password"),
2 =>{
let n_name = value_vec[0].to_string();
let n_passwd: String = value_vec[1].to_string();
let n_passwd: usize = n_passwd.to_string().chars().count();
info!("Network name: {} password: {} - {}", n_name, "*".repeat(n_passwd), n_passwd);
},
_ => error!("Couldn't read wifi name and password: Too many arguments")
}
// for s in bob{
// println!("{}", s);
// }
//println!("{}", &bob)
}
Err(err) => {
error!("Write stream error: {}", &err);
reader_opt = None;
}
}
}
}
}
println!("Removing service and advertisement");
drop(app_handle);
drop(adv_handle);
sleep(Duration::from_secs(1)).await;
Ok(())
}