mirror of
https://github.com/jkingsman/Remote-Terminal-for-MeshCore.git
synced 2026-03-28 17:43:05 +01:00
Correct yet MORE instances of not using a well sourced MC object
This commit is contained in:
15
app/radio.py
15
app/radio.py
@@ -247,23 +247,24 @@ class RadioManager:
|
||||
if not self._meshcore:
|
||||
return
|
||||
self._setup_in_progress = True
|
||||
mc = self._meshcore
|
||||
try:
|
||||
register_event_handlers(self._meshcore)
|
||||
await export_and_store_private_key(self._meshcore)
|
||||
register_event_handlers(mc)
|
||||
await export_and_store_private_key(mc)
|
||||
|
||||
# Sync radio clock with system time
|
||||
await sync_radio_time()
|
||||
await sync_radio_time(mc)
|
||||
|
||||
# Sync contacts/channels from radio to DB and clear radio
|
||||
logger.info("Syncing and offloading radio data...")
|
||||
result = await sync_and_offload_all()
|
||||
result = await sync_and_offload_all(mc)
|
||||
logger.info("Sync complete: %s", result)
|
||||
|
||||
# Start periodic sync (idempotent)
|
||||
start_periodic_sync()
|
||||
|
||||
# Send advertisement to announce our presence (if enabled and not throttled)
|
||||
if await send_advertisement():
|
||||
if await send_advertisement(mc):
|
||||
logger.info("Advertisement sent")
|
||||
else:
|
||||
logger.debug("Advertisement skipped (disabled or throttled)")
|
||||
@@ -274,11 +275,11 @@ class RadioManager:
|
||||
# Drain any messages that were queued before we connected.
|
||||
# This must happen BEFORE starting auto-fetch, otherwise both
|
||||
# compete on get_msg() with interleaved radio I/O.
|
||||
drained = await drain_pending_messages()
|
||||
drained = await drain_pending_messages(mc)
|
||||
if drained > 0:
|
||||
logger.info("Drained %d pending message(s)", drained)
|
||||
|
||||
await self._meshcore.start_auto_message_fetching()
|
||||
await mc.start_auto_message_fetching()
|
||||
logger.info("Auto message fetching started")
|
||||
|
||||
# Start periodic message polling as fallback (idempotent)
|
||||
|
||||
@@ -14,7 +14,7 @@ import logging
|
||||
import time
|
||||
from contextlib import asynccontextmanager
|
||||
|
||||
from meshcore import EventType
|
||||
from meshcore import EventType, MeshCore
|
||||
|
||||
from app.event_handlers import cleanup_expired_acks
|
||||
from app.models import Contact
|
||||
@@ -77,16 +77,11 @@ _sync_task: asyncio.Task | None = None
|
||||
SYNC_INTERVAL = 300
|
||||
|
||||
|
||||
async def sync_and_offload_contacts() -> dict:
|
||||
async def sync_and_offload_contacts(mc: MeshCore) -> dict:
|
||||
"""
|
||||
Sync contacts from radio to database, then remove them from radio.
|
||||
Returns counts of synced and removed contacts.
|
||||
"""
|
||||
if not radio_manager.is_connected or radio_manager.meshcore is None:
|
||||
logger.warning("Cannot sync contacts: radio not connected")
|
||||
return {"synced": 0, "removed": 0, "error": "Radio not connected"}
|
||||
|
||||
mc = radio_manager.meshcore
|
||||
synced = 0
|
||||
removed = 0
|
||||
|
||||
@@ -137,16 +132,11 @@ async def sync_and_offload_contacts() -> dict:
|
||||
return {"synced": synced, "removed": removed}
|
||||
|
||||
|
||||
async def sync_and_offload_channels() -> dict:
|
||||
async def sync_and_offload_channels(mc: MeshCore) -> dict:
|
||||
"""
|
||||
Sync channels from radio to database, then clear them from radio.
|
||||
Returns counts of synced and cleared channels.
|
||||
"""
|
||||
if not radio_manager.is_connected or radio_manager.meshcore is None:
|
||||
logger.warning("Cannot sync channels: radio not connected")
|
||||
return {"synced": 0, "cleared": 0, "error": "Radio not connected"}
|
||||
|
||||
mc = radio_manager.meshcore
|
||||
synced = 0
|
||||
cleared = 0
|
||||
|
||||
@@ -227,12 +217,12 @@ async def ensure_default_channels() -> None:
|
||||
)
|
||||
|
||||
|
||||
async def sync_and_offload_all() -> dict:
|
||||
async def sync_and_offload_all(mc: MeshCore) -> dict:
|
||||
"""Sync and offload both contacts and channels, then ensure defaults exist."""
|
||||
logger.info("Starting full radio sync and offload")
|
||||
|
||||
contacts_result = await sync_and_offload_contacts()
|
||||
channels_result = await sync_and_offload_channels()
|
||||
contacts_result = await sync_and_offload_contacts(mc)
|
||||
channels_result = await sync_and_offload_channels(mc)
|
||||
|
||||
# Ensure default channels exist
|
||||
await ensure_default_channels()
|
||||
@@ -243,17 +233,13 @@ async def sync_and_offload_all() -> dict:
|
||||
}
|
||||
|
||||
|
||||
async def drain_pending_messages() -> int:
|
||||
async def drain_pending_messages(mc: MeshCore) -> int:
|
||||
"""
|
||||
Drain all pending messages from the radio.
|
||||
|
||||
Calls get_msg() repeatedly until NO_MORE_MSGS is received.
|
||||
Returns the count of messages retrieved.
|
||||
"""
|
||||
if not radio_manager.is_connected or radio_manager.meshcore is None:
|
||||
return 0
|
||||
|
||||
mc = radio_manager.meshcore
|
||||
count = 0
|
||||
max_iterations = 100 # Safety limit
|
||||
|
||||
@@ -281,7 +267,7 @@ async def drain_pending_messages() -> int:
|
||||
return count
|
||||
|
||||
|
||||
async def poll_for_messages() -> int:
|
||||
async def poll_for_messages(mc: MeshCore) -> int:
|
||||
"""
|
||||
Poll the radio for any pending messages (single pass).
|
||||
|
||||
@@ -290,10 +276,6 @@ async def poll_for_messages() -> int:
|
||||
|
||||
Returns the count of messages retrieved.
|
||||
"""
|
||||
if not radio_manager.is_connected or radio_manager.meshcore is None:
|
||||
return 0
|
||||
|
||||
mc = radio_manager.meshcore
|
||||
count = 0
|
||||
|
||||
try:
|
||||
@@ -308,7 +290,7 @@ async def poll_for_messages() -> int:
|
||||
elif result.type in (EventType.CONTACT_MSG_RECV, EventType.CHANNEL_MSG_RECV):
|
||||
count += 1
|
||||
# If we got a message, there might be more - drain them
|
||||
count += await drain_pending_messages()
|
||||
count += await drain_pending_messages(mc)
|
||||
|
||||
except asyncio.TimeoutError:
|
||||
pass
|
||||
@@ -329,16 +311,14 @@ async def _message_poll_loop():
|
||||
cleanup_expired_acks()
|
||||
|
||||
if radio_manager.is_connected and not is_polling_paused():
|
||||
mc = radio_manager.meshcore
|
||||
if mc is not None:
|
||||
try:
|
||||
async with radio_manager.radio_operation(
|
||||
"message_poll_loop",
|
||||
blocking=False,
|
||||
):
|
||||
await poll_for_messages()
|
||||
except RadioOperationBusyError:
|
||||
logger.debug("Skipping message poll: radio busy")
|
||||
try:
|
||||
async with radio_manager.radio_operation(
|
||||
"message_poll_loop",
|
||||
blocking=False,
|
||||
) as mc:
|
||||
await poll_for_messages(mc)
|
||||
except RadioOperationBusyError:
|
||||
logger.debug("Skipping message poll: radio busy")
|
||||
|
||||
except asyncio.CancelledError:
|
||||
break
|
||||
@@ -367,21 +347,18 @@ async def stop_message_polling():
|
||||
logger.info("Stopped periodic message polling")
|
||||
|
||||
|
||||
async def send_advertisement(force: bool = False) -> bool:
|
||||
async def send_advertisement(mc: MeshCore, *, force: bool = False) -> bool:
|
||||
"""Send an advertisement to announce presence on the mesh.
|
||||
|
||||
Respects the configured advert_interval - won't send if not enough time
|
||||
has elapsed since the last advertisement, unless force=True.
|
||||
|
||||
Args:
|
||||
mc: The MeshCore instance to use for the advertisement.
|
||||
force: If True, send immediately regardless of interval.
|
||||
|
||||
Returns True if successful, False otherwise (including if throttled).
|
||||
"""
|
||||
if not radio_manager.is_connected or radio_manager.meshcore is None:
|
||||
logger.debug("Cannot send advertisement: radio not connected")
|
||||
return False
|
||||
|
||||
# Check if enough time has elapsed (unless forced)
|
||||
if not force:
|
||||
settings = await AppSettingsRepository.get()
|
||||
@@ -410,7 +387,7 @@ async def send_advertisement(force: bool = False) -> bool:
|
||||
return False
|
||||
|
||||
try:
|
||||
result = await radio_manager.meshcore.commands.send_advert(flood=True)
|
||||
result = await mc.commands.send_advert(flood=True)
|
||||
if result.type == EventType.OK:
|
||||
# Update last_advert_time in database
|
||||
now = int(time.time())
|
||||
@@ -437,16 +414,14 @@ async def _periodic_advert_loop():
|
||||
# Try to send - send_advertisement() handles all checks
|
||||
# (disabled, throttled, not connected)
|
||||
if radio_manager.is_connected:
|
||||
mc = radio_manager.meshcore
|
||||
if mc is not None:
|
||||
try:
|
||||
async with radio_manager.radio_operation(
|
||||
"periodic_advertisement",
|
||||
blocking=False,
|
||||
):
|
||||
await send_advertisement()
|
||||
except RadioOperationBusyError:
|
||||
logger.debug("Skipping periodic advertisement: radio busy")
|
||||
try:
|
||||
async with radio_manager.radio_operation(
|
||||
"periodic_advertisement",
|
||||
blocking=False,
|
||||
) as mc:
|
||||
await send_advertisement(mc)
|
||||
except RadioOperationBusyError:
|
||||
logger.debug("Skipping periodic advertisement: radio busy")
|
||||
|
||||
# Sleep before next check
|
||||
await asyncio.sleep(ADVERT_CHECK_INTERVAL)
|
||||
@@ -484,16 +459,11 @@ async def stop_periodic_advert():
|
||||
logger.info("Stopped periodic advertisement")
|
||||
|
||||
|
||||
async def sync_radio_time() -> bool:
|
||||
async def sync_radio_time(mc: MeshCore) -> bool:
|
||||
"""Sync the radio's clock with the system time.
|
||||
|
||||
Returns True if successful, False otherwise.
|
||||
"""
|
||||
mc = radio_manager.meshcore
|
||||
if not mc:
|
||||
logger.debug("Cannot sync time: radio not connected")
|
||||
return False
|
||||
|
||||
try:
|
||||
now = int(time.time())
|
||||
await mc.commands.set_time(now)
|
||||
@@ -509,18 +479,17 @@ async def _periodic_sync_loop():
|
||||
while True:
|
||||
try:
|
||||
await asyncio.sleep(SYNC_INTERVAL)
|
||||
mc = radio_manager.meshcore
|
||||
if mc is None:
|
||||
if not radio_manager.is_connected:
|
||||
continue
|
||||
|
||||
try:
|
||||
async with radio_manager.radio_operation(
|
||||
"periodic_sync",
|
||||
blocking=False,
|
||||
):
|
||||
) as mc:
|
||||
logger.debug("Running periodic radio sync")
|
||||
await sync_and_offload_all()
|
||||
await sync_radio_time()
|
||||
await sync_and_offload_all(mc)
|
||||
await sync_radio_time(mc)
|
||||
except RadioOperationBusyError:
|
||||
logger.debug("Skipping periodic sync: radio busy")
|
||||
except asyncio.CancelledError:
|
||||
|
||||
@@ -104,7 +104,7 @@ async def update_radio_config(update: RadioConfigUpdate) -> RadioConfigResponse:
|
||||
)
|
||||
|
||||
# Sync time with system clock
|
||||
await sync_radio_time()
|
||||
await sync_radio_time(mc)
|
||||
|
||||
# Re-fetch self_info so the response reflects the changes we just made.
|
||||
# Commands like set_name() write to flash but don't update the cached
|
||||
@@ -168,8 +168,8 @@ async def send_advertisement() -> dict:
|
||||
require_connected()
|
||||
|
||||
logger.info("Sending flood advertisement")
|
||||
async with radio_manager.radio_operation("manual_advertisement"):
|
||||
success = await do_send_advertisement(force=True)
|
||||
async with radio_manager.radio_operation("manual_advertisement") as mc:
|
||||
success = await do_send_advertisement(mc, force=True)
|
||||
|
||||
if not success:
|
||||
raise HTTPException(status_code=500, detail="Failed to send advertisement")
|
||||
|
||||
@@ -452,7 +452,7 @@ class TestPostConnectSetupOrdering:
|
||||
|
||||
call_order = []
|
||||
|
||||
async def mock_drain():
|
||||
async def mock_drain(mc):
|
||||
call_order.append("drain")
|
||||
return 0
|
||||
|
||||
@@ -494,7 +494,7 @@ class TestPostConnectSetupOrdering:
|
||||
|
||||
observed_during = None
|
||||
|
||||
async def mock_drain():
|
||||
async def mock_drain(mc):
|
||||
nonlocal observed_during
|
||||
observed_during = rm.is_setup_in_progress
|
||||
return 0
|
||||
|
||||
@@ -237,7 +237,7 @@ class TestAdvertise:
|
||||
active = 0
|
||||
max_active = 0
|
||||
|
||||
async def fake_send(*, force: bool):
|
||||
async def fake_send(mc, *, force: bool):
|
||||
nonlocal active, max_active
|
||||
assert force is True
|
||||
active += 1
|
||||
|
||||
@@ -188,31 +188,21 @@ class TestPollingPause:
|
||||
class TestSyncRadioTime:
|
||||
"""Test the radio time sync function."""
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_returns_false_when_not_connected(self):
|
||||
"""sync_radio_time returns False when radio is not connected."""
|
||||
with patch("app.radio_sync.radio_manager") as mock_manager:
|
||||
mock_manager.meshcore = None
|
||||
result = await sync_radio_time()
|
||||
assert result is False
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_returns_true_on_success(self):
|
||||
"""sync_radio_time returns True when time is set successfully."""
|
||||
mock_mc = MagicMock()
|
||||
mock_mc.commands.set_time = AsyncMock()
|
||||
|
||||
with patch("app.radio_sync.radio_manager") as mock_manager:
|
||||
mock_manager.meshcore = mock_mc
|
||||
result = await sync_radio_time()
|
||||
result = await sync_radio_time(mock_mc)
|
||||
|
||||
assert result is True
|
||||
mock_mc.commands.set_time.assert_called_once()
|
||||
# Verify timestamp is reasonable (within last few seconds)
|
||||
call_args = mock_mc.commands.set_time.call_args[0][0]
|
||||
import time
|
||||
assert result is True
|
||||
mock_mc.commands.set_time.assert_called_once()
|
||||
# Verify timestamp is reasonable (within last few seconds)
|
||||
call_args = mock_mc.commands.set_time.call_args[0][0]
|
||||
import time
|
||||
|
||||
assert abs(call_args - int(time.time())) < 5
|
||||
assert abs(call_args - int(time.time())) < 5
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_returns_false_on_exception(self):
|
||||
@@ -220,11 +210,9 @@ class TestSyncRadioTime:
|
||||
mock_mc = MagicMock()
|
||||
mock_mc.commands.set_time = AsyncMock(side_effect=Exception("Radio error"))
|
||||
|
||||
with patch("app.radio_sync.radio_manager") as mock_manager:
|
||||
mock_manager.meshcore = mock_mc
|
||||
result = await sync_radio_time()
|
||||
result = await sync_radio_time(mock_mc)
|
||||
|
||||
assert result is False
|
||||
assert result is False
|
||||
|
||||
|
||||
class TestSyncRecentContactsToRadio:
|
||||
@@ -429,21 +417,6 @@ class TestSyncRecentContactsToRadio:
|
||||
class TestSyncAndOffloadContacts:
|
||||
"""Test sync_and_offload_contacts: pull contacts from radio, save to DB, remove from radio."""
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_returns_error_when_not_connected(self):
|
||||
"""Returns error dict when radio is not connected."""
|
||||
from app.radio_sync import sync_and_offload_contacts
|
||||
|
||||
with patch("app.radio_sync.radio_manager") as mock_rm:
|
||||
mock_rm.is_connected = False
|
||||
mock_rm.meshcore = None
|
||||
|
||||
result = await sync_and_offload_contacts()
|
||||
|
||||
assert result["synced"] == 0
|
||||
assert result["removed"] == 0
|
||||
assert "error" in result
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_syncs_and_removes_contacts(self, test_db):
|
||||
"""Contacts are upserted to DB and removed from radio."""
|
||||
@@ -465,11 +438,7 @@ class TestSyncAndOffloadContacts:
|
||||
mock_mc.commands.get_contacts = AsyncMock(return_value=mock_get_result)
|
||||
mock_mc.commands.remove_contact = AsyncMock(return_value=mock_remove_result)
|
||||
|
||||
with patch("app.radio_sync.radio_manager") as mock_rm:
|
||||
mock_rm.is_connected = True
|
||||
mock_rm.meshcore = mock_mc
|
||||
|
||||
result = await sync_and_offload_contacts()
|
||||
result = await sync_and_offload_contacts(mock_mc)
|
||||
|
||||
assert result["synced"] == 2
|
||||
assert result["removed"] == 2
|
||||
@@ -509,11 +478,7 @@ class TestSyncAndOffloadContacts:
|
||||
mock_mc.commands.get_contacts = AsyncMock(return_value=mock_get_result)
|
||||
mock_mc.commands.remove_contact = AsyncMock(return_value=mock_remove_result)
|
||||
|
||||
with patch("app.radio_sync.radio_manager") as mock_rm:
|
||||
mock_rm.is_connected = True
|
||||
mock_rm.meshcore = mock_mc
|
||||
|
||||
await sync_and_offload_contacts()
|
||||
await sync_and_offload_contacts(mock_mc)
|
||||
|
||||
# Verify the prefix message was claimed (promoted to full key)
|
||||
messages = await MessageRepository.get_all(conversation_key=KEY_A)
|
||||
@@ -546,11 +511,7 @@ class TestSyncAndOffloadContacts:
|
||||
# First remove fails, second succeeds
|
||||
mock_mc.commands.remove_contact = AsyncMock(side_effect=[mock_fail_result, mock_ok_result])
|
||||
|
||||
with patch("app.radio_sync.radio_manager") as mock_rm:
|
||||
mock_rm.is_connected = True
|
||||
mock_rm.meshcore = mock_mc
|
||||
|
||||
result = await sync_and_offload_contacts()
|
||||
result = await sync_and_offload_contacts(mock_mc)
|
||||
|
||||
# Both contacts synced, but only one removed successfully
|
||||
assert result["synced"] == 2
|
||||
@@ -571,11 +532,7 @@ class TestSyncAndOffloadContacts:
|
||||
mock_mc.commands.get_contacts = AsyncMock(return_value=mock_get_result)
|
||||
mock_mc.commands.remove_contact = AsyncMock(side_effect=Exception("Timeout"))
|
||||
|
||||
with patch("app.radio_sync.radio_manager") as mock_rm:
|
||||
mock_rm.is_connected = True
|
||||
mock_rm.meshcore = mock_mc
|
||||
|
||||
result = await sync_and_offload_contacts()
|
||||
result = await sync_and_offload_contacts(mock_mc)
|
||||
|
||||
assert result["synced"] == 1
|
||||
assert result["removed"] == 0
|
||||
@@ -592,11 +549,7 @@ class TestSyncAndOffloadContacts:
|
||||
mock_mc = MagicMock()
|
||||
mock_mc.commands.get_contacts = AsyncMock(return_value=mock_error_result)
|
||||
|
||||
with patch("app.radio_sync.radio_manager") as mock_rm:
|
||||
mock_rm.is_connected = True
|
||||
mock_rm.meshcore = mock_mc
|
||||
|
||||
result = await sync_and_offload_contacts()
|
||||
result = await sync_and_offload_contacts(mock_mc)
|
||||
|
||||
assert result["synced"] == 0
|
||||
assert result["removed"] == 0
|
||||
@@ -620,11 +573,7 @@ class TestSyncAndOffloadContacts:
|
||||
mock_mc.commands.get_contacts = AsyncMock(return_value=mock_get_result)
|
||||
mock_mc.commands.remove_contact = AsyncMock(return_value=mock_remove_result)
|
||||
|
||||
with patch("app.radio_sync.radio_manager") as mock_rm:
|
||||
mock_rm.is_connected = True
|
||||
mock_rm.meshcore = mock_mc
|
||||
|
||||
await sync_and_offload_contacts()
|
||||
await sync_and_offload_contacts(mock_mc)
|
||||
|
||||
contact = await ContactRepository.get_by_key(KEY_A)
|
||||
assert contact is not None
|
||||
@@ -634,21 +583,6 @@ class TestSyncAndOffloadContacts:
|
||||
class TestSyncAndOffloadChannels:
|
||||
"""Test sync_and_offload_channels: pull channels from radio, save to DB, clear from radio."""
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_returns_error_when_not_connected(self):
|
||||
"""Returns error dict when radio is not connected."""
|
||||
from app.radio_sync import sync_and_offload_channels
|
||||
|
||||
with patch("app.radio_sync.radio_manager") as mock_rm:
|
||||
mock_rm.is_connected = False
|
||||
mock_rm.meshcore = None
|
||||
|
||||
result = await sync_and_offload_channels()
|
||||
|
||||
assert result["synced"] == 0
|
||||
assert result["cleared"] == 0
|
||||
assert "error" in result
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_syncs_valid_channel_and_clears(self, test_db):
|
||||
"""Valid channel is upserted to DB and cleared from radio."""
|
||||
@@ -672,11 +606,7 @@ class TestSyncAndOffloadChannels:
|
||||
clear_result.type = EventType.OK
|
||||
mock_mc.commands.set_channel = AsyncMock(return_value=clear_result)
|
||||
|
||||
with patch("app.radio_sync.radio_manager") as mock_rm:
|
||||
mock_rm.is_connected = True
|
||||
mock_rm.meshcore = mock_mc
|
||||
|
||||
result = await sync_and_offload_channels()
|
||||
result = await sync_and_offload_channels(mock_mc)
|
||||
|
||||
assert result["synced"] == 1
|
||||
assert result["cleared"] == 1
|
||||
@@ -708,11 +638,7 @@ class TestSyncAndOffloadChannels:
|
||||
side_effect=[empty_name_result] + [other_result] * 39
|
||||
)
|
||||
|
||||
with patch("app.radio_sync.radio_manager") as mock_rm:
|
||||
mock_rm.is_connected = True
|
||||
mock_rm.meshcore = mock_mc
|
||||
|
||||
result = await sync_and_offload_channels()
|
||||
result = await sync_and_offload_channels(mock_mc)
|
||||
|
||||
assert result["synced"] == 0
|
||||
assert result["cleared"] == 0
|
||||
@@ -737,11 +663,7 @@ class TestSyncAndOffloadChannels:
|
||||
side_effect=[zero_key_result] + [other_result] * 39
|
||||
)
|
||||
|
||||
with patch("app.radio_sync.radio_manager") as mock_rm:
|
||||
mock_rm.is_connected = True
|
||||
mock_rm.meshcore = mock_mc
|
||||
|
||||
result = await sync_and_offload_channels()
|
||||
result = await sync_and_offload_channels(mock_mc)
|
||||
|
||||
assert result["synced"] == 0
|
||||
|
||||
@@ -767,11 +689,7 @@ class TestSyncAndOffloadChannels:
|
||||
clear_result.type = EventType.OK
|
||||
mock_mc.commands.set_channel = AsyncMock(return_value=clear_result)
|
||||
|
||||
with patch("app.radio_sync.radio_manager") as mock_rm:
|
||||
mock_rm.is_connected = True
|
||||
mock_rm.meshcore = mock_mc
|
||||
|
||||
await sync_and_offload_channels()
|
||||
await sync_and_offload_channels(mock_mc)
|
||||
|
||||
channel = await ChannelRepository.get_by_key("8B3387E9C5CDEA6AC9E5EDBAA115CD72")
|
||||
assert channel is not None
|
||||
@@ -799,11 +717,7 @@ class TestSyncAndOffloadChannels:
|
||||
clear_result.type = EventType.OK
|
||||
mock_mc.commands.set_channel = AsyncMock(return_value=clear_result)
|
||||
|
||||
with patch("app.radio_sync.radio_manager") as mock_rm:
|
||||
mock_rm.is_connected = True
|
||||
mock_rm.meshcore = mock_mc
|
||||
|
||||
await sync_and_offload_channels()
|
||||
await sync_and_offload_channels(mock_mc)
|
||||
|
||||
mock_mc.commands.set_channel.assert_called_once_with(
|
||||
channel_idx=0,
|
||||
@@ -841,11 +755,7 @@ class TestSyncAndOffloadChannels:
|
||||
|
||||
mock_mc.commands.set_channel = AsyncMock(side_effect=[fail_result, ok_result])
|
||||
|
||||
with patch("app.radio_sync.radio_manager") as mock_rm:
|
||||
mock_rm.is_connected = True
|
||||
mock_rm.meshcore = mock_mc
|
||||
|
||||
result = await sync_and_offload_channels()
|
||||
result = await sync_and_offload_channels(mock_mc)
|
||||
|
||||
assert result["synced"] == 2
|
||||
assert result["cleared"] == 1
|
||||
@@ -861,11 +771,7 @@ class TestSyncAndOffloadChannels:
|
||||
mock_mc = MagicMock()
|
||||
mock_mc.commands.get_channel = AsyncMock(return_value=empty_result)
|
||||
|
||||
with patch("app.radio_sync.radio_manager") as mock_rm:
|
||||
mock_rm.is_connected = True
|
||||
mock_rm.meshcore = mock_mc
|
||||
|
||||
result = await sync_and_offload_channels()
|
||||
result = await sync_and_offload_channels(mock_mc)
|
||||
|
||||
assert mock_mc.commands.get_channel.call_count == 40
|
||||
assert result["synced"] == 0
|
||||
|
||||
Reference in New Issue
Block a user