From b7b2e7fc61f7085fc138a0d7c621b6385fdb2e9d Mon Sep 17 00:00:00 2001 From: simon Date: Sun, 5 Jul 2026 01:41:02 +0100 Subject: [PATCH] Fix periodic poll never finding new readings extract_readings() only read the latestReading field embedded in the stations-endpoint response. For some stations that field is always null even though the measure's own /readings endpoint has current data, so every non-backfill poll silently found 0 readings forever. Now falls back to fetching the single latest reading directly from the measure when the embedded field is missing. Co-Authored-By: Claude Sonnet 5 --- river_monitor.py | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/river_monitor.py b/river_monitor.py index 1730b3c..732451e 100644 --- a/river_monitor.py +++ b/river_monitor.py @@ -160,7 +160,22 @@ def fetch_historical_readings( return readings -def extract_readings(stations: Iterable[dict]) -> list[Reading]: +def fetch_latest_reading(session: requests.Session, measure_id: str) -> Optional[dict]: + """Fetch a measure's single most recent reading directly. Some stations + never populate the stations-endpoint's embedded `latestReading` field, + even though the measure's own /readings endpoint has current data.""" + try: + resp = session.get( + f"{measure_id}/readings", params={"_sorted": "", "_limit": 1}, timeout=15 + ) + resp.raise_for_status() + except requests.RequestException: + return None + items = resp.json().get("items", []) + return items[0] if items else None + + +def extract_readings(session: requests.Session, stations: Iterable[dict]) -> list[Reading]: readings: list[Reading] = [] for station in stations: station_id = station.get("stationReference") or station.get("@id", "").rsplit("/", 1)[-1] @@ -178,7 +193,10 @@ def extract_readings(stations: Iterable[dict]) -> list[Reading]: for measure in measures: if measure.get("parameter") != "level": continue + measure_id = measure.get("@id", "") latest = measure.get("latestReading") + if not latest and measure_id: + latest = fetch_latest_reading(session, measure_id) if not latest: continue readings.append( @@ -188,7 +206,7 @@ def extract_readings(stations: Iterable[dict]) -> list[Reading]: river_name=river_name, lat=lat, lon=lon, - measure_id=measure.get("@id", ""), + measure_id=measure_id, unit=measure.get("unitName"), qualifier=measure.get("qualifier"), value=latest.get("value"), @@ -445,7 +463,7 @@ def poll_once(cfg: dict, session: requests.Session, verbose: bool = True, backfi print(f"[{ts}] Backfilling {backfill_days} days of history for {len(stations)} stations...") readings = fetch_historical_readings(session, stations, backfill_days) else: - readings = extract_readings(stations) + readings = extract_readings(session, stations) new_rows = store_readings(conn, readings) if not no_html: build_dashboard(conn, Path(cfg["output"]))