From 733224d18de9769d47f956f7e42b5591028cfece Mon Sep 17 00:00:00 2001 From: Dusan Vojacek Date: Thu, 11 Jun 2026 22:37:57 +0200 Subject: [PATCH] =?UTF-8?q?Collector:=20poll=5Fpool=5Fpumps=20=E2=80=94=20?= =?UTF-8?q?1min=20telemetrie=20Shelly=20baz=C3=A9nu?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - nová funkce na konci souboru + jeden řádek v run_telemetry_loop (minimální dotyk kvůli souběžným změnám na main) - čte vw_asset_pool_pump_http_poll, zapisuje fn_telemetry_pool_pump_sample - při výpadku čtení nic nezapisuje (žádná fabrikovaná nula) Co-Authored-By: Claude Fable 5 --- backend/services/telemetry_collector.py | 40 +++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/backend/services/telemetry_collector.py b/backend/services/telemetry_collector.py index 588d180..aefe92a 100644 --- a/backend/services/telemetry_collector.py +++ b/backend/services/telemetry_collector.py @@ -300,6 +300,7 @@ async def run_telemetry_loop(conn: asyncpg.Connection) -> float: await poll_inverter(sid, conn) await poll_ev_chargers(sid, conn) await poll_heat_pump(sid, conn) + await poll_pool_pumps(sid, conn) except Exception as e: logger.error("Telemetry loop error site %s: %s", sid, e) return loop.time() - start @@ -322,3 +323,42 @@ async def run_telemetry_loop_wrapper(pool: asyncpg.Pool) -> None: if elapsed > 50: logger.warning("Telemetry loop took %.1fs (>50s)", elapsed) await asyncio.sleep(max(0.0, 60.0 - elapsed)) + + +async def poll_pool_pumps(site_id: int, db: asyncpg.Connection) -> None: + """Poll bazénových čerpadel přes Shelly relé (Gen2 RPC Switch.GetStatus), 60 s. + + Shelly nedrží historii — stavíme ji 1min vzorky jako u ostatních zařízení. + """ + # Lokální import: minimální dotyk hlavičky souboru (souběžné změny na main). + from services.shelly_client import get_switch_status, shelly_base_url + + rows = await db.fetch( + """ + select pump_id as id, code, shelly_switch_id, protocol, host, port + from ems.vw_asset_pool_pump_http_poll + where site_id = $1 + """, + site_id, + ) + measured_at = datetime.now(timezone.utc) + for row in rows: + code = row["code"] + base = shelly_base_url(row["protocol"], row["host"], row["port"]) + try: + status = await get_switch_status(base, int(row["shelly_switch_id"] or 0)) + except Exception as e: + # Při výpadku čtení NIC nezapisovat — fabrikovaná nula by špinila + # historii spotřeby (stejný princip jako u EV nabíječek výše). + logger.warning("pool pump %s (%s) read failed: %s", code, base, e) + continue + + await db.execute( + "select ems.fn_telemetry_pool_pump_sample($1::int, $2::int, $3::timestamptz, $4::boolean, $5::int, $6::bigint)", + site_id, + row["id"], + measured_at, + status.output, + int(round(status.apower_w)) if status.apower_w is not None else None, + int(round(status.aenergy_total_wh)) if status.aenergy_total_wh is not None else None, + )