formattable trait

This commit is contained in:
Robin Appelman 2026-06-27 00:13:40 +02:00
commit e13243f9a5
6 changed files with 36 additions and 18 deletions

View file

@ -3,6 +3,8 @@ use std::{
time::Instant, time::Instant,
}; };
use crate::device::FormattableDevice;
pub enum DsmrMessageType { pub enum DsmrMessageType {
Water, Water,
Gas, Gas,
@ -34,8 +36,10 @@ impl DsmrState {
last_seen: Instant::now(), last_seen: Instant::now(),
} }
} }
}
pub fn format_open_metrics(&self) -> impl Display + '_ { impl FormattableDevice for DsmrState {
fn format_open_metrics(&self) -> impl Display + '_ {
DsmrFormatter { device: self } DsmrFormatter { device: self }
} }
} }

View file

@ -1,6 +1,6 @@
use jzon::JsonValue; use jzon::JsonValue;
use crate::device::BDAddr; use crate::device::{BDAddr, FormattableDevice};
use std::{ use std::{
fmt::{self, Debug, Display}, fmt::{self, Debug, Display},
time::Instant, time::Instant,
@ -48,8 +48,10 @@ impl MiTempDevice {
self.dew_point = dew_point; self.dew_point = dew_point;
} }
} }
}
pub fn format_open_metrics(&self) -> impl Display + '_ { impl FormattableDevice for MiTempDevice {
fn format_open_metrics(&self) -> impl Display + '_ {
MitempFormatter { device: self } MitempFormatter { device: self }
} }
} }

View file

@ -32,6 +32,10 @@ pub struct DeviceStates {
active_rf_temp_id: RfDeviceId, active_rf_temp_id: RfDeviceId,
} }
pub trait FormattableDevice {
fn format_open_metrics(&self) -> impl Display + '_;
}
impl DeviceStates { impl DeviceStates {
pub fn new( pub fn new(
mi_temp_names: BTreeMap<BDAddr, String>, mi_temp_names: BTreeMap<BDAddr, String>,
@ -44,12 +48,12 @@ impl DeviceStates {
} }
} }
pub fn devices(&self) -> impl Iterator<Item = (&Device, &DeviceState)> { pub fn devices(&self) -> impl Iterator<Item = &impl FormattableDevice> {
self.devices.iter() self.devices.values()
} }
pub fn dsmr_devices(&self) -> impl Iterator<Item = (&Device, &DsmrState)> { pub fn dsmr_devices(&self) -> impl Iterator<Item = &impl FormattableDevice> {
self.dsmr_devices.iter() self.dsmr_devices.values()
} }
pub fn update(&mut self, device: Device, json: JsonValue) { pub fn update(&mut self, device: Device, json: JsonValue) {
@ -147,12 +151,12 @@ impl DeviceStates {
} }
} }
pub fn mi_temp(&self) -> impl Iterator<Item = (&BDAddr, &MiTempDevice)> { pub fn mi_temp(&self) -> impl Iterator<Item = &impl FormattableDevice> {
self.mi_temp_devices.iter() self.mi_temp_devices.values()
} }
pub fn rf_temp(&self) -> impl Iterator<Item = (&RfDeviceId, &TempState)> { pub fn rf_temp(&self) -> impl Iterator<Item = &impl FormattableDevice> {
self.rf_temp_devices.iter() self.rf_temp_devices.values()
} }
pub fn retain(&mut self, cleanup_time: Instant, ping_time: Instant, client: &AsyncClient) { pub fn retain(&mut self, cleanup_time: Instant, ping_time: Instant, client: &AsyncClient) {

View file

@ -5,6 +5,8 @@ use std::str::FromStr;
use serde::{Deserialize, Deserializer, de::Error}; use serde::{Deserialize, Deserializer, de::Error};
use crate::device::FormattableDevice;
#[derive(Debug)] #[derive(Debug)]
pub struct TempState { pub struct TempState {
pub name: String, pub name: String,
@ -22,8 +24,10 @@ impl TempState {
humidity: 0, humidity: 0,
} }
} }
}
pub fn format_open_metrics(&self) -> impl Display + '_ { impl FormattableDevice for TempState {
fn format_open_metrics(&self) -> impl Display + '_ {
TempFormatter { device: self } TempFormatter { device: self }
} }
} }

View file

@ -5,6 +5,8 @@ use std::{
use jzon::JsonValue; use jzon::JsonValue;
use crate::device::FormattableDevice;
#[derive(Debug)] #[derive(Debug)]
pub struct DeviceState { pub struct DeviceState {
pub state: Option<bool>, pub state: Option<bool>,
@ -100,8 +102,10 @@ impl DeviceState {
pms.update(&json["PMS5003"]); pms.update(&json["PMS5003"]);
} }
} }
}
pub fn format_open_metrics(&self) -> impl Display + '_ { impl FormattableDevice for DeviceState {
fn format_open_metrics(&self) -> impl Display + '_ {
TasmotaFormatter { device: self } TasmotaFormatter { device: self }
} }
} }

View file

@ -4,7 +4,7 @@ mod mqtt;
mod topic; mod topic;
use crate::config::{Config, ListenConfig}; use crate::config::{Config, ListenConfig};
use crate::device::{Device, DeviceStates}; use crate::device::{Device, DeviceStates, FormattableDevice};
use crate::mqtt::mqtt_stream; use crate::mqtt::mqtt_stream;
use crate::topic::Topic; use crate::topic::Topic;
use clap::Parser; use clap::Parser;
@ -78,19 +78,19 @@ async fn serve(device_states: Arc<Mutex<DeviceStates>>, listen: ListenConfig) {
.map(move |state: Arc<Mutex<DeviceStates>>| { .map(move |state: Arc<Mutex<DeviceStates>>| {
let state = state.lock().unwrap(); let state = state.lock().unwrap();
let mut response = String::new(); let mut response = String::new();
for (_, state) in state.devices() { for state in state.devices() {
write!(&mut response, "{}", state.format_open_metrics()) write!(&mut response, "{}", state.format_open_metrics())
.expect("formatting failed"); .expect("formatting failed");
} }
for (_, state) in state.dsmr_devices() { for state in state.dsmr_devices() {
write!(&mut response, "{}", state.format_open_metrics()) write!(&mut response, "{}", state.format_open_metrics())
.expect("formatting failed"); .expect("formatting failed");
} }
for (_, state) in state.mi_temp() { for state in state.mi_temp() {
write!(&mut response, "{}", state.format_open_metrics()) write!(&mut response, "{}", state.format_open_metrics())
.expect("formatting failed"); .expect("formatting failed");
} }
for (_, state) in state.rf_temp() { for state in state.rf_temp() {
write!(&mut response, "{}", state.format_open_metrics()) write!(&mut response, "{}", state.format_open_metrics())
.expect("formatting failed"); .expect("formatting failed");
} }