* wip: openssl autodetection * add voltaile read inside of asset fn * support xcode 15 for --device * vendor openssl on android * Smaller width TUI * switch to anyhow for the entire CLI * add backtrace and print double printing of cargo_metadata errors * add some padding to multi-line anyhow error * check semvers * don't open if not interactive * set the tailwind current_dir so it doesn't twitch * get the oboe demo working * copy the c++ library on android * cleanup env vars * add depinfo watcher * fix stale hotpatches and crate count * add musl support * remove outdated autofmt test * update scanner app * add hotdog app and bundle to ci * upload dx on every branch * collapse mobile into desktop * `dx doctor` command * windows command files * no pipe on doctor * fix ci? * fix links * fix ci * use main instead of nightly * bump node * build cli for host * cargo doc * prep dog_app for bundle * package hotdog * no bundle or nightly cli * comment out nightly cli * add quotes to linker files
95 lines
4.1 KiB
Rust
95 lines
4.1 KiB
Rust
use dioxus::prelude::*;
|
|
|
|
fn main() {
|
|
dioxus::launch(app)
|
|
}
|
|
|
|
fn app() -> Element {
|
|
let mut status = use_resource(|| async {
|
|
use btleplug::api::{Central, Manager as _, Peripheral, ScanFilter};
|
|
|
|
let manager = btleplug::platform::Manager::new().await.unwrap();
|
|
|
|
// get the first bluetooth adapter
|
|
let adapters = manager.adapters().await.unwrap();
|
|
let central = adapters.into_iter().next().unwrap();
|
|
|
|
// start scanning for devices
|
|
central.start_scan(ScanFilter::default()).await.unwrap();
|
|
|
|
tokio::time::sleep(std::time::Duration::from_secs(2)).await;
|
|
|
|
// Return the list of peripherals after scanning
|
|
let mut devices = vec![];
|
|
for p in central.peripherals().await.unwrap() {
|
|
if let Some(p) = p.properties().await.unwrap() {
|
|
devices.push(p);
|
|
}
|
|
}
|
|
|
|
println!("Found {} Bluetooth devices", devices.len());
|
|
|
|
devices
|
|
});
|
|
|
|
let scanning = !status.finished();
|
|
|
|
rsx! {
|
|
link { rel: "stylesheet", href: asset!("/assets/tailwind.css") },
|
|
div {
|
|
div { class: "py-8 px-6",
|
|
div { class: "container px-4 mx-auto",
|
|
h2 { class: "text-2xl font-bold", "Scan for Bluetooth Devices" }
|
|
button {
|
|
class: "inline-block w-full md:w-auto px-6 py-3 font-medium text-white bg-indigo-500 hover:bg-indigo-600 rounded transition duration-200",
|
|
disabled: scanning,
|
|
onclick: move |_| {
|
|
status.restart();
|
|
},
|
|
if scanning { "Scanning" } else { "Scan" }
|
|
}
|
|
}
|
|
}
|
|
|
|
section { class: "py-8",
|
|
div { class: "container px-4 mx-auto",
|
|
div { class: "p-4 mb-6 bg-white shadow rounded overflow-x-auto",
|
|
table { class: "table-auto w-full",
|
|
thead {
|
|
tr { class: "text-xs text-gray-500 text-left",
|
|
th { class: "pl-6 pb-3 font-medium", "Strength" }
|
|
th { class: "pb-3 font-medium", "Network" }
|
|
th { class: "pb-3 font-medium", "Channel" }
|
|
th { class: "pb-3 px-2 font-medium", "Security" }
|
|
}
|
|
}
|
|
|
|
match &*status.read() {
|
|
None => rsx!("no devices yet!"),
|
|
Some(peripherals) => {
|
|
// Create vector of tuples of (signal_level, wifi) for sorting by signal_level
|
|
let mut sorted_devices = peripherals.clone();
|
|
sorted_devices.sort_by(|a, b| a.rssi.partial_cmp(&b.rssi).unwrap());
|
|
|
|
rsx! {
|
|
tbody {
|
|
for peripheral in sorted_devices.into_iter().rev() {
|
|
tr { class: "text-xs bg-gray-50",
|
|
td { class: "py-5 px-6 font-medium", "{peripheral.rssi.unwrap_or(-100)}" }
|
|
td { class: "flex py-3 font-medium", "{peripheral.local_name.clone().unwrap_or_default()}" }
|
|
td { span { class: "inline-block py-1 px-2 text-white bg-green-500 rounded-full", "{peripheral.address}" } }
|
|
td { span { class: "inline-block py-1 px-2 text-purple-500 bg-purple-50 rounded-full", "{peripheral.tx_power_level.unwrap_or_default()}" } }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|