71 lines
2.2 KiB
Python
71 lines
2.2 KiB
Python
"""Heartbeat: DB záznam + volitelný HTTP pulz do Loxone."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import logging
|
|
import os
|
|
|
|
import httpx
|
|
|
|
from app.config import get_settings
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
EMS_BACKEND_VERSION = "v1.0.0"
|
|
|
|
|
|
async def send_heartbeat(
|
|
site_id: int,
|
|
db,
|
|
loxone_host: str | None = None,
|
|
loxone_port: int | None = None,
|
|
) -> None:
|
|
"""
|
|
1. Aktualizuje ems.site_heartbeat v DB
|
|
2. Pokud je Loxone nakonfigurováno, pošle HTTP pulz
|
|
"""
|
|
try:
|
|
endpoint = await db.fetchrow(
|
|
"""
|
|
SELECT host, port, protocol, auth_reference
|
|
FROM ems.site_endpoint
|
|
WHERE site_id = $1 AND endpoint_type = 'loxone_http' AND enabled = true
|
|
ORDER BY id
|
|
LIMIT 1
|
|
""",
|
|
site_id,
|
|
)
|
|
|
|
loxone_ok = False
|
|
if endpoint:
|
|
proto = (endpoint["protocol"] or "http").lower()
|
|
if proto not in ("http", "https"):
|
|
proto = "http"
|
|
host = loxone_host if loxone_host is not None else endpoint["host"]
|
|
if loxone_port is not None:
|
|
port = int(loxone_port)
|
|
else:
|
|
port = int(endpoint["port"] or (443 if proto == "https" else 80))
|
|
|
|
url = f"{proto}://{host}:{port}/dev/sps/io/EMS_Heartbeat/1"
|
|
settings = get_settings()
|
|
user = settings.loxone_user or os.getenv("LOXONE_USER") or ""
|
|
password = settings.loxone_password or os.getenv("LOXONE_PASSWORD") or ""
|
|
auth = (user, password) if user else None
|
|
try:
|
|
async with httpx.AsyncClient(timeout=5.0) as client:
|
|
await client.get(url, auth=auth)
|
|
loxone_ok = True
|
|
except Exception as e:
|
|
logger.warning("Heartbeat Loxone failed (site=%s): %s", site_id, e)
|
|
|
|
status = "ok" if (not endpoint or loxone_ok) else "degraded"
|
|
await db.execute(
|
|
"SELECT ems.fn_update_heartbeat($1, $2, $3)",
|
|
site_id,
|
|
status,
|
|
EMS_BACKEND_VERSION,
|
|
)
|
|
except Exception as e:
|
|
logger.error("Heartbeat service error (site=%s): %s", site_id, e)
|