131 lines
4.0 KiB
Python
131 lines
4.0 KiB
Python
"""
|
|
Weather service for Munich using Open-Meteo API (free, no API key needed)
|
|
"""
|
|
import requests
|
|
from datetime import datetime
|
|
|
|
|
|
def get_munich_weather():
|
|
"""
|
|
Get current weather for Munich, Germany
|
|
|
|
Returns:
|
|
{
|
|
'success': bool,
|
|
'temperature': float, # Celsius
|
|
'condition': str, # e.g., "Partly cloudy"
|
|
'icon': str, # Weather emoji
|
|
'high': float, # Today's high
|
|
'low': float, # Today's low
|
|
'error': str or None
|
|
}
|
|
"""
|
|
try:
|
|
# Munich coordinates
|
|
lat = 48.1351
|
|
lon = 11.5820
|
|
|
|
# Open-Meteo API (free, no key needed)
|
|
url = f"https://api.open-meteo.com/v1/forecast"
|
|
params = {
|
|
'latitude': lat,
|
|
'longitude': lon,
|
|
'current': 'temperature_2m,weather_code',
|
|
'daily': 'temperature_2m_max,temperature_2m_min',
|
|
'timezone': 'Europe/Berlin',
|
|
'forecast_days': 1
|
|
}
|
|
|
|
response = requests.get(url, params=params, timeout=10)
|
|
response.raise_for_status()
|
|
data = response.json()
|
|
|
|
# Extract data
|
|
current = data.get('current', {})
|
|
daily = data.get('daily', {})
|
|
|
|
temperature = current.get('temperature_2m')
|
|
weather_code = current.get('weather_code', 0)
|
|
high = daily.get('temperature_2m_max', [None])[0]
|
|
low = daily.get('temperature_2m_min', [None])[0]
|
|
|
|
# Map weather code to condition and emoji
|
|
condition, icon = _get_weather_description(weather_code)
|
|
|
|
return {
|
|
'success': True,
|
|
'temperature': round(temperature, 1) if temperature else None,
|
|
'condition': condition,
|
|
'icon': icon,
|
|
'high': round(high, 1) if high else None,
|
|
'low': round(low, 1) if low else None,
|
|
'error': None
|
|
}
|
|
|
|
except requests.exceptions.Timeout:
|
|
return {
|
|
'success': False,
|
|
'temperature': None,
|
|
'condition': 'Unknown',
|
|
'icon': '🌡️',
|
|
'high': None,
|
|
'low': None,
|
|
'error': 'Weather service timeout'
|
|
}
|
|
except Exception as e:
|
|
return {
|
|
'success': False,
|
|
'temperature': None,
|
|
'condition': 'Unknown',
|
|
'icon': '🌡️',
|
|
'high': None,
|
|
'low': None,
|
|
'error': str(e)
|
|
}
|
|
|
|
|
|
def _get_weather_description(code):
|
|
"""
|
|
Map WMO weather code to description and emoji
|
|
https://open-meteo.com/en/docs
|
|
"""
|
|
weather_map = {
|
|
0: ('Clear sky', '☀️'),
|
|
1: ('Mainly clear', '🌤️'),
|
|
2: ('Partly cloudy', '⛅'),
|
|
3: ('Overcast', '☁️'),
|
|
45: ('Foggy', '🌫️'),
|
|
48: ('Foggy', '🌫️'),
|
|
51: ('Light drizzle', '🌦️'),
|
|
53: ('Drizzle', '🌦️'),
|
|
55: ('Heavy drizzle', '🌧️'),
|
|
61: ('Light rain', '🌧️'),
|
|
63: ('Rain', '🌧️'),
|
|
65: ('Heavy rain', '⛈️'),
|
|
71: ('Light snow', '🌨️'),
|
|
73: ('Snow', '❄️'),
|
|
75: ('Heavy snow', '❄️'),
|
|
77: ('Snow grains', '🌨️'),
|
|
80: ('Light showers', '🌦️'),
|
|
81: ('Showers', '🌧️'),
|
|
82: ('Heavy showers', '⛈️'),
|
|
85: ('Light snow showers', '🌨️'),
|
|
86: ('Snow showers', '❄️'),
|
|
95: ('Thunderstorm', '⛈️'),
|
|
96: ('Thunderstorm with hail', '⛈️'),
|
|
99: ('Thunderstorm with hail', '⛈️'),
|
|
}
|
|
|
|
return weather_map.get(code, ('Unknown', '🌡️'))
|
|
|
|
|
|
if __name__ == '__main__':
|
|
# Test
|
|
weather = get_munich_weather()
|
|
print(f"Success: {weather['success']}")
|
|
print(f"Temperature: {weather['temperature']}°C")
|
|
print(f"Condition: {weather['icon']} {weather['condition']}")
|
|
print(f"High/Low: {weather['high']}°C / {weather['low']}°C")
|
|
if weather['error']:
|
|
print(f"Error: {weather['error']}")
|