Hi,
im new to Rust and hope to find some help here.
I try to write a small app which runs in the browser via egui, web_sys, wasm_bindgen.
The goal is to use the (unstable) Bluetooth API to connect to a bluetooth device, fetch & parse data and create some plots of this data.
use eframe::egui;
use js_sys::Array;
use std::str;
use wasm_bindgen::JsValue;
use wasm_bindgen::JsCast;
use wasm_bindgen_futures::spawn_local;
use wasm_bindgen::closure::Closure;
use web_sys::console;
use web_sys::{Bluetooth, Navigator};
pub struct TemplateApp {
gatt_service_characteristics: Option<web_sys::BluetoothRemoteGattCharacteristic>,
}
impl Default for TemplateApp {
fn default() -> Self {
Self {
gatt_service_characteristics: None::<web_sys::BluetoothRemoteGattCharacteristic>,
}
}
}
fn js_array(values: &[&str]) -> JsValue {
return JsValue::from(
values
.into_iter()
.map(|x| JsValue::from_str(x))
.collect::<Array>(),
);
}
impl eframe::App for TemplateApp {
/// Called each time the UI needs repainting, which may be many times per second.
/// Put your widgets into a `SidePanel`, `TopPanel`, `CentralPanel`, `Window` or `Area`.
fn update(&mut self, ctx: &egui::Context, frame: &mut eframe::Frame) {
let Self { gatt_service_characteristics } = self;
egui::CentralPanel::default().show(ctx, |ui| {
ui.heading("example App");
if ui.button("Connect BLE").clicked() {
let window = web_sys::window().expect("Missing Window");
let navigator = window.navigator();
let blue = navigator.bluetooth().unwrap();
let mut opt = web_sys::RequestDeviceOptions::new();
opt.accept_all_devices(true);
opt.optional_services(&js_array(&["0000ffe0-0000-1000-8000-00805f9b34fb"]));
let res_promise = blue.request_device(&opt);
let res_future = wasm_bindgen_futures::JsFuture::from(res_promise);
spawn_local(async move{
match res_future.await {
Ok(message) => {
let device = web_sys::BluetoothDevice::from(message);
let gatt_server = device.gatt().unwrap();
let connect_promise = gatt_server.connect();
let connect_future =
wasm_bindgen_futures::JsFuture::from(connect_promise);
let gatt_server = web_sys::BluetoothRemoteGattServer::from(
connect_future.await.unwrap(),
);
let gatt_service_promise = gatt_server.get_primary_service_with_str(
"0000ffe0-0000-1000-8000-00805f9b34fb",
);
let gatt_service_future =
wasm_bindgen_futures::JsFuture::from(gatt_service_promise);
let remote_gatt_service = web_sys::BluetoothRemoteGattService::from(
gatt_service_future.await.unwrap(),
);
console::log_2(
&"remote_gatt_service : %s".into(),
&remote_gatt_service.uuid().into(),
);
let gatt_service_characteristics_promise = remote_gatt_service
.get_characteristic_with_str(
"0000ffe1-0000-1000-8000-00805f9b34fb",
);
let gatt_service_characteristics_future =
wasm_bindgen_futures::JsFuture::from(
gatt_service_characteristics_promise,
);
*gatt_service_characteristics = Some(
web_sys::BluetoothRemoteGattCharacteristic::from(
gatt_service_characteristics_future.await.unwrap(),
));
console::log_2(
&"remote_gatt_characteristics : %s".into(),
&gatt_service_characteristics.unwrap().uuid().into(),
);
}
Err(e) => {}
}
});
}
});
}
}
Actually the compiler complains about the lifetime:
error[E0759]: `self` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement
--> src\app.rs:35:20
|
34 | fn update(&mut self, ctx: &egui::Context, frame: &mut eframe::Frame) {
| --------- this data with an anonymous lifetime `'_`...
35 | let Self { gatt_service_characteristics } = self;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...is used here...
...
55 | spawn_local(async move{
| ----------- ...and is required to live as long as `'static` here
|
note: `'static` lifetime requirement introduced by this bound
--> cargo\registry\src\github.com-1ecc6299db9ec823\wasm-bindgen-futures-0.4.30\src\lib.rs:79:30
|
79 | F: Future<Output = ()> + 'static,
| ^^^^^^^
- How can i set the correct lifetime for gatt_service_characteristics ? And is this even the right approach to use it elsewhere after connection succeeded?
Any other suggestion on dealing with promises/futures (as this feels a bit clumsy) or about a better option for "spawn_local" are highly welcome.
Thanks