use jzon::JsonValue; use crate::device::{BDAddr, FormattableDevice}; use std::{ fmt::{self, Debug, Display}, time::Instant, }; #[derive(Debug)] pub struct MiTempDevice { pub name: String, pub addr: BDAddr, temperature: f32, humidity: f32, dew_point: f32, battery: u8, pub last_seen: Instant, } impl MiTempDevice { pub fn new(addr: BDAddr, name: String) -> Self { MiTempDevice { name, addr, temperature: 0.0, humidity: 0.0, dew_point: 0.0, battery: 0, last_seen: Instant::now(), } } pub fn update(&mut self, json: &JsonValue) { self.last_seen = Instant::now(); if let Some(temperature) = json["Temperature"].as_number().map(f32::from) { self.temperature = temperature; } if let Some(humidity) = json["Humidity"].as_number().map(f32::from) { self.humidity = humidity; } if let Some(battery) = json["Battery"] .as_number() .and_then(|num| u8::try_from(num).ok()) { self.battery = battery; } if let Some(dew_point) = json["DewPoint"].as_number().map(f32::from) { self.dew_point = dew_point; } } } impl FormattableDevice for MiTempDevice { fn format_open_metrics(&self) -> impl Display + '_ { MitempFormatter { device: self } } } struct MitempFormatter<'a> { device: &'a MiTempDevice, } impl Display for MitempFormatter<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { if self.device.battery > 0 { writeln!( f, "sensor_battery{{mac=\"{}\", name=\"{}\"}} {}", self.device.addr, self.device.name, self.device.battery )?; } if self.device.temperature > 0.0 { writeln!( f, "sensor_temperature{{mac=\"{}\", name=\"{}\"}} {}", self.device.addr, self.device.name, self.device.temperature )?; } if self.device.humidity > 0.0 { writeln!( f, "sensor_humidity{{mac=\"{}\", name=\"{}\"}} {}", self.device.addr, self.device.name, self.device.humidity )?; } Ok(()) } }