diff --git a/app/fanout/mqtt_ha.py b/app/fanout/mqtt_ha.py index f6fb21e..094c651 100644 --- a/app/fanout/mqtt_ha.py +++ b/app/fanout/mqtt_ha.py @@ -401,6 +401,7 @@ class MqttHaModule(FanoutModule): # ── Lifecycle ────────────────────────────────────────────────────── async def start(self) -> None: + self._seed_radio_identity_from_runtime() settings = _config_to_settings(self.config) await self._publisher.start(settings) @@ -480,6 +481,29 @@ class MqttHaModule(FanoutModule): pass return pub_key[:12] + def _seed_radio_identity_from_runtime(self) -> None: + """Best-effort bootstrap from the currently connected radio session.""" + try: + from app.services.radio_runtime import radio_runtime + + if not radio_runtime.is_connected: + return + + mc = radio_runtime.meshcore + self_info = mc.self_info if mc is not None else None + if not isinstance(self_info, dict): + return + + pub_key = self_info.get("public_key") + if isinstance(pub_key, str) and pub_key.strip(): + self._radio_key = pub_key.strip().lower() + + name = self_info.get("name") + if isinstance(name, str) and name.strip(): + self._radio_name = name.strip() + except Exception: + logger.debug("HA MQTT: failed to seed radio identity from runtime", exc_info=True) + # ── Event handlers ──────────────────────────────────────────────── async def on_health(self, data: dict) -> None: diff --git a/tests/test_mqtt_ha.py b/tests/test_mqtt_ha.py index f0b500c..d8973fc 100644 --- a/tests/test_mqtt_ha.py +++ b/tests/test_mqtt_ha.py @@ -1,5 +1,6 @@ """Tests for the Home Assistant MQTT Discovery fanout module.""" +from types import SimpleNamespace from unittest.mock import AsyncMock, MagicMock import pytest @@ -286,6 +287,31 @@ class TestMqttHaHealth: assert mod._radio_name == "MyRadio" +class TestMqttHaLifecycle: + @pytest.mark.asyncio + async def test_start_seeds_radio_identity_from_connected_runtime(self, monkeypatch): + from app.services.radio_runtime import radio_runtime + + monkeypatch.setattr( + radio_runtime.manager, + "_meshcore", + SimpleNamespace( + is_connected=True, + self_info={"public_key": "AABBCCDDEEFF", "name": "MyRadio"}, + ), + ) + + mod = MqttHaModule("test", _base_config()) + mod._publisher = MagicMock() + mod._publisher.start = AsyncMock() + + await mod.start() + + assert mod._radio_key == "aabbccddeeff" + assert mod._radio_name == "MyRadio" + mod._publisher.start.assert_awaited_once() + + class TestMqttHaMessage: @pytest.mark.asyncio async def test_on_message_publishes_event(self):