use crate::{
ble::{self, PeripheralOps},
proto, Cube,
};
use anyhow::{anyhow, Context, Result};
use std::fmt::{self, Debug};
use std::time::Duration;
const SEARCH_TIMEOUT: Duration = Duration::from_secs(3);
pub struct Searcher {
searcher: ble::Searcher,
}
impl Debug for Searcher {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("Searcher").finish()
}
}
impl Searcher {
pub fn new() -> Self {
Self {
searcher: ble::searcher(),
}
}
pub async fn all(&mut self) -> Result<Vec<Cube>> {
self.all_timeout(SEARCH_TIMEOUT).await
}
pub async fn nearest(&mut self) -> Result<Cube> {
self.nearest_timeout(SEARCH_TIMEOUT).await
}
pub async fn all_timeout(&mut self, timeout: Duration) -> Result<Vec<Cube>> {
let mut cubes: Vec<_> = self
.do_search(timeout)
.await?
.into_iter()
.map(|a| Cube::new(a))
.collect();
cubes.sort_by(|a, b| b.rssi().cmp(&a.rssi()));
Ok(cubes)
}
pub async fn nearest_timeout(&mut self, timeout: Duration) -> Result<Cube> {
self.do_search(timeout)
.await?
.into_iter()
.max_by(|a, b| a.rssi().cmp(&b.rssi()))
.map(|a| Cube::new(a))
.ok_or_else(|| anyhow!("No cube found"))
}
async fn do_search(&mut self, timeout: Duration) -> Result<Vec<ble::Peripheral>> {
Ok(self
.searcher
.search(&proto::UUID_SERVICE, timeout)
.await
.context("Error on searching cubes")?)
}
}