Landscape orientation, redesigned web UI, rotation on/off + minutes, weather by city name
- Panel is mounted sideways: render landscape (600x400), rotate to the panel's native portrait orientation right before writing to hardware. - Web UI: card-based layout, dark mode, active nav highlighting, save confirmation toasts, error banners. - Rotation: separate enabled/disabled toggle (off pins to the first screen in the list) and the interval is now in minutes instead of raw seconds. Migrates existing config.json from the old interval_seconds field. - Weather: type a city name instead of hunting down coordinates, resolved via Open-Meteo's free geocoding API. Manual lat/long still available as a fallback.
This commit is contained in:
1 parent
7c197e20a5
commit
61348be674
11 files changed
+393
-104
No files matched your search
+24
-1
@@ -11,6 +11,7 @@ from screens.render_utils import load_font, text_width
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
HTTP_TIMEOUT = 10
|
||||
GEOCODE_URL = "https://geocoding-api.open-meteo.com/v1/search"
|
||||
|
||||
# WMO weather codes -> (German description, symbol). Not exhaustive, covers
|
||||
# the common cases; unmapped codes fall back to a generic description.
|
||||
@@ -47,7 +48,29 @@ class WeatherScreen(Screen):
|
||||
poll_interval = 1800 # 30 minutes -- weather doesn't need to be fresher
|
||||
|
||||
def default_settings(self) -> dict:
|
||||
return {"latitude": None, "longitude": None}
|
||||
return {"city": "", "latitude": None, "longitude": None}
|
||||
|
||||
def geocode(self, city: str):
|
||||
"""Resolve a city name to coordinates via Open-Meteo's free geocoding
|
||||
API (no key needed). Returns {"latitude", "longitude", "label"} or
|
||||
None if nothing matched."""
|
||||
response = requests.get(
|
||||
GEOCODE_URL,
|
||||
params={"name": city, "count": 1, "language": "de"},
|
||||
timeout=HTTP_TIMEOUT,
|
||||
)
|
||||
response.raise_for_status()
|
||||
results = response.json().get("results") or []
|
||||
if not results:
|
||||
return None
|
||||
|
||||
top = results[0]
|
||||
label_parts = [top.get("name"), top.get("admin1"), top.get("country")]
|
||||
return {
|
||||
"latitude": top["latitude"],
|
||||
"longitude": top["longitude"],
|
||||
"label": ", ".join(p for p in label_parts if p),
|
||||
}
|
||||
|
||||
def check(self, settings: dict):
|
||||
lat = settings.get("latitude")
|
||||
|
||||
Reference in new issue
Block a user