From f9c5b70b86bc31dcd0d5ca1898fad102ae89a1d4 Mon Sep 17 00:00:00 2001 From: Avii Date: Sun, 9 Aug 2026 16:08:12 +0200 Subject: [PATCH] 1786284492 --- Cargo.lock | 1 + dashboard/Cargo.toml | 1 + dashboard/src/main.rs | 107 +++++++++++++++--------------------------- 3 files changed, 41 insertions(+), 68 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6200031..0c1575d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -848,6 +848,7 @@ dependencies = [ "chrono", "dotenvy", "hass-rs", + "paste", "serde_json", "slint", "slint-build", diff --git a/dashboard/Cargo.toml b/dashboard/Cargo.toml index 9cf2be3..85e7635 100644 --- a/dashboard/Cargo.toml +++ b/dashboard/Cargo.toml @@ -13,6 +13,7 @@ dotenvy = "0.15.7" url = "2.5.8" chrono = "0.4.45" thiserror = "2.0.20" +paste = "1.0.15" [features] dev = ["slint/backend-winit-x11"] diff --git a/dashboard/src/main.rs b/dashboard/src/main.rs index dd60bf2..ed508ae 100644 --- a/dashboard/src/main.rs +++ b/dashboard/src/main.rs @@ -1,5 +1,37 @@ mod ha_ext; +use paste::paste; + +macro_rules! apply_model { + ($app:expr, $entities:expr, $name:ident, $ty:ty, $filter:expr) => { + paste! { + if $app + .[]() + .as_any() + .downcast_ref::>() + .is_none() + { + $app.[](ModelRc::new(VecModel::<$ty>::default())); + } + + let data = $app + .[](); + + let model = data + .as_any() + .downcast_ref::>() + .unwrap(); + + for entity in $entities.iter().filter($filter) { + match model.iter().position(|item| item.id == entity.entity_id) { + Some(index) => model.set_row_data(index, entity.into()), + None => model.push(entity.into()), + } + } + } + }; +} + use std::collections::HashMap; use dotenvy::var; @@ -49,84 +81,23 @@ fn apply_weather(app: &AppWindow, entities: &Vec) { } fn apply_lights(app: &AppWindow, entities: &[HassEntity]) { - if app - .get_lights() - .as_any() - .downcast_ref::>() - .is_none() - { - app.set_lights(ModelRc::new(VecModel::default())); - } - - let lights = app.get_lights(); - let model = lights - .as_any() - .downcast_ref::>() - .unwrap(); - - for entity in entities.iter().filter(|entity| { + apply_model!(app, entities, lights, LightData, |entity| { entity.domain() == "light" && !entity.entity_id.ends_with("screen") && !entity.entity_id.chars().any(char::is_numeric) - }) { - match model.iter().position(|light| light.id == entity.entity_id) { - Some(index) => model.set_row_data(index, entity.into()), - None => model.push(entity.into()), - } - } + }); } fn apply_thermometers(app: &AppWindow, entities: &[HassEntity]) { - if app - .get_thermometers() - .as_any() - .downcast_ref::>() - .is_none() - { - app.set_thermometers(ModelRc::new(VecModel::default())); - } - - let data = app.get_thermometers(); - let model = data - .as_any() - .downcast_ref::>() - .unwrap(); - - for entity in entities.iter().filter(|entity| { + apply_model!(app, entities, thermometers, ThermometerData, |entity| { entity.domain() == "sensor" && entity.entity_id.ends_with("thermometer_temperature") - }) { - match model.iter().position(|item| item.id == entity.entity_id) { - Some(index) => model.set_row_data(index, entity.into()), - None => model.push(entity.into()), - } - } + }); } fn apply_thermostats(app: &AppWindow, entities: &[HassEntity]) { - if app - .get_thermostats() - .as_any() - .downcast_ref::>() - .is_none() - { - app.set_thermostats(ModelRc::new(VecModel::default())); - } - - let data = app.get_thermostats(); - let model = data - .as_any() - .downcast_ref::>() - .unwrap(); - - for entity in entities - .iter() - .filter(|entity| entity.domain() == "climate" && !entity.entity_id.contains("diyless")) - { - match model.iter().position(|item| item.id == entity.entity_id) { - Some(index) => model.set_row_data(index, entity.into()), - None => model.push(entity.into()), - } - } + apply_model!(app, entities, thermostats, ThermostatData, |entity| { + entity.domain() == "climate" && !entity.entity_id.contains("diyless") + }); } fn apply_state(app: &Weak, entities: Vec) {