This commit is contained in:
Robin Appelman 2024-11-17 18:22:10 +01:00
commit 7c3d4a7867
10 changed files with 1435 additions and 653 deletions

View file

@ -1,41 +1,41 @@
mod config;
use btleplug::api::{Central, Manager as _};
use btleplug::platform::Manager;
use log::info;
use tracing::info;
use main_error::MainError;
use mitemp::{listen, BDAddr, Sensor};
use std::collections::HashMap;
use std::collections::{BTreeMap, HashMap};
use std::fmt::Write;
use std::str::FromStr;
use std::sync::{Arc, Mutex};
use tokio::{pin, spawn};
use tokio_stream::StreamExt;
use warp::Filter;
use clap::Parser;
use tokio::net::UnixListener;
use tokio_stream::wrappers::UnixListenerStream;
use crate::config::{Config, ListenConfig};
type Cache = Arc<Mutex<HashMap<BDAddr, Sensor>>>;
#[derive(Parser, Debug)]
#[command(author, version, about, long_about = None)]
struct Args {
/// Config file to use, if omitted the config will be loaded from environment variables
config: Option<String>,
}
#[tokio::main]
async fn main() -> Result<(), MainError> {
env_logger::init();
tracing_subscriber::fmt::init();
let cache: Cache = Arc::default();
let mut env: HashMap<String, String> = dotenv::vars().collect();
let port = env
.get("PORT")
.and_then(|s| u16::from_str(s).ok())
.unwrap_or(80);
let names = env.remove("NAMES").unwrap_or_default();
let names = names
.split(',')
.map(|pair| {
let mut parts = pair.split('=');
if let (Some(Ok(mac)), Some(name)) = (parts.next().map(BDAddr::from_str), parts.next())
{
Ok((mac, name.to_string()))
} else {
Err(MainError::from("Invalid NAMES"))
}
})
.collect::<Result<HashMap<BDAddr, String>, MainError>>()?;
let args = Args::parse();
let config = match args.config {
Some(path) => Config::from_file(path)?,
_ => Config::from_env()?,
};
info!("{} devices configured", config.names.len());
let manager = Manager::new().await?;
for adapter in manager.adapters().await? {
@ -60,6 +60,7 @@ async fn main() -> Result<(), MainError> {
});
}
let names = config.names;
let metrics = warp::path!("metrics").map(move || {
let mut result = String::new();
@ -70,7 +71,16 @@ async fn main() -> Result<(), MainError> {
result
});
warp::serve(metrics).run(([0, 0, 0, 0], port)).await;
match config.listen {
ListenConfig::Ip { address, port } => {
warp::serve(metrics).run((address, port)).await;
}
ListenConfig::Unix { socket: path } => {
let listener = UnixListener::bind(path).unwrap();
let incoming = UnixListenerStream::new(listener);
warp::serve(metrics).run_incoming(incoming).await;
}
}
Ok(())
}
@ -78,7 +88,7 @@ async fn main() -> Result<(), MainError> {
fn format<W: Write>(
mut writer: W,
sensor: &Sensor,
names: &HashMap<BDAddr, String>,
names: &BTreeMap<BDAddr, String>,
) -> std::fmt::Result {
if sensor.data.temperature == 0.0 || sensor.data.humidity == 0.0 {
return Ok(());
@ -92,7 +102,7 @@ fn format<W: Write>(
name, sensor.mac, sensor.data.battery
)?;
} else {
info!("Skipping unnamed censor {}", sensor.mac);
info!("Skipping unnamed sensor {}", sensor.mac);
}
}
if let Some(name) = name {
@ -107,7 +117,7 @@ fn format<W: Write>(
name, sensor.mac, sensor.data.humidity
)?;
} else {
info!("Skipping unnamed censor {}", sensor.mac);
info!("Skipping unnamed sensor {}", sensor.mac);
}
Ok(())