mirror of
https://github.com/jkingsman/Remote-Terminal-for-MeshCore.git
synced 2026-07-01 23:41:27 +02:00
Make advert interval manual
This commit is contained in:
@@ -100,6 +100,13 @@ async def run_migrations(conn: aiosqlite.Connection) -> int:
|
||||
await set_version(conn, 9)
|
||||
applied += 1
|
||||
|
||||
# Migration 10: Add advert_interval column to app_settings
|
||||
if version < 10:
|
||||
logger.info("Applying migration 10: add advert_interval column")
|
||||
await _migrate_010_add_advert_interval(conn)
|
||||
await set_version(conn, 10)
|
||||
applied += 1
|
||||
|
||||
if applied > 0:
|
||||
logger.info(
|
||||
"Applied %d migration(s), schema now at version %d", applied, await get_version(conn)
|
||||
@@ -629,3 +636,21 @@ async def _migrate_009_create_app_settings_table(conn: aiosqlite.Connection) ->
|
||||
|
||||
await conn.commit()
|
||||
logger.debug("Created app_settings table with default values")
|
||||
|
||||
|
||||
async def _migrate_010_add_advert_interval(conn: aiosqlite.Connection) -> None:
|
||||
"""
|
||||
Add advert_interval column to app_settings table.
|
||||
|
||||
This enables configurable periodic advertisement interval (default 0 = disabled).
|
||||
"""
|
||||
try:
|
||||
await conn.execute("ALTER TABLE app_settings ADD COLUMN advert_interval INTEGER DEFAULT 0")
|
||||
logger.debug("Added advert_interval column to app_settings")
|
||||
except aiosqlite.OperationalError as e:
|
||||
if "duplicate column" in str(e).lower():
|
||||
logger.debug("advert_interval column already exists, skipping")
|
||||
else:
|
||||
raise
|
||||
|
||||
await conn.commit()
|
||||
|
||||
@@ -255,3 +255,7 @@ class AppSettings(BaseModel):
|
||||
default=False,
|
||||
description="Whether preferences have been migrated from localStorage",
|
||||
)
|
||||
advert_interval: int = Field(
|
||||
default=0,
|
||||
description="Periodic advertisement interval in seconds (0 = disabled)",
|
||||
)
|
||||
|
||||
+45
-12
@@ -32,8 +32,9 @@ MESSAGE_POLL_INTERVAL = 5
|
||||
# Periodic advertisement task handle
|
||||
_advert_task: asyncio.Task | None = None
|
||||
|
||||
# Advertisement interval in seconds (1 hour)
|
||||
ADVERT_INTERVAL = 3600
|
||||
# Default check interval when periodic advertising is disabled (seconds)
|
||||
# We still need to periodically check if it's been enabled
|
||||
ADVERT_CHECK_INTERVAL = 60
|
||||
|
||||
# Counter to pause polling during repeater operations (supports nested pauses)
|
||||
_polling_pause_count: int = 0
|
||||
@@ -358,31 +359,63 @@ async def send_advertisement() -> bool:
|
||||
|
||||
|
||||
async def _periodic_advert_loop():
|
||||
"""Background task that periodically sends advertisements."""
|
||||
"""Background task that periodically sends advertisements.
|
||||
|
||||
Reads the interval from app_settings on each iteration, allowing
|
||||
dynamic configuration changes without restarting the task.
|
||||
If interval is 0, advertising is disabled but the task continues
|
||||
running to detect when it's re-enabled.
|
||||
"""
|
||||
from app.repository import AppSettingsRepository
|
||||
|
||||
last_advert_time = 0.0
|
||||
|
||||
while True:
|
||||
try:
|
||||
await asyncio.sleep(ADVERT_INTERVAL)
|
||||
# Get current interval setting
|
||||
settings = await AppSettingsRepository.get()
|
||||
interval = settings.advert_interval
|
||||
|
||||
if radio_manager.is_connected:
|
||||
await send_advertisement()
|
||||
if interval <= 0:
|
||||
# Advertising disabled - check again later
|
||||
await asyncio.sleep(ADVERT_CHECK_INTERVAL)
|
||||
continue
|
||||
|
||||
# Check if enough time has passed since last advertisement
|
||||
now = asyncio.get_running_loop().time()
|
||||
time_since_last = now - last_advert_time
|
||||
|
||||
if time_since_last >= interval and radio_manager.is_connected:
|
||||
if await send_advertisement():
|
||||
last_advert_time = now
|
||||
elif time_since_last < interval:
|
||||
# Sleep until next advertisement is due
|
||||
sleep_time = min(interval - time_since_last, ADVERT_CHECK_INTERVAL)
|
||||
await asyncio.sleep(sleep_time)
|
||||
continue
|
||||
|
||||
# Sleep for the configured interval
|
||||
await asyncio.sleep(interval)
|
||||
|
||||
except asyncio.CancelledError:
|
||||
logger.info("Periodic advertisement task cancelled")
|
||||
break
|
||||
except Exception as e:
|
||||
logger.error("Error in periodic advertisement loop: %s", e)
|
||||
# Sleep a bit before retrying on error
|
||||
await asyncio.sleep(ADVERT_CHECK_INTERVAL)
|
||||
|
||||
|
||||
def start_periodic_advert():
|
||||
"""Start the periodic advertisement background task."""
|
||||
"""Start the periodic advertisement background task.
|
||||
|
||||
The task reads interval from app_settings dynamically, so it will
|
||||
adapt to configuration changes without restart.
|
||||
"""
|
||||
global _advert_task
|
||||
if _advert_task is None or _advert_task.done():
|
||||
_advert_task = asyncio.create_task(_periodic_advert_loop())
|
||||
logger.info(
|
||||
"Started periodic advertisement (interval: %ds / %d min)",
|
||||
ADVERT_INTERVAL,
|
||||
ADVERT_INTERVAL // 60,
|
||||
)
|
||||
logger.info("Started periodic advertisement task (interval configured in settings)")
|
||||
|
||||
|
||||
async def stop_periodic_advert():
|
||||
|
||||
+8
-1
@@ -717,7 +717,8 @@ class AppSettingsRepository:
|
||||
cursor = await db.conn.execute(
|
||||
"""
|
||||
SELECT max_radio_contacts, favorites, auto_decrypt_dm_on_advert,
|
||||
sidebar_sort_order, last_message_times, preferences_migrated
|
||||
sidebar_sort_order, last_message_times, preferences_migrated,
|
||||
advert_interval
|
||||
FROM app_settings WHERE id = 1
|
||||
"""
|
||||
)
|
||||
@@ -765,6 +766,7 @@ class AppSettingsRepository:
|
||||
sidebar_sort_order=sort_order,
|
||||
last_message_times=last_message_times,
|
||||
preferences_migrated=bool(row["preferences_migrated"]),
|
||||
advert_interval=row["advert_interval"] or 0,
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
@@ -775,6 +777,7 @@ class AppSettingsRepository:
|
||||
sidebar_sort_order: str | None = None,
|
||||
last_message_times: dict[str, int] | None = None,
|
||||
preferences_migrated: bool | None = None,
|
||||
advert_interval: int | None = None,
|
||||
) -> AppSettings:
|
||||
"""Update app settings. Only provided fields are updated."""
|
||||
updates = []
|
||||
@@ -805,6 +808,10 @@ class AppSettingsRepository:
|
||||
updates.append("preferences_migrated = ?")
|
||||
params.append(1 if preferences_migrated else 0)
|
||||
|
||||
if advert_interval is not None:
|
||||
updates.append("advert_interval = ?")
|
||||
params.append(advert_interval)
|
||||
|
||||
if updates:
|
||||
query = f"UPDATE app_settings SET {', '.join(updates)} WHERE id = 1"
|
||||
await db.conn.execute(query, params)
|
||||
|
||||
@@ -26,6 +26,11 @@ class AppSettingsUpdate(BaseModel):
|
||||
default=None,
|
||||
description="Sidebar sort order: 'recent' or 'alpha'",
|
||||
)
|
||||
advert_interval: int | None = Field(
|
||||
default=None,
|
||||
ge=0,
|
||||
description="Periodic advertisement interval in seconds (0 = disabled)",
|
||||
)
|
||||
|
||||
|
||||
class FavoriteRequest(BaseModel):
|
||||
@@ -85,6 +90,10 @@ async def update_settings(update: AppSettingsUpdate) -> AppSettings:
|
||||
logger.info("Updating sidebar_sort_order to %s", update.sidebar_sort_order)
|
||||
kwargs["sidebar_sort_order"] = update.sidebar_sort_order
|
||||
|
||||
if update.advert_interval is not None:
|
||||
logger.info("Updating advert_interval to %d", update.advert_interval)
|
||||
kwargs["advert_interval"] = update.advert_interval
|
||||
|
||||
if kwargs:
|
||||
return await AppSettingsRepository.update(**kwargs)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user