Files
trx-rs/SCHEDULER.md
T
sjg 6874055b1c [feat](trx-frontend-http): add Background Decoding Scheduler
Implements a scheduler that retunes the rig automatically when no SSE
clients are connected.  Two modes are supported:

- Grayline: tunes to per-period bookmarks (dawn/day/dusk/night) based on
  an inline NOAA solar algorithm given station lat/lon.
- Time Span: tunes to bookmarks within user-defined UTC windows; midnight-
  spanning intervals supported.

Backend:
- SchedulerStore (PickleDB, sch:{rig_id} keys) in scheduler.rs
- spawn_scheduler_task polls every 30 s, checks context.sse_clients == 0,
  sends SetFreq + SetMode via RigRequest with rig_id_override
- HTTP API: GET/PUT/DELETE /scheduler/{rig_id}, GET …/status
- sse_clients Arc<AtomicUsize> added to FrontendRuntimeContext and shared
  with the SSE counter in build_server (single source of truth)
- /scheduler/ added to Read auth routes (write requires Control)

Frontend:
- Scheduler tab (clock icon, 6th position) with Grayline/TimeSpan UI
- scheduler.js plugin: loads config + bookmarks, live status polling
  every 15 s, write controls hidden for Rx-role users
- CSS .sch-* component styles added to style.css
- SCHEDULER.md design document at repo root

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-10 23:20:42 +01:00

3.9 KiB
Raw Blame History

Background Decoding Scheduler

Overview

The Background Decoding Scheduler automatically retunes the rig to pre-configured bookmarks when no users are connected to the HTTP frontend. It runs as a background tokio task inside trx-frontend-http, polling every 30 seconds.

Modes

Disabled (default)

Scheduler is inactive. Rig is not touched automatically.

Grayline

Retunes around the solar terminator (day/night boundary).

The user provides:

  • Station latitude and longitude (decimal degrees)
  • Optional transition window width (minutes, default 20)
  • Bookmark IDs for four periods:
    • Dawn window around sunrise (sunrise ± window_min/2)
    • Day after dawn until dusk
    • Dusk window around sunset (sunset ± window_min/2)
    • Night after dusk until next dawn

Period precedence (most specific wins): Dawn > Dusk > Day > Night.

If no bookmark is assigned to a period, the rig is not retuned for that period.

Sunrise/sunset is computed inline using the NOAA simplified algorithm. Polar regions (midnight sun / polar night) fall back to Day/Night accordingly.

TimeSpan

Retunes according to a list of user-defined time windows (UTC).

Each entry specifies:

  • start_hhmm start of window (e.g. 600 = 06:00 UTC)
  • end_hhmm end of window (e.g. 700 = 07:00 UTC)
  • bookmark_id bookmark to apply
  • label optional human-readable description

Windows that span midnight (end_hhmm < start_hhmm) are supported. When multiple entries overlap, the first match (by list order) wins.

Storage

Configuration is stored in PickleDB at ~/.config/trx-rs/scheduler.db.

Keys: sch:{rig_id} → JSON SchedulerConfig.

HTTP API

All read endpoints are accessible at the Rx role level. Write endpoints require the Control role.

Method Path Description
GET /scheduler/{rig_id} Get scheduler config for a rig
PUT /scheduler/{rig_id} Save scheduler config (Control only)
DELETE /scheduler/{rig_id} Reset config to Disabled (Control only)
GET /scheduler/{rig_id}/status Get last-applied bookmark and next event

Activation logic

Every 30 seconds the scheduler task checks:

  1. context.sse_clients.load() == 0 — no users connected
  2. Active rig has a non-Disabled scheduler config
  3. Current UTC time matches a scheduled window or grayline period
  4. If the matching bookmark differs from last_applied, send SetFreq + SetMode

The scheduler does not revert changes when users reconnect. Bookmarks serve as a frequency map — the user can retune manually after connecting.

Data model (Rust)

pub enum SchedulerMode { Disabled, Grayline, TimeSpan }

pub struct GraylineConfig {
    pub lat: f64,
    pub lon: f64,
    pub transition_window_min: u32,
    pub day_bookmark_id: Option<String>,
    pub night_bookmark_id: Option<String>,
    pub dawn_bookmark_id: Option<String>,
    pub dusk_bookmark_id: Option<String>,
}

pub struct ScheduleEntry {
    pub id: String,
    pub start_hhmm: u32,
    pub end_hhmm: u32,
    pub bookmark_id: String,
    pub label: Option<String>,
}

pub struct SchedulerConfig {
    pub rig_id: String,
    pub mode: SchedulerMode,
    pub grayline: Option<GraylineConfig>,
    pub entries: Vec<ScheduleEntry>,
}

UI (Scheduler tab)

A dedicated sixth tab with a clock icon.

  • Rig selector: shows active rig (read-only).
  • Mode picker: Disabled / Grayline / TimeSpan radio buttons.
  • Grayline section (visible when mode = Grayline):
    • Lat/lon inputs
    • Transition window slider (560 min)
    • Four bookmark selectors (Dawn / Day / Dusk / Night)
  • TimeSpan section (visible when mode = TimeSpan):
    • Table of entries with Start, End, Bookmark, Label, Remove button
    • "Add Entry" row at the bottom
  • Status card: last applied bookmark name and timestamp.
  • Save button (Control only; form is read-only for Rx users).