diff --git a/dashboard/src/ha_ext.rs b/dashboard/src/ha_ext.rs index afd32fe..d452f7d 100644 --- a/dashboard/src/ha_ext.rs +++ b/dashboard/src/ha_ext.rs @@ -83,6 +83,8 @@ impl From<&HassEntity> for DateTimeData { impl From<&HassEntity> for ThermostatData { fn from(value: &HassEntity) -> Self { + let id = value.entity_id.to_shared_string(); + let available = value.available(); let current = value @@ -95,13 +97,15 @@ impl From<&HassEntity> for ThermostatData { .attributes .get("temperature") .and_then(|x| x.as_f64()) - .unwrap_or_default(); + .unwrap_or_default() as f32; let (target, remainder) = split_number(temperature, 1); Self { + id, available, current, + temperature, name: value.friendly_name().to_shared_string(), state: value.state.to_uppercase().to_shared_string(), unit: "°C".into(), @@ -272,10 +276,10 @@ pub fn pretty_label(value: &str) -> String { .join(" ") } -fn split_number(x: f64, decimals: u32) -> (i32, i32) { +fn split_number(x: f32, decimals: u32) -> (i32, i32) { let factor = 10_i32.pow(decimals); let main = x.trunc() as i32; - let remainder = ((x.fract() * factor as f64).round()) as i32; + let remainder = ((x.fract() * factor as f32).round()) as i32; (main, remainder) } diff --git a/dashboard/src/main.rs b/dashboard/src/main.rs index 6731d57..6cf46ae 100644 --- a/dashboard/src/main.rs +++ b/dashboard/src/main.rs @@ -92,6 +92,7 @@ async fn main() -> Result<(), Box> { app.on_toggle_light({ let state = state.clone(); + let c2s_tx = c2s_tx.clone(); move |entity_id| { let id = entity_id.to_string(); @@ -116,6 +117,51 @@ async fn main() -> Result<(), Box> { } }); + app.on_set_temperature({ + let c2s_tx = c2s_tx.clone(); + move |entity_id, value| { + let payload = Some(json!({ + "entity_id": entity_id.to_string(), + "temperature": value + })); + + c2s_tx + .send(C2sMessage::CallService( + "climate".into(), + "set_temperature".into(), + payload.clone(), + )) + .ok(); + } + }); + + app.on_toggle_thermostat({ + let state = state.clone(); + let c2s_tx = c2s_tx.clone(); + move |entity_id| { + let id = entity_id.to_string(); + + let payload = Some(json!({ + "entity_id": id + })); + + if let Some(entity) = state.get(&id) { + let action = if entity.state == "heat" { + "turn_off" + } else { + "turn_on" + }; + c2s_tx + .send(C2sMessage::CallService( + "climate".into(), + action.into(), + payload.clone(), + )) + .ok(); + } + } + }); + app.run()?; Ok(()) diff --git a/dashboard/ui/climate.slint b/dashboard/ui/climate.slint index f122386..4565214 100644 --- a/dashboard/ui/climate.slint +++ b/dashboard/ui/climate.slint @@ -5,6 +5,7 @@ import { ElevatedButton, SegmentedButton, MaterialPalette, + FilledButton, } from "material/material.slint"; import { Icons } from "material/ui/icons/icons.slint"; export struct WeatherData { @@ -29,8 +30,10 @@ export struct WeatherData { } export struct ThermostatData { + id: string, name: string, current: float, + temperature: float, unit: string, target: int, remainder: int, @@ -45,6 +48,9 @@ export component Climate inherits Rectangle { property icon-index: weather.icon-index == 1 && is-night ? 2 : weather.icon-index; + callback set_temperature(string, float); + callback toggle_thermostat(string); + property <[image]> icons: [ @image-url("icons/sun.svg"), @image-url("icons/cloud-sun.svg"), @@ -96,6 +102,7 @@ export component Climate inherits Rectangle { ElevatedButton { icon: Icons.remove; + clicked => { root.set_temperature(thermostat.id, thermostat.temperature - 0.5) } } Rectangle { @@ -149,6 +156,17 @@ export component Climate inherits Rectangle { ElevatedButton { icon: Icons.add; + clicked => { root.set_temperature(thermostat.id, thermostat.temperature + 0.5) } + } + + if thermostat.state == "OFF": ElevatedButton { + icon: Icons.mode_heat_off; + clicked => { root.toggle_thermostat(thermostat.id) } + } + + if thermostat.state == "HEAT": FilledButton { + icon: Icons.mode_heat; + clicked => { root.toggle_thermostat(thermostat.id) } } } diff --git a/dashboard/ui/main.slint b/dashboard/ui/main.slint index d61b348..5c521fe 100644 --- a/dashboard/ui/main.slint +++ b/dashboard/ui/main.slint @@ -127,6 +127,8 @@ export component AppWindow inherits Window { in property <[ThermostatData]> thermostats; in property weather; in property is-night; + callback set_temperature(string, float); + callback toggle_thermostat(string); in property <[ThermometerData]> thermometers; @@ -170,6 +172,8 @@ export component AppWindow inherits Window { thermostats: thermostats; is-night: is-night; weather: weather; + set_temperature(entity_id, value) => { root.set_temperature(entity_id, value); } + toggle_thermostat(entity_id) => { toggle_thermostat(entity_id) } } if tab-bar.current-index == 1: Calendar { } if tab-bar.current-index == 2: Energy { }