| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193 |
- # -*- coding: utf-8 -*-
- """
- Hilfsfunktionen fuer das Weather-Plugin.
- WMO-Code-Tabelle, Bright-Sky-Condition-Tabelle, TTS-Formatierung
- und Windrichtungs-Konvertierung.
- """
- from plugins.weather.models import ForecastDay, WeatherData
- # =========================================================================
- # WMO-Wettercode-Tabelle (Open-Meteo)
- # https://www.noaa.gov/weather/wmo-weather-codes
- # =========================================================================
- WMO_DESCRIPTIONS: dict[int, str] = {
- 0: "Klarer Himmel",
- 1: "Ueberwiegend klar",
- 2: "Teilweise bewoelkt",
- 3: "Bedeckt",
- 45: "Nebel",
- 48: "Gefrierender Nebel",
- 51: "Leichter Nieselregen",
- 53: "Maessiger Nieselregen",
- 55: "Starker Nieselregen",
- 56: "Leichter gefrierender Nieselregen",
- 57: "Starker gefrierender Nieselregen",
- 61: "Leichter Regen",
- 63: "Maessiger Regen",
- 65: "Starker Regen",
- 66: "Leichter gefrierender Regen",
- 67: "Starker gefrierender Regen",
- 71: "Leichter Schneefall",
- 73: "Maessiger Schneefall",
- 75: "Starker Schneefall",
- 77: "Schneegriesel",
- 80: "Leichte Regenschauer",
- 81: "Maessige Regenschauer",
- 82: "Starke Regenschauer",
- 85: "Leichte Schneeschauer",
- 86: "Starke Schneeschauer",
- 95: "Gewitter",
- 96: "Gewitter mit leichtem Hagel",
- 99: "Gewitter mit starkem Hagel",
- }
- # =========================================================================
- # Bright Sky (DWD) Condition-Tabelle
- # =========================================================================
- BRIGHTSKY_CONDITIONS: dict[str, str] = {
- "dry": "Trocken",
- "fog": "Nebel",
- "rain": "Regen",
- "sleet": "Schneeregen",
- "snow": "Schnee",
- "hail": "Hagel",
- "thunderstorm": "Gewitter",
- "wind": "Windig",
- }
- # =========================================================================
- # Windrichtung
- # =========================================================================
- _WIND_DIRECTIONS = [
- (0, 22.5, "Nord"),
- (22.5, 67.5, "Nordost"),
- (67.5, 112.5, "Ost"),
- (112.5, 157.5, "Suedost"),
- (157.5, 202.5, "Sued"),
- (202.5, 247.5, "Suedwest"),
- (247.5, 292.5, "West"),
- (292.5, 337.5, "Nordwest"),
- (337.5, 360.1, "Nord"),
- ]
- def format_wind_direction(degrees: int) -> str:
- """
- Konvertiert Windrichtung in Grad zu Himmelsrichtung.
- Args:
- degrees: Windrichtung in Grad (0-360)
- Returns:
- Himmelsrichtung als String (z.B. "Suedwest")
- """
- degrees = degrees % 360
- for low, high, name in _WIND_DIRECTIONS:
- if low <= degrees < high:
- return name
- return "Nord"
- # =========================================================================
- # Lookup-Funktionen
- # =========================================================================
- def get_wmo_description(code: int) -> str:
- """
- Gibt die deutsche Beschreibung fuer einen WMO-Wettercode zurueck.
- Args:
- code: WMO-Wettercode
- Returns:
- Deutsche Wetterbeschreibung
- """
- return WMO_DESCRIPTIONS.get(code, f"Unbekannt ({code})")
- def get_brightsky_description(condition: str) -> str:
- """
- Gibt die deutsche Beschreibung fuer eine Bright-Sky-Condition zurueck.
- Args:
- condition: Bright-Sky-Condition-String
- Returns:
- Deutsche Wetterbeschreibung
- """
- return BRIGHTSKY_CONDITIONS.get(condition, condition.capitalize())
- # =========================================================================
- # TTS-Formatierung
- # =========================================================================
- def format_weather_for_tts(data: WeatherData) -> str:
- """
- Formatiert aktuelle Wetterdaten fuer die Sprachausgabe.
- Beispiel: "In Sinsheim sind es 8 Grad, leichter Regen bei 12 km/h Wind
- aus Suedwest."
- Args:
- data: Aktuelle Wetterdaten
- Returns:
- TTS-formatierter String
- """
- temp = round(data.temperature)
- parts = [f"In {data.location} sind es {temp} Grad"]
- if data.feels_like is not None:
- diff = abs(round(data.feels_like) - temp)
- if diff >= 3:
- parts.append(f"gefuehlt {round(data.feels_like)} Grad")
- parts.append(data.description)
- if data.wind_speed >= 5:
- wind_dir = format_wind_direction(data.wind_direction)
- parts.append(f"bei {round(data.wind_speed)} km/h Wind aus {wind_dir}")
- if data.precipitation > 0:
- parts.append(
- f"mit {data.precipitation:.1f} Millimeter Niederschlag"
- )
- return ", ".join(parts) + "."
- def format_forecast_for_tts(day: ForecastDay, date_label: str) -> str:
- """
- Formatiert eine Tagesvorhersage fuer die Sprachausgabe.
- Beispiel: "Morgen in Sinsheim: 5 bis 12 Grad, bewoelkt."
- Args:
- day: Vorhersagedaten fuer einen Tag
- date_label: Datum-Label (z.B. "Morgen", "Am Freitag")
- Returns:
- TTS-formatierter String
- """
- temp_min = round(day.temp_min)
- temp_max = round(day.temp_max)
- parts = [f"{date_label}: {temp_min} bis {temp_max} Grad, {day.description}"]
- if day.precipitation > 0:
- parts.append(
- f"{day.precipitation:.1f} Millimeter Niederschlag"
- )
- if day.wind_speed_max >= 30:
- parts.append(f"Windboeen bis {round(day.wind_speed_max)} km/h")
- return ", ".join(parts) + "."
|