M5-T11: add HA discovery and state publishing wired to polling
This commit is contained in:
+36
@@ -28,6 +28,7 @@ from app.services.auth import AuthBootstrapError, initialize_auth_schema
|
||||
from app.services.config_page import seed_missing_config_from_bootstrap, sync_app_hostname_from_bootstrap
|
||||
from app.services.public_ip import check_public_ipv4_and_notify
|
||||
from app.services.modbus_poll import poll_all_enabled_devices, BASE_POLL_TICK_SECONDS
|
||||
from app.services.ha_discovery import publish_discovery, publish_states
|
||||
from scripts.app_db_adopt import AppDatabaseAdoptionError, validate_app_runtime_db
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -60,6 +61,30 @@ def _run_scheduled_modbus_poll() -> None:
|
||||
session.close()
|
||||
|
||||
|
||||
def _run_scheduled_ha_state_publish() -> None:
|
||||
"""Periodic job: publish discovery configs + state + availability for all enabled exposed entities.
|
||||
|
||||
Runs every 60 seconds. When the MQTT broker is connected:
|
||||
- Publishes (or re-publishes) all HA Discovery configs (retained, idempotent).
|
||||
- Publishes the current state / availability for all enabled entities.
|
||||
|
||||
This also serves as the reliable "publish discovery after connect" mechanism:
|
||||
because paho connects asynchronously, a synchronous call immediately after
|
||||
``mqtt_manager.connect()`` would fire before the TCP handshake completes and
|
||||
be a no-op. Instead, this periodic job picks it up within 60 seconds of the
|
||||
broker becoming available — retained payloads make repeated publishes harmless.
|
||||
"""
|
||||
session_local = get_session_local()
|
||||
session: Session = session_local()
|
||||
try:
|
||||
publish_discovery(session)
|
||||
publish_states(session)
|
||||
except Exception:
|
||||
logger.exception("_run_scheduled_ha_state_publish: unexpected error")
|
||||
finally:
|
||||
session.close()
|
||||
|
||||
|
||||
def ensure_auth_db_ready() -> None:
|
||||
session_local = get_session_local()
|
||||
session: Session = session_local()
|
||||
@@ -103,9 +128,20 @@ async def lifespan(_: FastAPI):
|
||||
max_instances=1,
|
||||
coalesce=True,
|
||||
)
|
||||
# Periodic HA state / availability publish (60-second fallback sweep).
|
||||
scheduler.add_job(
|
||||
_run_scheduled_ha_state_publish,
|
||||
trigger=IntervalTrigger(seconds=60),
|
||||
id="ha-state-publish",
|
||||
replace_existing=True,
|
||||
max_instances=1,
|
||||
coalesce=True,
|
||||
)
|
||||
scheduler.start()
|
||||
|
||||
# MQTT: connect if configured.
|
||||
# Discovery will be published by the first run of _run_scheduled_ha_state_publish
|
||||
# (within 60 s of startup), after the async paho handshake completes.
|
||||
mqtt_manager.connect(get_settings())
|
||||
|
||||
yield
|
||||
|
||||
Reference in New Issue
Block a user