diff --git a/dashboard/src/ha_ext.rs b/dashboard/src/ha_ext.rs index 65f15cc..ab5e44a 100644 --- a/dashboard/src/ha_ext.rs +++ b/dashboard/src/ha_ext.rs @@ -97,19 +97,141 @@ supported_features: int */ impl From<&HassEntity> for WeatherData { fn from(value: &HassEntity) -> Self { + let kind = match value.state.as_str() { + "sunny" => "sun", + "clear-night" => "moon", + // "partlycloudy" if is_night => "cloud-moon", + "partlycloudy" => "cloud-sun", + "rainy" => "cloud-rain", + "pouring" | "windy" | "windy-variant" => "cloud-rain-wind", + "lightning" | "lightning-rainy" => "cloud-lightning", + "snowy" | "snowy-rainy" | "hail" => "snowflake", + "fog" => "cloud-fog", + _ => "cloud", + } + .to_shared_string(); + + let attribution = value + .attributes + .get("attribution") + .and_then(|x| x.as_str()) + .unwrap_or_default() + .to_shared_string(); + + let cloud_coverage = value + .attributes + .get("cloud_coverage") + .and_then(|x| x.as_i64()) + .unwrap_or_default() as i32; + + let dew_point = value + .attributes + .get("dew_point") + .and_then(|x| x.as_f64()) + .unwrap_or_default() as f32; + + let friendly_name = value + .attributes + .get("friendly_name") + .and_then(|x| x.as_str()) + .unwrap_or_default() + .to_shared_string(); + + let humidity = value + .attributes + .get("humidity") + .and_then(|x| x.as_i64()) + .unwrap_or_default() as i32; + + let precipitation_unit = value + .attributes + .get("precipitation_unit") + .and_then(|x| x.as_str()) + .unwrap_or_default() + .to_shared_string(); + + let pressure = value + .attributes + .get("pressure") + .and_then(|x| x.as_f64()) + .unwrap_or_default() as f32; + + let pressure_unit = value + .attributes + .get("pressure_unit") + .and_then(|x| x.as_str()) + .unwrap_or_default() + .to_shared_string(); + + let supported_features = value + .attributes + .get("supported_features") + .and_then(|x| x.as_i64()) + .unwrap_or_default() as i32; + let temperature = value .attributes .get("temperature") .and_then(|x| x.as_f64()) .unwrap_or_default() as f32; - todo!(); + let temperature_unit = value + .attributes + .get("temperature_unit") + .and_then(|x| x.as_str()) + .unwrap_or_default() + .to_shared_string(); + + let uv_index = value + .attributes + .get("uv_index") + .and_then(|x| x.as_f64()) + .unwrap_or_default() as f32; + + let visibility_unit = value + .attributes + .get("visibility_unit") + .and_then(|x| x.as_str()) + .unwrap_or_default() + .to_shared_string(); + + let wind_bearing = value + .attributes + .get("wind_bearing") + .and_then(|x| x.as_f64()) + .unwrap_or_default() as f32; + + let wind_speed = value + .attributes + .get("wind_speed") + .and_then(|x| x.as_f64()) + .unwrap_or_default() as f32; + + let wind_speed_unit = value + .attributes + .get("wind_speed_unit") + .and_then(|x| x.as_str()) + .unwrap_or_default() + .to_shared_string(); Self { + kind, + attribution, + cloud_coverage, + dew_point, + friendly_name, + humidity, + precipitation_unit, + pressure, + pressure_unit, + supported_features, temperature, - outside_high: todo!(), - outside_condition: todo!(), - weather_kind: todo!(), + temperature_unit, + uv_index, + visibility_unit, + wind_bearing, + wind_speed, + wind_speed_unit, } } } diff --git a/dashboard/src/main.rs b/dashboard/src/main.rs index 49a72b8..0e7553d 100644 --- a/dashboard/src/main.rs +++ b/dashboard/src/main.rs @@ -42,6 +42,11 @@ fn apply_state(app: &Weak, state: State) { if let Some(weather) = state.get("weather.forecast_home").as_ref() { app.set_weather(weather.into()); } + app.set_is_night( + state + .get("sun.sun") + .is_some_and(|sun| sun.state == "below_horizon"), + ); }) .ok(); } diff --git a/dashboard/ui/climate.slint b/dashboard/ui/climate.slint index c0f2628..968e302 100644 --- a/dashboard/ui/climate.slint +++ b/dashboard/ui/climate.slint @@ -5,7 +5,9 @@ in property : "CONNECTING"; in property : "cloud"; */ +import { Palette } from "std-widgets.slint"; export struct WeatherData { + kind: string, temperature: float, dew_point: float, temperature_unit: string, @@ -26,11 +28,11 @@ export struct WeatherData { export component Climate inherits Rectangle { in property weather; + in property is-night; + Text { - width: 300px; - height: 116px; text: "\{weather.temperature}\{weather.temperature-unit}"; - font-size: 104px; + font-size: 72px; font-weight: 700; vertical-alignment: center; } @@ -44,64 +46,74 @@ export component Climate inherits Rectangle { // vertical-alignment: center; // } - // if weather.weather-kind == "sun": Image { - // width: 120px; - // height: 105px; - // source: @image-url("icons/sun.svg"); - // image-fit: contain; - // } - // if weather.weather-kind == "cloud-sun": Image { - // width: 120px; - // height: 105px; - // source: @image-url("icons/cloud-sun.svg"); - // image-fit: contain; - // } - // if weather.weather-kind == "cloud-moon": Image { - // width: 120px; - // height: 105px; - // source: @image-url("icons/cloud-moon.svg"); - // image-fit: contain; - // } - // if weather.weather-kind == "cloud": Image { - // width: 120px; - // height: 105px; - // source: @image-url("icons/cloud.svg"); - // image-fit: contain; - // } - // if weather.weather-kind == "cloud-rain": Image { - // width: 120px; - // height: 105px; - // source: @image-url("icons/cloud-rain.svg"); - // image-fit: contain; - // } - // if weather.weather-kind == "cloud-rain-wind": Image { - // width: 120px; - // height: 105px; - // source: @image-url("icons/cloud-rain-wind.svg"); - // image-fit: contain; - // } - // if weather.weather-kind == "cloud-lightning": Image { - // width: 120px; - // height: 105px; - // source: @image-url("icons/cloud-lightning.svg"); - // image-fit: contain; - // } - // if weather.weather-kind == "snowflake": Image { - // width: 120px; - // height: 105px; - // source: @image-url("icons/snowflake.svg"); - // image-fit: contain; - // } - // if weather.weather-kind == "cloud-fog": Image { - // width: 120px; - // height: 105px; - // source: @image-url("icons/cloud-fog.svg"); - // image-fit: contain; - // } - // if weather.weather-kind == "moon": Image { - // width: 120px; - // height: 105px; - // source: @image-url("icons/moon.svg"); - // image-fit: contain; - // } + if weather.kind == "sun": Image { + colorize: Palette.foreground; + width: 120px; + height: 105px; + source: @image-url("icons/sun.svg"); + image-fit: contain; + } + if weather.kind == "cloud-sun" && !is-night: Image { + colorize: Palette.foreground; + width: 120px; + height: 105px; + source: @image-url("icons/cloud-sun.svg"); + image-fit: contain; + } + if weather.kind == "cloud-sun" && is-night: Image { + colorize: Palette.foreground; + width: 120px; + height: 105px; + source: @image-url("icons/cloud-moon.svg"); + image-fit: contain; + } + if weather.kind == "cloud": Image { + colorize: Palette.foreground; + width: 120px; + height: 105px; + source: @image-url("icons/cloud.svg"); + image-fit: contain; + } + if weather.kind == "cloud-rain": Image { + colorize: Palette.foreground; + width: 120px; + height: 105px; + source: @image-url("icons/cloud-rain.svg"); + image-fit: contain; + } + if weather.kind == "cloud-rain-wind": Image { + colorize: Palette.foreground; + width: 120px; + height: 105px; + source: @image-url("icons/cloud-rain-wind.svg"); + image-fit: contain; + } + if weather.kind == "cloud-lightning": Image { + colorize: Palette.foreground; + width: 120px; + height: 105px; + source: @image-url("icons/cloud-lightning.svg"); + image-fit: contain; + } + if weather.kind == "snowflake": Image { + colorize: Palette.foreground; + width: 120px; + height: 105px; + source: @image-url("icons/snowflake.svg"); + image-fit: contain; + } + if weather.kind == "cloud-fog": Image { + colorize: Palette.foreground; + width: 120px; + height: 105px; + source: @image-url("icons/cloud-fog.svg"); + image-fit: contain; + } + if weather.kind == "moon": Image { + colorize: Palette.foreground; + width: 120px; + height: 105px; + source: @image-url("icons/moon.svg"); + image-fit: contain; + } } diff --git a/dashboard/ui/main.slint b/dashboard/ui/main.slint index 17aec7d..f3e9587 100644 --- a/dashboard/ui/main.slint +++ b/dashboard/ui/main.slint @@ -92,7 +92,10 @@ export component AppWindow inherits Window { property page: 0; in property date-time; + in property weather; + in property is-night; + in property <[ThermometerData]> thermometers; in property <[LightData]> lights; @@ -132,6 +135,7 @@ export component AppWindow inherits Window { preferred-width: root.width; VerticalLayout { if root.page == 0: Climate { + is-night: is-night; weather: weather; } if root.page == 1: Calendar { }