""" 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']}")