mirror of
https://github.com/ChuckBuilds/LEDMatrix.git
synced 2026-04-11 13:23:00 +00:00
Improve weather network error handling. Add retry logic with backoff and better caching fallback.
This commit is contained in:
@@ -7,6 +7,9 @@ from .weather_icons import WeatherIcons
|
|||||||
from .cache_manager import CacheManager
|
from .cache_manager import CacheManager
|
||||||
import logging
|
import logging
|
||||||
import threading
|
import threading
|
||||||
|
from requests.adapters import HTTPAdapter
|
||||||
|
from urllib3.util.retry import Retry
|
||||||
|
from requests.exceptions import RequestException, SSLError, ConnectionError
|
||||||
|
|
||||||
class WeatherManager:
|
class WeatherManager:
|
||||||
# Weather condition to larger colored icons (we'll use these as placeholders until you provide custom ones)
|
# Weather condition to larger colored icons (we'll use these as placeholders until you provide custom ones)
|
||||||
@@ -68,6 +71,17 @@ class WeatherManager:
|
|||||||
self.last_hourly_state = None
|
self.last_hourly_state = None
|
||||||
self.last_daily_state = None
|
self.last_daily_state = None
|
||||||
|
|
||||||
|
# Configure retry strategy
|
||||||
|
self.session = requests.Session()
|
||||||
|
retry_strategy = Retry(
|
||||||
|
total=3, # number of retries
|
||||||
|
backoff_factor=0.5, # wait 0.5, 1, 2 seconds between retries
|
||||||
|
status_forcelist=[500, 502, 503, 504], # HTTP status codes to retry on
|
||||||
|
)
|
||||||
|
adapter = HTTPAdapter(max_retries=retry_strategy)
|
||||||
|
self.session.mount("https://", adapter)
|
||||||
|
self.session.mount("http://", adapter)
|
||||||
|
|
||||||
def _process_forecast_data(self, data: Dict[str, Any]) -> Dict[str, Any]:
|
def _process_forecast_data(self, data: Dict[str, Any]) -> Dict[str, Any]:
|
||||||
"""Process forecast data with caching."""
|
"""Process forecast data with caching."""
|
||||||
current_time = time.time()
|
current_time = time.time()
|
||||||
@@ -129,15 +143,34 @@ class WeatherManager:
|
|||||||
"units": units
|
"units": units
|
||||||
}
|
}
|
||||||
|
|
||||||
response = requests.get(current_url, params=params, timeout=10)
|
try:
|
||||||
response.raise_for_status()
|
response = self.session.get(current_url, params=params, timeout=10)
|
||||||
current_data = response.json()
|
response.raise_for_status()
|
||||||
|
current_data = response.json()
|
||||||
|
except (ConnectionError, RequestException) as e:
|
||||||
|
self.logger.error(f"Network error fetching current weather: {e}")
|
||||||
|
# Try to use cached data as fallback
|
||||||
|
cached_data = self.cache_manager.get_cached_data('weather', max_age=self._update_interval)
|
||||||
|
if cached_data:
|
||||||
|
self.logger.info("Using cached weather data due to network error")
|
||||||
|
return self._process_forecast_data(cached_data)
|
||||||
|
return None
|
||||||
|
|
||||||
# Fetch forecast
|
# Fetch forecast
|
||||||
forecast_url = "https://api.openweathermap.org/data/2.5/forecast"
|
forecast_url = "https://api.openweathermap.org/data/2.5/forecast"
|
||||||
response = requests.get(forecast_url, params=params, timeout=10)
|
try:
|
||||||
response.raise_for_status()
|
response = self.session.get(forecast_url, params=params, timeout=10)
|
||||||
forecast_data = response.json()
|
response.raise_for_status()
|
||||||
|
forecast_data = response.json()
|
||||||
|
except (ConnectionError, RequestException) as e:
|
||||||
|
self.logger.error(f"Network error fetching forecast: {e}")
|
||||||
|
# If we have current data but forecast failed, use cached forecast if available
|
||||||
|
cached_data = self.cache_manager.get_cached_data('weather', max_age=self._update_interval)
|
||||||
|
if cached_data and 'hourly' in cached_data:
|
||||||
|
self.logger.info("Using cached forecast data due to network error")
|
||||||
|
forecast_data = {'list': cached_data['hourly']}
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
# Combine the data
|
# Combine the data
|
||||||
data = {
|
data = {
|
||||||
|
|||||||
Reference in New Issue
Block a user