diff --git a/aurora-livecam/WeatherManager.php b/aurora-livecam/WeatherManager.php index 4bc6dd0..bd96cec 100644 --- a/aurora-livecam/WeatherManager.php +++ b/aurora-livecam/WeatherManager.php @@ -1,6 +1,7 @@ settingsManager->getWeatherApiKey(); - if (empty($apiKey)) { - return ['error' => 'API Key fehlt']; - } - // Prüfe Cache $cached = $this->getCache(); if ($cached !== null) { return $cached; } - // Hole frische Daten von API + // Hole frische Daten von API (Open-Meteo) $coords = $this->settingsManager->getWeatherCoords(); - $units = $this->settingsManager->getWeatherUnits(); - $url = "https://api.openweathermap.org/data/2.5/weather?lat={$coords['lat']}&lon={$coords['lon']}&units={$units}&appid={$apiKey}&lang=de"; + // Open-Meteo API URL - komplett kostenlos, kein API Key! + $url = "https://api.open-meteo.com/v1/forecast?" . http_build_query([ + 'latitude' => $coords['lat'], + 'longitude' => $coords['lon'], + 'current' => 'temperature_2m,relative_humidity_2m,precipitation,weather_code,wind_speed_10m,wind_direction_10m,pressure_msl,cloud_cover', + 'timezone' => 'Europe/Zurich' + ]); $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); @@ -53,25 +53,27 @@ class WeatherManager { } $data = json_decode($response, true); - if (!$data || !isset($data['main'])) { + if (!$data || !isset($data['current'])) { return ['error' => 'Ungültige API Antwort']; } + $current = $data['current']; + // Formatiere Daten $weather = [ - 'temp' => round($data['main']['temp'], 1), - 'feels_like' => round($data['main']['feels_like'], 1), - 'humidity' => $data['main']['humidity'], - 'pressure' => $data['main']['pressure'], - 'wind_speed' => round($data['wind']['speed'] * 3.6, 1), // m/s -> km/h - 'wind_deg' => $data['wind']['deg'] ?? 0, - 'wind_direction' => $this->getWindDirection($data['wind']['deg'] ?? 0), - 'clouds' => $data['clouds']['all'] ?? 0, - 'description' => ucfirst($data['weather'][0]['description'] ?? 'Unbekannt'), - 'icon' => $data['weather'][0]['icon'] ?? '01d', - 'rain_1h' => $data['rain']['1h'] ?? 0, - 'snow_1h' => $data['snow']['1h'] ?? 0, - 'location' => $data['name'] ?? $this->settingsManager->getWeatherLocation(), + 'temp' => round($current['temperature_2m'], 1), + 'feels_like' => round($current['temperature_2m'], 1), // Open-Meteo hat keine "feels like" + 'humidity' => $current['relative_humidity_2m'], + 'pressure' => round($current['pressure_msl'], 0), + 'wind_speed' => round($current['wind_speed_10m'], 1), // Schon in km/h! + 'wind_deg' => $current['wind_direction_10m'], + 'wind_direction' => $this->getWindDirection($current['wind_direction_10m']), + 'clouds' => $current['cloud_cover'] ?? 0, + 'description' => $this->getWeatherDescription($current['weather_code']), + 'icon' => $this->getWeatherIcon($current['weather_code']), + 'rain_1h' => $current['precipitation'] ?? 0, + 'snow_1h' => 0, // Open-Meteo gibt Niederschlag gesamt + 'location' => $this->settingsManager->getWeatherLocation(), 'timestamp' => time() ]; @@ -81,6 +83,59 @@ class WeatherManager { return $weather; } + /** + * Wandelt WMO Weather Code in Beschreibung um + * https://open-meteo.com/en/docs + */ + private function getWeatherDescription($code) { + $descriptions = [ + 0 => 'Klar', + 1 => 'Überwiegend klar', + 2 => 'Teilweise bewölkt', + 3 => 'Bewölkt', + 45 => 'Neblig', + 48 => 'Nebel mit Reifablagerung', + 51 => 'Leichter Nieselregen', + 53 => 'Mäßiger Nieselregen', + 55 => 'Dichter Nieselregen', + 61 => 'Leichter Regen', + 63 => 'Mäßiger Regen', + 65 => 'Starker Regen', + 71 => 'Leichter Schneefall', + 73 => 'Mäßiger Schneefall', + 75 => 'Starker Schneefall', + 77 => 'Schneegraupeln', + 80 => 'Leichte Regenschauer', + 81 => 'Mäßige Regenschauer', + 82 => 'Starke Regenschauer', + 85 => 'Leichte Schneeschauer', + 86 => 'Starke Schneeschauer', + 95 => 'Gewitter', + 96 => 'Gewitter mit leichtem Hagel', + 99 => 'Gewitter mit starkem Hagel' + ]; + + return $descriptions[$code] ?? 'Unbekannt'; + } + + /** + * Wandelt WMO Weather Code in Icon-Code um (OpenWeatherMap kompatibel) + */ + private function getWeatherIcon($code) { + if ($code == 0) return '01d'; // Klar + if ($code >= 1 && $code <= 2) return '02d'; // Teilweise bewölkt + if ($code == 3) return '04d'; // Bewölkt + if ($code >= 45 && $code <= 48) return '50d'; // Nebel + if ($code >= 51 && $code <= 55) return '09d'; // Nieselregen + if ($code >= 61 && $code <= 65) return '10d'; // Regen + if ($code >= 71 && $code <= 77) return '13d'; // Schnee + if ($code >= 80 && $code <= 82) return '09d'; // Regenschauer + if ($code >= 85 && $code <= 86) return '13d'; // Schneeschauer + if ($code >= 95 && $code <= 99) return '11d'; // Gewitter + + return '01d'; // Default + } + /** * Wandelt Windrichtung (Grad) in Kompassrichtung um */ diff --git a/aurora-livecam/index.php b/aurora-livecam/index.php index c8f200d..db0e914 100644 --- a/aurora-livecam/index.php +++ b/aurora-livecam/index.php @@ -1271,7 +1271,7 @@ class AdminManager { // Weather Settings $output .= '
'; - $output .= '

🌤️ Wetter-Widget

'; + $output .= '

🌤️ Wetter-Widget (Open-Meteo - 100% kostenlos!)

'; $output .= '
'; $output .= 'Wetter-Widget anzeigen'; @@ -1283,13 +1283,6 @@ class AdminManager { $output .= '
'; $output .= '
'; - $output .= '
'; - $output .= 'OpenWeatherMap API Key (kostenlos registrieren)'; - $output .= '
'; - $output .= ''; - $output .= '
'; - $output .= '
'; - $output .= '
'; $output .= 'Standort (Stadt,Land)'; $output .= '
'; @@ -3581,10 +3574,6 @@ const AdminSettings = { this.updateSetting('weather.enabled', e.target.checked); }); - document.getElementById('setting-weather-api-key')?.addEventListener('change', (e) => { - this.updateSetting('weather.api_key', e.target.value); - }); - document.getElementById('setting-weather-location')?.addEventListener('change', (e) => { this.updateSetting('weather.location', e.target.value); });