Weather: Replace wttr.in with Open-Meteo + structured logging

- Replace wttr.in (unreachable from Docker) with Open-Meteo API
  (free, no API key, reliable) with geocoding cache
- WMO weather codes mapped to German descriptions + emoji icons
- Add [WEATHER], [NEWS], [UNRAID], [DASHBOARD] log prefixes
- Structured integration status table on startup
- Suppress noisy httpx INFO logs (services log their own summaries)
- Add logging to unraid_service (was completely silent on errors)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Sam 2026-03-02 17:45:23 +01:00
parent 94cf618e0d
commit d3305a243c
6 changed files with 280 additions and 196 deletions

View file

@ -1,10 +1,13 @@
from __future__ import annotations
import asyncio
import logging
import httpx
from dataclasses import dataclass, field
from typing import Any, Dict, List, Optional
logger = logging.getLogger(__name__)
@dataclass
class ServerConfig:
@ -114,9 +117,14 @@ async def _try_api_endpoint(
_parse_system_info(data, result)
_parse_array_info(data, result)
_parse_docker_info(data, result)
logger.info("[UNRAID] %s (%s): API OK", server.name, server.host)
return True
except Exception:
pass
else:
logger.warning("[UNRAID] %s (%s): /api/system returned HTTP %d",
server.name, server.host, resp.status_code)
except Exception as exc:
logger.warning("[UNRAID] %s (%s): /api/system failed: %s",
server.name, server.host, exc)
# Try individual endpoints if the combined one failed
fetched_any = False
@ -208,11 +216,16 @@ async def fetch_server_stats(server: ServerConfig) -> Dict[str, Any]:
api_ok = await _try_api_endpoint(client, server, result)
if not api_ok and not result["online"]:
logger.info("[UNRAID] %s: API failed, trying connectivity check", server.name)
await _try_connectivity_check(client, server, result)
except Exception as exc:
result["online"] = False
result["error"] = str(exc)
logger.error("[UNRAID] %s (%s): connection failed: %s", server.name, server.host, exc)
if not result["online"]:
logger.warning("[UNRAID] %s (%s): offline (error=%s)", server.name, server.host, result.get("error"))
return result