mirror of
https://github.com/jkingsman/Remote-Terminal-for-MeshCore.git
synced 2026-08-06 08:43:36 +02:00
Add radio model and stats display. Closes #64
This commit is contained in:
@@ -78,6 +78,11 @@ class TestHealthEndpoint:
|
||||
with patch("app.routers.health.radio_manager") as mock_rm:
|
||||
mock_rm.is_connected = True
|
||||
mock_rm.connection_info = "Serial: /dev/ttyUSB0"
|
||||
mock_rm.is_setup_in_progress = False
|
||||
mock_rm.is_setup_complete = True
|
||||
mock_rm.connection_desired = True
|
||||
mock_rm.is_reconnecting = False
|
||||
mock_rm.device_info_loaded = False
|
||||
|
||||
from app.main import app
|
||||
|
||||
@@ -97,6 +102,11 @@ class TestHealthEndpoint:
|
||||
with patch("app.routers.health.radio_manager") as mock_rm:
|
||||
mock_rm.is_connected = False
|
||||
mock_rm.connection_info = None
|
||||
mock_rm.is_setup_in_progress = False
|
||||
mock_rm.is_setup_complete = False
|
||||
mock_rm.connection_desired = True
|
||||
mock_rm.is_reconnecting = False
|
||||
mock_rm.device_info_loaded = False
|
||||
|
||||
from app.main import app
|
||||
|
||||
@@ -1118,6 +1128,11 @@ class TestHealthEndpointDatabaseSize:
|
||||
):
|
||||
mock_rm.is_connected = True
|
||||
mock_rm.connection_info = "Serial: /dev/ttyUSB0"
|
||||
mock_rm.is_setup_in_progress = False
|
||||
mock_rm.is_setup_complete = True
|
||||
mock_rm.connection_desired = True
|
||||
mock_rm.is_reconnecting = False
|
||||
mock_rm.device_info_loaded = False
|
||||
mock_getsize.return_value = 10 * 1024 * 1024 # 10 MB
|
||||
|
||||
from app.main import app
|
||||
@@ -1148,6 +1163,11 @@ class TestHealthEndpointOldestUndecrypted:
|
||||
):
|
||||
mock_rm.is_connected = True
|
||||
mock_rm.connection_info = "Serial: /dev/ttyUSB0"
|
||||
mock_rm.is_setup_in_progress = False
|
||||
mock_rm.is_setup_complete = True
|
||||
mock_rm.connection_desired = True
|
||||
mock_rm.is_reconnecting = False
|
||||
mock_rm.device_info_loaded = False
|
||||
mock_getsize.return_value = 5 * 1024 * 1024 # 5 MB
|
||||
mock_repo.get_oldest_undecrypted = AsyncMock(return_value=1700000000)
|
||||
|
||||
@@ -1175,6 +1195,11 @@ class TestHealthEndpointOldestUndecrypted:
|
||||
):
|
||||
mock_rm.is_connected = True
|
||||
mock_rm.connection_info = "Serial: /dev/ttyUSB0"
|
||||
mock_rm.is_setup_in_progress = False
|
||||
mock_rm.is_setup_complete = True
|
||||
mock_rm.connection_desired = True
|
||||
mock_rm.is_reconnecting = False
|
||||
mock_rm.device_info_loaded = False
|
||||
mock_getsize.return_value = 1 * 1024 * 1024 # 1 MB
|
||||
mock_repo.get_oldest_undecrypted = AsyncMock(return_value=None)
|
||||
|
||||
@@ -1202,6 +1227,11 @@ class TestHealthEndpointOldestUndecrypted:
|
||||
):
|
||||
mock_rm.is_connected = False
|
||||
mock_rm.connection_info = None
|
||||
mock_rm.is_setup_in_progress = False
|
||||
mock_rm.is_setup_complete = False
|
||||
mock_rm.connection_desired = True
|
||||
mock_rm.is_reconnecting = False
|
||||
mock_rm.device_info_loaded = False
|
||||
mock_getsize.side_effect = OSError("File not found")
|
||||
mock_repo.get_oldest_undecrypted = AsyncMock(side_effect=RuntimeError("No DB"))
|
||||
|
||||
|
||||
@@ -59,6 +59,35 @@ class TestHealthFanoutStatus:
|
||||
assert data["radio_state"] == "connected"
|
||||
assert data["connection_info"] == "Serial: /dev/ttyUSB0"
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_health_includes_cached_radio_device_info(self, test_db):
|
||||
"""Health includes device metadata captured during post-connect setup."""
|
||||
with (
|
||||
patch(
|
||||
"app.routers.health.RawPacketRepository.get_oldest_undecrypted", return_value=None
|
||||
),
|
||||
patch("app.routers.health.radio_manager") as mock_rm,
|
||||
):
|
||||
mock_rm.is_setup_in_progress = False
|
||||
mock_rm.is_setup_complete = True
|
||||
mock_rm.connection_desired = True
|
||||
mock_rm.is_reconnecting = False
|
||||
mock_rm.device_info_loaded = True
|
||||
mock_rm.device_model = "T-Echo"
|
||||
mock_rm.firmware_build = "2025-02-01"
|
||||
mock_rm.firmware_version = "1.2.3"
|
||||
mock_rm.max_contacts = 350
|
||||
mock_rm.max_channels = 64
|
||||
data = await build_health_data(True, "Serial: /dev/ttyUSB0")
|
||||
|
||||
assert data["radio_device_info"] == {
|
||||
"model": "T-Echo",
|
||||
"firmware_build": "2025-02-01",
|
||||
"firmware_version": "1.2.3",
|
||||
"max_contacts": 350,
|
||||
"max_channels": 64,
|
||||
}
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_health_status_degraded_when_disconnected(self, test_db):
|
||||
"""Health status is 'degraded' when radio is disconnected."""
|
||||
|
||||
@@ -476,6 +476,11 @@ class TestManualDisconnectCleanup:
|
||||
mock_mc.connection_manager = connection_manager
|
||||
rm._meshcore = mock_mc
|
||||
rm._setup_complete = True
|
||||
rm.device_info_loaded = True
|
||||
rm.max_contacts = 350
|
||||
rm.device_model = "T-Echo"
|
||||
rm.firmware_build = "2025-02-01"
|
||||
rm.firmware_version = "1.2.3"
|
||||
rm.max_channels = 8
|
||||
rm.path_hash_mode = 2
|
||||
rm.path_hash_mode_supported = True
|
||||
@@ -491,6 +496,11 @@ class TestManualDisconnectCleanup:
|
||||
assert reconnect_task is not None and reconnect_task.cancelled()
|
||||
assert rm.meshcore is None
|
||||
assert rm.is_setup_complete is False
|
||||
assert rm.device_info_loaded is False
|
||||
assert rm.max_contacts is None
|
||||
assert rm.device_model is None
|
||||
assert rm.firmware_build is None
|
||||
assert rm.firmware_version is None
|
||||
assert rm.max_channels == 40
|
||||
assert rm.path_hash_mode == 0
|
||||
assert rm.path_hash_mode_supported is False
|
||||
|
||||
@@ -112,6 +112,11 @@ class TestRunPostConnectSetup:
|
||||
radio_manager._setup_lock = None
|
||||
radio_manager._setup_in_progress = False
|
||||
radio_manager._setup_complete = False
|
||||
radio_manager.device_info_loaded = False
|
||||
radio_manager.max_contacts = None
|
||||
radio_manager.device_model = None
|
||||
radio_manager.firmware_build = None
|
||||
radio_manager.firmware_version = None
|
||||
radio_manager.max_channels = 40
|
||||
radio_manager.path_hash_mode = 0
|
||||
radio_manager.path_hash_mode_supported = False
|
||||
@@ -145,3 +150,66 @@ class TestRunPostConnectSetup:
|
||||
replacement_mc.start_auto_message_fetching.assert_awaited_once()
|
||||
initial_mc.start_auto_message_fetching.assert_not_called()
|
||||
assert radio_manager.max_channels == 8
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_caches_device_info_metadata_from_device_query(self):
|
||||
mc = MagicMock()
|
||||
mc.commands.send_device_query = AsyncMock(
|
||||
return_value=MagicMock(
|
||||
payload={
|
||||
"fw ver": 10,
|
||||
"max_contacts": 350,
|
||||
"max_channels": 64,
|
||||
"model": "T-Echo",
|
||||
"fw_build": "2025-02-01",
|
||||
"ver": "1.2.3",
|
||||
"path_hash_mode": 2,
|
||||
}
|
||||
)
|
||||
)
|
||||
mc.commands.set_flood_scope = AsyncMock(return_value=None)
|
||||
mc._reader = MagicMock()
|
||||
mc._reader.handle_rx = AsyncMock()
|
||||
mc.start_auto_message_fetching = AsyncMock()
|
||||
|
||||
radio_manager = MagicMock()
|
||||
radio_manager.meshcore = mc
|
||||
radio_manager._setup_lock = None
|
||||
radio_manager._setup_in_progress = False
|
||||
radio_manager._setup_complete = False
|
||||
radio_manager.device_info_loaded = False
|
||||
radio_manager.max_contacts = None
|
||||
radio_manager.device_model = None
|
||||
radio_manager.firmware_build = None
|
||||
radio_manager.firmware_version = None
|
||||
radio_manager.max_channels = 40
|
||||
radio_manager.path_hash_mode = 0
|
||||
radio_manager.path_hash_mode_supported = False
|
||||
radio_manager._acquire_operation_lock = AsyncMock()
|
||||
radio_manager._release_operation_lock = MagicMock()
|
||||
|
||||
with (
|
||||
patch("app.event_handlers.register_event_handlers"),
|
||||
patch("app.keystore.export_and_store_private_key", new=AsyncMock()),
|
||||
patch("app.radio_sync.sync_radio_time", new=AsyncMock()),
|
||||
patch(
|
||||
"app.repository.AppSettingsRepository.get",
|
||||
new=AsyncMock(return_value=MagicMock(flood_scope=None)),
|
||||
),
|
||||
patch("app.radio_sync.sync_and_offload_all", new=AsyncMock(return_value={"synced": 0})),
|
||||
patch("app.radio_sync.send_advertisement", new=AsyncMock(return_value=False)),
|
||||
patch("app.radio_sync.drain_pending_messages", new=AsyncMock(return_value=0)),
|
||||
patch("app.radio_sync.start_periodic_sync"),
|
||||
patch("app.radio_sync.start_periodic_advert"),
|
||||
patch("app.radio_sync.start_message_polling"),
|
||||
):
|
||||
await run_post_connect_setup(radio_manager)
|
||||
|
||||
assert radio_manager.device_info_loaded is True
|
||||
assert radio_manager.max_contacts == 350
|
||||
assert radio_manager.max_channels == 64
|
||||
assert radio_manager.device_model == "T-Echo"
|
||||
assert radio_manager.firmware_build == "2025-02-01"
|
||||
assert radio_manager.firmware_version == "1.2.3"
|
||||
assert radio_manager.path_hash_mode == 2
|
||||
assert radio_manager.path_hash_mode_supported is True
|
||||
|
||||
@@ -41,6 +41,11 @@ class TestWebSocketEndpoint:
|
||||
mock_ws_rm.connection_info = "Serial: /dev/ttyUSB0"
|
||||
mock_health_rm.is_connected = True
|
||||
mock_health_rm.connection_info = "Serial: /dev/ttyUSB0"
|
||||
mock_health_rm.is_setup_in_progress = False
|
||||
mock_health_rm.is_setup_complete = True
|
||||
mock_health_rm.connection_desired = True
|
||||
mock_health_rm.is_reconnecting = False
|
||||
mock_health_rm.device_info_loaded = False
|
||||
mock_repo.get_oldest_undecrypted = AsyncMock(return_value=None)
|
||||
mock_settings.database_path = "/tmp/test.db"
|
||||
mock_settings.disable_bots = False
|
||||
@@ -75,6 +80,11 @@ class TestWebSocketEndpoint:
|
||||
mock_ws_rm.connection_info = None
|
||||
mock_health_rm.is_connected = False
|
||||
mock_health_rm.connection_info = None
|
||||
mock_health_rm.is_setup_in_progress = False
|
||||
mock_health_rm.is_setup_complete = False
|
||||
mock_health_rm.connection_desired = True
|
||||
mock_health_rm.is_reconnecting = False
|
||||
mock_health_rm.device_info_loaded = False
|
||||
mock_repo.get_oldest_undecrypted = AsyncMock(return_value=None)
|
||||
mock_settings.database_path = "/tmp/test.db"
|
||||
mock_settings.disable_bots = False
|
||||
@@ -105,6 +115,11 @@ class TestWebSocketEndpoint:
|
||||
mock_ws_rm.connection_info = "TCP: 192.168.1.1:4000"
|
||||
mock_health_rm.is_connected = True
|
||||
mock_health_rm.connection_info = "TCP: 192.168.1.1:4000"
|
||||
mock_health_rm.is_setup_in_progress = False
|
||||
mock_health_rm.is_setup_complete = True
|
||||
mock_health_rm.connection_desired = True
|
||||
mock_health_rm.is_reconnecting = False
|
||||
mock_health_rm.device_info_loaded = False
|
||||
mock_repo.get_oldest_undecrypted = AsyncMock(return_value=None)
|
||||
mock_settings.database_path = "/tmp/test.db"
|
||||
mock_settings.disable_bots = False
|
||||
@@ -136,6 +151,11 @@ class TestWebSocketEndpoint:
|
||||
mock_ws_rm.connection_info = "Serial: /dev/ttyUSB0"
|
||||
mock_health_rm.is_connected = True
|
||||
mock_health_rm.connection_info = "Serial: /dev/ttyUSB0"
|
||||
mock_health_rm.is_setup_in_progress = False
|
||||
mock_health_rm.is_setup_complete = True
|
||||
mock_health_rm.connection_desired = True
|
||||
mock_health_rm.is_reconnecting = False
|
||||
mock_health_rm.device_info_loaded = False
|
||||
mock_repo.get_oldest_undecrypted = AsyncMock(return_value=None)
|
||||
mock_settings.database_path = "/tmp/test.db"
|
||||
mock_settings.disable_bots = False
|
||||
@@ -167,6 +187,11 @@ class TestWebSocketEndpoint:
|
||||
mock_ws_rm.connection_info = "Serial: /dev/ttyUSB0"
|
||||
mock_health_rm.is_connected = True
|
||||
mock_health_rm.connection_info = "Serial: /dev/ttyUSB0"
|
||||
mock_health_rm.is_setup_in_progress = False
|
||||
mock_health_rm.is_setup_complete = True
|
||||
mock_health_rm.connection_desired = True
|
||||
mock_health_rm.is_reconnecting = False
|
||||
mock_health_rm.device_info_loaded = False
|
||||
mock_repo.get_oldest_undecrypted = AsyncMock(return_value=None)
|
||||
mock_settings.database_path = "/tmp/test.db"
|
||||
mock_settings.disable_bots = False
|
||||
|
||||
Reference in New Issue
Block a user