1786284492

This commit is contained in:
2026-08-09 16:08:12 +02:00
parent b5b3025e88
commit f9c5b70b86
3 changed files with 41 additions and 68 deletions

1
Cargo.lock generated
View File

@@ -848,6 +848,7 @@ dependencies = [
"chrono", "chrono",
"dotenvy", "dotenvy",
"hass-rs", "hass-rs",
"paste",
"serde_json", "serde_json",
"slint", "slint",
"slint-build", "slint-build",

View File

@@ -13,6 +13,7 @@ dotenvy = "0.15.7"
url = "2.5.8" url = "2.5.8"
chrono = "0.4.45" chrono = "0.4.45"
thiserror = "2.0.20" thiserror = "2.0.20"
paste = "1.0.15"
[features] [features]
dev = ["slint/backend-winit-x11"] dev = ["slint/backend-winit-x11"]

View File

@@ -1,5 +1,37 @@
mod ha_ext; mod ha_ext;
use paste::paste;
macro_rules! apply_model {
($app:expr, $entities:expr, $name:ident, $ty:ty, $filter:expr) => {
paste! {
if $app
.[<get_ $name>]()
.as_any()
.downcast_ref::<VecModel<$ty>>()
.is_none()
{
$app.[<set_ $name>](ModelRc::new(VecModel::<$ty>::default()));
}
let data = $app
.[<get_ $name>]();
let model = data
.as_any()
.downcast_ref::<VecModel<$ty>>()
.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 std::collections::HashMap;
use dotenvy::var; use dotenvy::var;
@@ -49,84 +81,23 @@ fn apply_weather(app: &AppWindow, entities: &Vec<HassEntity>) {
} }
fn apply_lights(app: &AppWindow, entities: &[HassEntity]) { fn apply_lights(app: &AppWindow, entities: &[HassEntity]) {
if app apply_model!(app, entities, lights, LightData, |entity| {
.get_lights()
.as_any()
.downcast_ref::<VecModel<LightData>>()
.is_none()
{
app.set_lights(ModelRc::new(VecModel::default()));
}
let lights = app.get_lights();
let model = lights
.as_any()
.downcast_ref::<VecModel<LightData>>()
.unwrap();
for entity in entities.iter().filter(|entity| {
entity.domain() == "light" entity.domain() == "light"
&& !entity.entity_id.ends_with("screen") && !entity.entity_id.ends_with("screen")
&& !entity.entity_id.chars().any(char::is_numeric) && !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]) { fn apply_thermometers(app: &AppWindow, entities: &[HassEntity]) {
if app apply_model!(app, entities, thermometers, ThermometerData, |entity| {
.get_thermometers()
.as_any()
.downcast_ref::<VecModel<ThermometerData>>()
.is_none()
{
app.set_thermometers(ModelRc::new(VecModel::default()));
}
let data = app.get_thermometers();
let model = data
.as_any()
.downcast_ref::<VecModel<ThermometerData>>()
.unwrap();
for entity in entities.iter().filter(|entity| {
entity.domain() == "sensor" && entity.entity_id.ends_with("thermometer_temperature") 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]) { fn apply_thermostats(app: &AppWindow, entities: &[HassEntity]) {
if app apply_model!(app, entities, thermostats, ThermostatData, |entity| {
.get_thermostats() entity.domain() == "climate" && !entity.entity_id.contains("diyless")
.as_any() });
.downcast_ref::<VecModel<ThermostatData>>()
.is_none()
{
app.set_thermostats(ModelRc::new(VecModel::default()));
}
let data = app.get_thermostats();
let model = data
.as_any()
.downcast_ref::<VecModel<ThermostatData>>()
.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()),
}
}
} }
fn apply_state(app: &Weak<AppWindow>, entities: Vec<HassEntity>) { fn apply_state(app: &Weak<AppWindow>, entities: Vec<HassEntity>) {