use std::{ fmt::{self, Display}, time::Instant, }; pub enum DsmrMessageType { Water, Gas, Energy1, Energy2, Power, } #[derive(Debug)] pub struct DsmrState { pub name: String, pub power: Option, pub power_total_tariff_1: Option, pub power_total_tariff_2: Option, pub gas_total: Option, pub water_total: Option, pub last_seen: Instant, } impl DsmrState { pub fn new(name: String) -> Self { DsmrState { name, power: None, power_total_tariff_1: None, power_total_tariff_2: None, gas_total: None, water_total: None, last_seen: Instant::now(), } } pub fn format_open_metrics(&self) -> impl Display + '_ { DsmrFormatter { device: self } } } struct DsmrFormatter<'a> { device: &'a DsmrState, } impl Display for DsmrFormatter<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let power_total = self.device.power_total_tariff_1.unwrap_or_default() + self.device.power_total_tariff_2.unwrap_or_default(); if power_total > 0.0 { writeln!( f, "power_total_kwh{{name=\"{}\"}} {}", self.device.name, power_total )?; } if let Some(power) = self.device.power_total_tariff_1 { writeln!( f, "power_total_low_kwh{{name=\"{}\"}} {}", self.device.name, power )?; } if let Some(power) = self.device.power_total_tariff_2 { writeln!( f, "power_total_high_kwh{{name=\"{}\"}} {}", self.device.name, power )?; } if let Some(power) = self.device.power { writeln!( f, "power_watts{{name=\"{}\"}} {}", self.device.name, power * 1000.0 )?; } if let Some(gas) = self.device.gas_total { writeln!(f, "gas_total_m3{{name=\"{}\"}} {}", self.device.name, gas)?; } if let Some(water) = self.device.water_total { writeln!( f, "water_total_m3{{name=\"{}\"}} {}", self.device.name, water )?; } Ok(()) } }