Collector: poll_pool_pumps — 1min telemetrie Shelly bazénu

- 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 <noreply@anthropic.com>
This commit is contained in:
Dusan Vojacek
2026-06-11 22:37:57 +02:00
parent 7f22311172
commit 733224d18d

View File

@@ -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,
)