extract radio runtime seam

This commit is contained in:
Jack Kingsman
2026-03-09 23:07:34 -07:00
parent 5e94b14b45
commit 81bdfe09fa
14 changed files with 210 additions and 22 deletions
+1 -1
View File
@@ -7,10 +7,10 @@ from pydantic import BaseModel, Field
from app.dependencies import require_connected
from app.models import Channel, ChannelDetail, ChannelMessageCounts, ChannelTopSender
from app.radio import radio_manager
from app.radio_sync import upsert_channel_from_radio_slot
from app.region_scope import normalize_region_scope
from app.repository import ChannelRepository, MessageRepository
from app.services.radio_runtime import radio_runtime as radio_manager
from app.websocket import broadcast_event
logger = logging.getLogger(__name__)
+1 -1
View File
@@ -18,7 +18,6 @@ from app.models import (
)
from app.packet_processor import start_historical_dm_decryption
from app.path_utils import parse_explicit_hop_route
from app.radio import radio_manager
from app.repository import (
AmbiguousPublicKeyPrefixError,
ContactAdvertPathRepository,
@@ -27,6 +26,7 @@ from app.repository import (
MessageRepository,
)
from app.services.contact_reconciliation import reconcile_contact_messages
from app.services.radio_runtime import radio_runtime as radio_manager
logger = logging.getLogger(__name__)
+3 -1
View File
@@ -5,8 +5,8 @@ from fastapi import APIRouter
from pydantic import BaseModel
from app.config import settings
from app.radio import radio_manager
from app.repository import RawPacketRepository
from app.services.radio_runtime import radio_runtime as radio_manager
router = APIRouter(tags=["health"])
@@ -53,6 +53,8 @@ async def build_health_data(radio_connected: bool, connection_info: str | None)
setup_complete = getattr(radio_manager, "is_setup_complete", radio_connected)
if not isinstance(setup_complete, bool):
setup_complete = radio_connected
if not radio_connected:
setup_complete = False
radio_initializing = bool(radio_connected and (setup_in_progress or not setup_complete))
+1 -1
View File
@@ -11,13 +11,13 @@ from app.models import (
SendChannelMessageRequest,
SendDirectMessageRequest,
)
from app.radio import radio_manager
from app.repository import AmbiguousPublicKeyPrefixError, AppSettingsRepository, MessageRepository
from app.services.message_send import (
resend_channel_message_record,
send_channel_message_to_channel,
send_direct_message_to_contact,
)
from app.services.radio_runtime import radio_runtime as radio_manager
from app.websocket import broadcast_error, broadcast_event
logger = logging.getLogger(__name__)
+14 -7
View File
@@ -4,7 +4,6 @@ from fastapi import APIRouter, HTTPException
from pydantic import BaseModel, Field
from app.dependencies import require_connected
from app.radio import radio_manager
from app.radio_sync import send_advertisement as do_send_advertisement
from app.radio_sync import sync_radio_time
from app.services.radio_commands import (
@@ -14,11 +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
class RadioSettings(BaseModel):
freq: float = Field(description="Frequency in MHz")
bw: float = Field(description="Bandwidth in kHz")
@@ -160,8 +168,6 @@ async def send_advertisement() -> dict:
async def _attempt_reconnect() -> dict:
"""Shared reconnection logic for reboot and reconnect endpoints."""
from app.services.radio_lifecycle import reconnect_and_prepare_radio
if radio_manager.is_reconnecting:
return {
"status": "pending",
@@ -171,7 +177,7 @@ async def _attempt_reconnect() -> dict:
try:
success = await reconnect_and_prepare_radio(
radio_manager,
_unwrap_radio_manager(),
broadcast_on_success=True,
)
except Exception as e:
@@ -217,15 +223,16 @@ async def reconnect_radio() -> dict:
if no specific port is configured. Useful when the radio has been disconnected
or power-cycled.
"""
from app.services.radio_lifecycle import prepare_connected_radio
if radio_manager.is_connected:
if radio_manager.is_setup_complete:
return {"status": "ok", "message": "Already connected", "connected": True}
logger.info("Radio connected but setup incomplete, retrying setup")
try:
await prepare_connected_radio(radio_manager, broadcast_on_success=True)
await prepare_connected_radio(
_unwrap_radio_manager(),
broadcast_on_success=True,
)
return {"status": "ok", "message": "Setup completed", "connected": True}
except Exception as e:
logger.exception("Post-connect setup failed")
+1 -1
View File
@@ -6,13 +6,13 @@ import time
from fastapi import APIRouter
from app.models import UnreadCounts
from app.radio import radio_manager
from app.repository import (
AppSettingsRepository,
ChannelRepository,
ContactRepository,
MessageRepository,
)
from app.services.radio_runtime import radio_runtime as radio_manager
logger = logging.getLogger(__name__)
router = APIRouter(prefix="/read-state", tags=["read-state"])
+1 -1
View File
@@ -25,9 +25,9 @@ from app.models import (
RepeaterRadioSettingsResponse,
RepeaterStatusResponse,
)
from app.radio import radio_manager
from app.repository import ContactRepository
from app.routers.contacts import _ensure_on_radio, _resolve_contact_or_404
from app.services.radio_runtime import radio_runtime as radio_manager
if TYPE_CHECKING:
from meshcore.events import Event
+1 -1
View File
@@ -132,7 +132,7 @@ async def update_settings(update: AppSettingsUpdate) -> AppSettings:
# Apply flood scope to radio immediately if changed
if flood_scope_changed:
from app.radio import radio_manager
from app.services.radio_runtime import radio_runtime as radio_manager
if radio_manager.is_connected:
try:
+1 -1
View File
@@ -4,8 +4,8 @@ import logging
from fastapi import APIRouter, WebSocket, WebSocketDisconnect
from app.radio import radio_manager
from app.routers.health import build_health_data
from app.services.radio_runtime import radio_runtime as radio_manager
from app.websocket import ws_manager
logger = logging.getLogger(__name__)