diff --git a/frontend/src/components/WeatherCard.vue b/frontend/src/components/WeatherCard.vue index 4434652..7e52c06 100644 --- a/frontend/src/components/WeatherCard.vue +++ b/frontend/src/components/WeatherCard.vue @@ -6,7 +6,7 @@ interface ForecastDay { condition: string high: number low: number - precip_mm: number + precip_probability: number | null windspeed_max: number } @@ -19,6 +19,7 @@ interface WeatherData { today_low: number | null yesterday_high: number | null yesterday_low: number | null + wind_unit?: string forecast: ForecastDay[] } @@ -87,10 +88,11 @@ const fetchedAtLabel = computed(() => {
{{ day.day }} {{ weatherIcon(day.condition) }} + {{ day.condition }} {{ day.high }}° / {{ day.low }}° - 💧 {{ day.precip_mm }}mm - - 💨 {{ day.windspeed_max }}km/h + 💧 {{ day.precip_probability }}% + 💧 — + 💨 {{ day.windspeed_max }} {{ weather.wind_unit ?? 'km/h' }}
@@ -186,6 +188,14 @@ const fetchedAtLabel = computed(() => { line-height: 1; } +.forecast-condition { + font-size: 0.7rem; + color: var(--color-text-muted); + text-align: center; + line-height: 1.2; + word-break: break-word; +} + .forecast-temps { white-space: nowrap; } diff --git a/frontend/src/views/BriefingView.vue b/frontend/src/views/BriefingView.vue index 4d558fe..34dbb35 100644 --- a/frontend/src/views/BriefingView.vue +++ b/frontend/src/views/BriefingView.vue @@ -35,7 +35,8 @@ interface WeatherData { today_low: number | null yesterday_high: number | null yesterday_low: number | null - forecast: { day: string; condition: string; high: number; low: number; precip_mm: number; windspeed_max: number }[] + wind_unit?: string + forecast: { day: string; condition: string; high: number; low: number; precip_probability: number | null; windspeed_max: number }[] } const chatStore = useChatStore() diff --git a/src/fabledassistant/services/weather.py b/src/fabledassistant/services/weather.py index 9b08d49..0525693 100644 --- a/src/fabledassistant/services/weather.py +++ b/src/fabledassistant/services/weather.py @@ -15,7 +15,7 @@ NOMINATIM_URL = "https://nominatim.openstreetmap.org/search" OPEN_METEO_URL = "https://api.open-meteo.com/v1/forecast" OPEN_METEO_DAILY = ( "temperature_2m_max,temperature_2m_min,precipitation_sum," - "weathercode,windspeed_10m_max" + "precipitation_probability_max,weathercode,windspeed_10m_max" ) # WMO weather code → description (subset; covers the most common codes) @@ -42,12 +42,14 @@ def parse_forecast(raw: dict) -> list[dict]: """Convert Open-Meteo daily response into a clean list of day dicts.""" daily = raw.get("daily", {}) dates = daily.get("time", []) + precip_prob = daily.get("precipitation_probability_max", []) return [ { "date": dates[i], "temp_max": daily.get("temperature_2m_max", [])[i], "temp_min": daily.get("temperature_2m_min", [])[i], "precip_mm": daily.get("precipitation_sum", [])[i], + "precip_probability": precip_prob[i] if i < len(precip_prob) else None, "weathercode": daily.get("weathercode", [])[i], "description": describe_weathercode(daily.get("weathercode", [])[i]), "windspeed_max": daily.get("windspeed_10m_max", [])[i], @@ -119,10 +121,13 @@ def parse_weather_card_data( yesterday_day = next((d for d in days if d["date"] == yesterday_str), None) future_days = [d for d in days if d["date"] > today_str][:5] + imperial = temp_unit == "F" + def to_temp(c: float) -> int: - if temp_unit == "F": - return round(c * 9 / 5 + 32) - return round(c) + return round(c * 9 / 5 + 32) if imperial else round(c) + + def to_wind(kmh: float) -> int: + return round(kmh * 0.621371) if imperial else round(kmh) def day_label(date_str: str) -> str: from datetime import date as _date @@ -131,6 +136,8 @@ def parse_weather_card_data( except ValueError: return date_str + wind_unit = "mph" if imperial else "km/h" + return { "location": getattr(cache_row, "location_label", ""), "fetched_at": cache_row.fetched_at.isoformat(), @@ -140,14 +147,15 @@ def parse_weather_card_data( "today_low": to_temp(today_day["temp_min"]) if today_day else None, "yesterday_high": to_temp(yesterday_day["temp_max"]) if yesterday_day else None, "yesterday_low": to_temp(yesterday_day["temp_min"]) if yesterday_day else None, + "wind_unit": wind_unit, "forecast": [ { "day": day_label(d["date"]), "condition": d["description"], "high": to_temp(d["temp_max"]), "low": to_temp(d["temp_min"]), - "precip_mm": round(d["precip_mm"], 1), - "windspeed_max": round(d["windspeed_max"]), + "precip_probability": d["precip_probability"], + "windspeed_max": to_wind(d["windspeed_max"]), } for d in future_days ],