store rf/mitemp names with device state

This commit is contained in:
Robin Appelman 2026-06-27 00:13:40 +02:00
commit 7335d35c68
3 changed files with 72 additions and 30 deletions

View file

@ -8,7 +8,9 @@ use std::{
};
#[derive(Debug)]
pub struct MiTempState {
pub struct MiTempDevice {
pub name: String,
pub addr: BDAddr,
temperature: f32,
humidity: f32,
dew_point: f32,
@ -16,9 +18,11 @@ pub struct MiTempState {
pub last_seen: Instant,
}
impl Default for MiTempState {
fn default() -> Self {
MiTempState {
impl MiTempDevice {
pub fn new(addr: BDAddr, name: String) -> Self {
MiTempDevice {
name,
addr,
temperature: 0.0,
humidity: 0.0,
dew_point: 0.0,
@ -26,9 +30,7 @@ impl Default for MiTempState {
last_seen: Instant::now(),
}
}
}
impl MiTempState {
pub fn update(&mut self, json: &JsonValue) {
self.last_seen = Instant::now();
if let Some(temperature) = json["Temperature"].as_number().map(f32::from) {
@ -53,7 +55,7 @@ pub fn format_mi_temp_state<W: Write>(
mut writer: W,
addr: BDAddr,
names: &BTreeMap<BDAddr, String>,
state: &MiTempState,
state: &MiTempDevice,
) -> fmt::Result {
// sensor_battery{name="Living Room", mac="58:2D:34:39:1D:5B"} 100
// sensor_temperature{name="Living Room", mac="58:2D:34:39:1D:5B"} 16.2

View file

@ -1,6 +1,6 @@
mod mitemp;
pub use crate::device::mitemp::{MiTempState, format_mi_temp_state};
pub use crate::device::mitemp::{MiTempDevice, format_mi_temp_state};
use color_eyre::{Report, Result, eyre::WrapErr};
use jzon::JsonValue;
use rumqttc::{AsyncClient, QoS};
@ -17,14 +17,28 @@ use tokio::task::spawn;
#[derive(Default)]
pub struct DeviceStates {
pub mi_temp_names: BTreeMap<BDAddr, String>,
pub rf_temp_names: HashMap<RfDeviceId, String>,
pub devices: HashMap<Device, DeviceState>,
pub dsmr_devices: HashMap<Device, DsmrState>,
pub mi_temp_devices: BTreeMap<BDAddr, MiTempState>,
pub mi_temp_devices: BTreeMap<BDAddr, MiTempDevice>,
pub rf_temp_devices: HashMap<RfDeviceId, TempState>,
active_rf_temp_id: RfDeviceId,
}
impl DeviceStates {
pub fn new(
mi_temp_names: BTreeMap<BDAddr, String>,
rf_temp_names: HashMap<RfDeviceId, String>,
) -> Self {
DeviceStates {
mi_temp_names,
rf_temp_names,
..Self::default()
}
}
pub fn devices(&self) -> impl Iterator<Item = (&Device, &DeviceState)> {
self.devices.iter()
}
@ -41,8 +55,13 @@ impl DeviceStates {
let addr = addr.trim_start_matches('-');
match BDAddr::from_mi_temp_mac_part(addr) {
Ok(addr) => {
let state = self.mi_temp_devices.entry(addr).or_default();
state.update(value);
if let Some(name) = self.mi_temp_names.get(&addr) {
let state = self
.mi_temp_devices
.entry(addr)
.or_insert_with(|| MiTempDevice::new(addr, name.clone()));
state.update(value);
}
}
Err(e) => eprintln!("Failed to parse mitemp mac: {:#}", e),
}
@ -68,9 +87,15 @@ impl DeviceStates {
pub fn update_rf(&mut self, payload: &str) {
if let Some(data) = parse_rf_payload(payload) {
let state = self.rf_temp_devices.entry(data.device_id()).or_default();
state.humidity = data.humidity;
state.temperature = data.temperature;
let id = data.device_id();
if let Some(name) = self.rf_temp_names.get(&id) {
let state = self
.rf_temp_devices
.entry(data.device_id())
.or_insert_with(|| TempState::new(name.clone()));
state.humidity = data.humidity;
state.temperature = data.temperature;
}
} else {
eprintln!("invalid rf payload: {payload}")
}
@ -92,24 +117,26 @@ impl DeviceStates {
}
fn update_active_rtl(&mut self, field: &str, payload: &str) {
let state = self
.rf_temp_devices
.entry(self.active_rf_temp_id.clone())
.or_default();
match field {
"temperature_C" => state.temperature = payload.parse().unwrap_or_default(),
"temperature_F" => {
state.temperature = payload
.parse()
.map(|temp_f: f32| (temp_f - 32.0) * 5.0 / 9.0)
.unwrap_or_default()
if let Some(name) = self.rf_temp_names.get(&self.active_rf_temp_id) {
let state = self
.rf_temp_devices
.entry(self.active_rf_temp_id.clone())
.or_insert_with(|| TempState::new(name.clone()));
match field {
"temperature_C" => state.temperature = payload.parse().unwrap_or_default(),
"temperature_F" => {
state.temperature = payload
.parse()
.map(|temp_f: f32| (temp_f - 32.0) * 5.0 / 9.0)
.unwrap_or_default()
}
"humidity" => state.humidity = payload.parse().unwrap_or_default(),
_ => {}
}
"humidity" => state.humidity = payload.parse().unwrap_or_default(),
_ => {}
}
}
pub fn mi_temp(&self) -> impl Iterator<Item = (&BDAddr, &MiTempState)> {
pub fn mi_temp(&self) -> impl Iterator<Item = (&BDAddr, &MiTempDevice)> {
self.mi_temp_devices.iter()
}
@ -393,12 +420,23 @@ pub fn format_device_state<W: Write>(
Ok(())
}
#[derive(Debug, Default)]
#[derive(Debug)]
pub struct TempState {
name: String,
temperature: f32,
humidity: u8,
}
impl TempState {
pub fn new(name: String) -> Self {
TempState {
name,
temperature: 0.0,
humidity: 0,
}
}
}
pub fn format_rf_temp_state<W: Write>(
mut writer: W,
channel: &RfDeviceId,