- new per-host service, follows node-agent pattern - 7 new HA event types defined (routing in supervisor — Phase 5) - HeartbeatCheck as pipeline validator (pings /api/, emits ha_websocket_dead) - service.yaml + host configs for piha (ken) and chelsty-infra (chelsty) - test scaffolding with aiohttp/aiosqlite mocks (15/15 passing) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
48 lines
1.6 KiB
Python
48 lines
1.6 KiB
Python
from __future__ import annotations
|
|
|
|
from ..ha_client import HAClient
|
|
from ..models import CheckResult, HAEventType, Severity
|
|
from .base import Check
|
|
|
|
|
|
class HeartbeatCheck(Check):
|
|
"""Pings HA /api/ to verify the API is reachable.
|
|
|
|
Validates the end-to-end pipeline: HA client → check result → event emitter.
|
|
Real diagnostic checks (entity availability, system health, etc.) come in Phase 3.
|
|
"""
|
|
|
|
name = "heartbeat"
|
|
|
|
def __init__(self, ha_client: HAClient) -> None:
|
|
self._client = ha_client
|
|
|
|
async def run(self) -> CheckResult:
|
|
try:
|
|
async with self._client:
|
|
data = await self._client.get_api_status()
|
|
if isinstance(data, dict) and "message" in data:
|
|
return CheckResult(
|
|
healthy=True,
|
|
event_type=None,
|
|
severity=Severity.info,
|
|
message="HA API reachable",
|
|
payload={"response": data},
|
|
)
|
|
return CheckResult(
|
|
healthy=False,
|
|
event_type=HAEventType.ha_websocket_dead,
|
|
severity=Severity.error,
|
|
message=f"HA API returned unexpected response: {data!r}",
|
|
payload={"response": str(data)},
|
|
)
|
|
except Exception as exc:
|
|
return CheckResult(
|
|
healthy=False,
|
|
event_type=HAEventType.ha_websocket_dead,
|
|
severity=Severity.error,
|
|
message=f"HA API unreachable: {exc}",
|
|
payload={"error": str(exc)},
|
|
)
|
|
|