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>
3.9 KiB
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
- Dawn – window around sunrise (
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 applylabel– 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:
context.sse_clients.load() == 0— no users connected- Active rig has a non-Disabled scheduler config
- Current UTC time matches a scheduled window or grayline period
- If the matching bookmark differs from
last_applied, sendSetFreq+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 (5–60 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).