From d6fd53e461a632dbdd3a2cc66548229cb8134d23 Mon Sep 17 00:00:00 2001 From: Urtzi Alfaro Date: Mon, 18 Aug 2025 21:14:42 +0200 Subject: [PATCH] Improve the dahboard 6 --- .../src/components/simple/WeatherContext.tsx | 58 ++++++++++++++++++- services/external/app/api/weather.py | 13 +++-- .../external/app/services/weather_service.py | 28 +++++++-- 3 files changed, 87 insertions(+), 12 deletions(-) diff --git a/frontend/src/components/simple/WeatherContext.tsx b/frontend/src/components/simple/WeatherContext.tsx index ec3cb748..b4fa7906 100644 --- a/frontend/src/components/simple/WeatherContext.tsx +++ b/frontend/src/components/simple/WeatherContext.tsx @@ -200,6 +200,36 @@ const WeatherContext: React.FC = ({ className = '' }) => { ); } + // Warning for unavailable/error weather data + if (weatherData && (weatherData.source === 'unavailable' || weatherData.source === 'error')) { + return ( + +
+ +

+ {weatherData.source === 'unavailable' ? '⚠️ Servicio Meteorológico No Disponible' : '❌ Error en Datos Meteorológicos'} +

+

+ {weatherData.source === 'unavailable' + ? 'AEMET está experimentando problemas temporales. Los datos meteorológicos no están disponibles en este momento.' + : 'Se ha producido un error al obtener los datos meteorológicos. Por favor, inténtalo de nuevo más tarde.' + } +

+
+ Estado: {weatherData.description} +
+ +
+
+ ); + } + // Warning for synthetic data if (weatherData && weatherData.source === 'synthetic') { return ( @@ -451,7 +481,7 @@ const WeatherContext: React.FC = ({ className = '' }) => { )} {/* Hourly Forecast Preview */} - {hourlyForecast.length > 0 && ( + {hourlyForecast.length > 0 ? (

Pronóstico por Horas (Próximas 8 horas)

@@ -475,10 +505,22 @@ const WeatherContext: React.FC = ({ className = '' }) => { ))}
+ ) : ( +
+

Pronóstico por Horas

+
+
+ ⚠️ Pronóstico por horas no disponible temporalmente +
+
+ Problemas de conectividad con AEMET +
+
+
)} {/* Weather Forecast */} - {weatherForecast.length > 0 && ( + {weatherForecast.length > 0 ? (

Pronóstico (Próximos Días)

@@ -505,6 +547,18 @@ const WeatherContext: React.FC = ({ className = '' }) => { ))}
+ ) : ( +
+

Pronóstico (Próximos Días)

+
+
+ ⚠️ Pronóstico diario no disponible temporalmente +
+
+ Problemas de conectividad con AEMET +
+
+
)} {/* Data Source Info & Controls */} diff --git a/services/external/app/api/weather.py b/services/external/app/api/weather.py index 65eaa920..8cd30a98 100644 --- a/services/external/app/api/weather.py +++ b/services/external/app/api/weather.py @@ -51,7 +51,7 @@ async def get_current_weather( weather = await weather_service.get_current_weather(latitude, longitude) if not weather: - raise HTTPException(status_code=404, detail="Weather data not available") + raise HTTPException(status_code=503, detail="Weather service temporarily unavailable") # Publish event try: @@ -133,8 +133,10 @@ async def get_weather_forecast( forecast = await weather_service.get_weather_forecast(request.latitude, request.longitude, request.days) + # Don't return 404 for empty forecast - return empty list with 200 status if not forecast: - raise HTTPException(status_code=404, detail="Weather forecast not available") + logger.info("Weather forecast unavailable - returning empty list") + return [] # Publish event try: @@ -180,11 +182,10 @@ async def get_hourly_weather_forecast( request.latitude, request.longitude, request.hours ) + # Don't return 404 for empty hourly forecast - return empty list with 200 status if not hourly_forecast: - raise HTTPException( - status_code=404, - detail="Hourly weather forecast not available. Please check AEMET API configuration." - ) + logger.info("Hourly weather forecast unavailable - returning empty list") + return [] # Publish event try: diff --git a/services/external/app/services/weather_service.py b/services/external/app/services/weather_service.py index 52eb7899..81e35d79 100644 --- a/services/external/app/services/weather_service.py +++ b/services/external/app/services/weather_service.py @@ -22,7 +22,7 @@ class WeatherService: self.database_manager = database_manager async def get_current_weather(self, latitude: float, longitude: float) -> Optional[WeatherDataResponse]: - """Get current weather for location""" + """Get current weather for location with graceful failure handling""" try: logger.debug("Getting current weather", lat=latitude, lon=longitude) weather_data = await self.aemet_client.get_current_weather(latitude, longitude) @@ -31,12 +31,32 @@ class WeatherService: logger.debug("Weather data received", source=weather_data.get('source')) return WeatherDataResponse(**weather_data) else: - logger.warning("No weather data received from AEMET client") - return None + logger.warning("No weather data received from AEMET client - providing service unavailable response") + # Return a response indicating service unavailable rather than None + return WeatherDataResponse( + date=datetime.utcnow().isoformat(), + temperature=None, + precipitation=None, + humidity=None, + wind_speed=None, + pressure=None, + description="Servicio meteorológico temporalmente no disponible", + source="unavailable" + ) except Exception as e: logger.error("Failed to get current weather", error=str(e), lat=latitude, lon=longitude) - return None + # Return error response rather than None to prevent 404 + return WeatherDataResponse( + date=datetime.utcnow().isoformat(), + temperature=None, + precipitation=None, + humidity=None, + wind_speed=None, + pressure=None, + description="Error al obtener datos meteorológicos", + source="error" + ) async def get_weather_forecast(self, latitude: float, longitude: float, days: int = 7) -> List[WeatherForecastResponse]: """Get weather forecast for location"""