use eyre::Report;
use mijia::{MijiaEvent, MijiaSession, SensorProps};
use std::process::exit;
use std::time::Duration;
use tokio::time;
use tokio_stream::StreamExt;
const SCAN_DURATION: Duration = Duration::from_secs(5);
#[tokio::main]
async fn main() -> Result<(), Report> {
pretty_env_logger::init();
let filters = parse_args()?;
let (_, session) = MijiaSession::new().await?;
let mut events = session.event_stream().await?;
session.bt_session.start_discovery().await?;
time::sleep(SCAN_DURATION).await;
let sensors = session.get_sensors().await?;
println!("Sensors:");
for sensor in sensors
.iter()
.filter(|sensor| should_include_sensor(sensor, &filters))
{
println!("Connecting to {} ({})", sensor.mac_address, sensor.id);
if let Err(e) = session.bt_session.connect(&sensor.id).await {
println!("Failed to connect to {}: {:?}", sensor.mac_address, e);
continue;
}
session.start_notify_sensor(&sensor.id).await?;
}
println!("Readings:");
while let Some(event) = events.next().await {
match event {
MijiaEvent::Readings { id, readings } => {
println!("{id}: {readings}");
}
_ => println!("Event: {event:?}"),
}
}
Ok(())
}
fn parse_args() -> Result<Vec<String>, Report> {
let mut args = std::env::args();
let binary_name = args
.next()
.ok_or_else(|| eyre::eyre!("Binary name missing"))?;
let filters: Vec<_> = args.collect();
if filters
.iter()
.any(|f| f.contains(|c: char| !(c.is_ascii_hexdigit() || c == ':')))
{
eprintln!("Invalid MAC addresses {filters:?}");
eprintln!("Usage:");
eprintln!(" {binary_name} [MAC address]...");
exit(1);
}
Ok(filters)
}
fn should_include_sensor(sensor: &SensorProps, filters: &[String]) -> bool {
let mac = sensor.mac_address.to_string();
filters.is_empty() || filters.iter().any(|filter| mac.contains(filter))
}