diff --git a/app/dependencies.py b/app/dependencies.py index a0bbcd2..af0a8b0 100644 --- a/app/dependencies.py +++ b/app/dependencies.py @@ -2,6 +2,7 @@ from fastapi import HTTPException +from app.services.radio_runtime import RadioRuntime from app.services.radio_runtime import radio_runtime as radio_manager @@ -10,6 +11,8 @@ def require_connected(): Raises HTTPException 503 if radio is not connected. """ + if isinstance(radio_manager, RadioRuntime): + return radio_manager.require_connected() if getattr(radio_manager, "is_setup_in_progress", False) is True: raise HTTPException(status_code=503, detail="Radio is initializing") mc = getattr(radio_manager, "meshcore", None) diff --git a/app/routers/radio.py b/app/routers/radio.py index 0914cf0..4e128a4 100644 --- a/app/routers/radio.py +++ b/app/routers/radio.py @@ -13,18 +13,20 @@ from app.services.radio_commands import ( apply_radio_config_update, import_private_key_and_refresh_keystore, ) -from app.services.radio_lifecycle import prepare_connected_radio, reconnect_and_prepare_radio -from app.services.radio_runtime import RadioRuntime from app.services.radio_runtime import radio_runtime as radio_manager logger = logging.getLogger(__name__) router = APIRouter(prefix="/radio", tags=["radio"]) -def _unwrap_radio_manager(): - if isinstance(radio_manager, RadioRuntime): - return radio_manager.manager - return radio_manager +async def _prepare_connected(*, broadcast_on_success: bool) -> None: + await radio_manager.prepare_connected(broadcast_on_success=broadcast_on_success) + + +async def _reconnect_and_prepare(*, broadcast_on_success: bool) -> bool: + return await radio_manager.reconnect_and_prepare( + broadcast_on_success=broadcast_on_success, + ) class RadioSettings(BaseModel): @@ -176,10 +178,7 @@ async def _attempt_reconnect() -> dict: } try: - success = await reconnect_and_prepare_radio( - _unwrap_radio_manager(), - broadcast_on_success=True, - ) + success = await _reconnect_and_prepare(broadcast_on_success=True) except Exception as e: logger.exception("Post-connect setup failed after reconnect") raise HTTPException( @@ -229,10 +228,7 @@ async def reconnect_radio() -> dict: logger.info("Radio connected but setup incomplete, retrying setup") try: - await prepare_connected_radio( - _unwrap_radio_manager(), - broadcast_on_success=True, - ) + await _prepare_connected(broadcast_on_success=True) return {"status": "ok", "message": "Setup completed", "connected": True} except Exception as e: logger.exception("Post-connect setup failed") diff --git a/tests/test_radio_router.py b/tests/test_radio_router.py index 095e3d6..9fbbc55 100644 --- a/tests/test_radio_router.py +++ b/tests/test_radio_router.py @@ -22,6 +22,7 @@ from app.routers.radio import ( set_private_key, update_radio_config, ) +from app.services.radio_runtime import RadioRuntime def _radio_result(event_type=EventType.OK, payload=None): @@ -41,6 +42,10 @@ def _noop_radio_operation(mc=None): return _ctx +def _runtime(manager): + return RadioRuntime(lambda: manager) + + @pytest.fixture(autouse=True) def _reset_radio_state(): """Save/restore radio_manager state so tests don't leak.""" @@ -301,7 +306,7 @@ class TestAdvertise: isolated_manager._meshcore = MagicMock() with ( patch("app.routers.radio.require_connected"), - patch("app.routers.radio.radio_manager", isolated_manager), + patch("app.routers.radio.radio_manager", _runtime(isolated_manager)), patch( "app.routers.radio.do_send_advertisement", new_callable=AsyncMock, @@ -324,7 +329,7 @@ class TestRebootAndReconnect: mock_rm.meshcore = mock_mc mock_rm.radio_operation = _noop_radio_operation(mock_mc) - with patch("app.routers.radio.radio_manager", mock_rm): + with patch("app.routers.radio.radio_manager", _runtime(mock_rm)): result = await reboot_radio() assert result["status"] == "ok" @@ -338,7 +343,7 @@ class TestRebootAndReconnect: mock_rm.is_reconnecting = True mock_rm.radio_operation = _noop_radio_operation() - with patch("app.routers.radio.radio_manager", mock_rm): + with patch("app.routers.radio.radio_manager", _runtime(mock_rm)): result = await reboot_radio() assert result["status"] == "pending" @@ -353,8 +358,9 @@ class TestRebootAndReconnect: mock_rm.reconnect = AsyncMock(return_value=True) mock_rm.post_connect_setup = AsyncMock() mock_rm.radio_operation = _noop_radio_operation() + mock_rm.connection_info = "TCP: test:4000" - with patch("app.routers.radio.radio_manager", mock_rm): + with patch("app.routers.radio.radio_manager", _runtime(mock_rm)): result = await reboot_radio() assert result["status"] == "ok" @@ -367,8 +373,9 @@ class TestRebootAndReconnect: mock_rm = MagicMock() mock_rm.is_connected = True mock_rm.radio_operation = _noop_radio_operation() + mock_rm.is_setup_complete = True - with patch("app.routers.radio.radio_manager", mock_rm): + with patch("app.routers.radio.radio_manager", _runtime(mock_rm)): result = await reconnect_radio() assert result["status"] == "ok" @@ -382,7 +389,7 @@ class TestRebootAndReconnect: mock_rm.reconnect = AsyncMock(return_value=False) mock_rm.radio_operation = _noop_radio_operation() - with patch("app.routers.radio.radio_manager", mock_rm): + with patch("app.routers.radio.radio_manager", _runtime(mock_rm)): with pytest.raises(HTTPException) as exc: await reconnect_radio()