================================================================================ SitRepNet Scheduler v1.0.0 — Program Overview Designed and developed by Stephen Clay McGehee, KN4AM Coding done using Claude Code AI See SitRepNet.com for more information ================================================================================ PURPOSE ------- SitRepNet Scheduler lets an unattended or lightly attended station keep monitoring its usual frequency — the primary frequency — in JS8Call or FLDIGI, while still catching bulletins and nets that happen on other frequencies at known times each week. At each scheduled time it switches the program to the bulletin's frequency, audio offset, and JS8Call speed or FLDIGI mode. When the window ends, it puts the program back exactly as it was just before the switch. The operator doesn't have to be there, and doesn't have to remember to change back. It is a companion to the other SitRepNet programs: SitRepMapper and JS8Spotter read and display the traffic that JS8Call receives, and the Scheduler makes sure JS8Call is on the right frequency to receive it. HOW IT WORKS ------------ The schedule is a list of entries. Each entry is one day of the week, a start time (UTC or local), a duration, an optional early start, and the settings to switch to. An entry repeats every week; for a net that meets on several days, there is one entry per day (Copy to Other Days makes them). The day is always the operator's local day, even when the time is given in UTC — that matches how nets announce themselves ("Monday night, 0200Z" is Monday evening in the US). The program works out each entry's actual dates and times from that rule, including daylight-saving changes, and shows the next few in the entry editor so they can be checked. When a window starts, the Scheduler: 1. Waits until the program isn't transmitting. 2. Reads the program's current settings — these are the primary settings — and saves them to disk (state.json) before changing anything. 3. Applies the entry's settings and reads them back to confirm they took. When the window ends, it waits again for any transmission to finish, puts the primary settings back, reads them back, and deletes state.json. If a second window starts while the first is still running, the Scheduler goes straight from one to the other and keeps the original primary settings — it never mistakes a bulletin frequency for the primary one. Because the primary settings are taken at switch time rather than entered anywhere, an operator who changes their monitoring frequency by hand doesn't need to tell the Scheduler. KEY FEATURES ------------ - Controls JS8Call (standard, and the JS8Call-improved fork) or FLDIGI — one at a time, chosen in Settings - Weekly schedule with UTC or local start times, local day of the week, optional early start (up to 2 hours), and duration (up to 24 hours) - JS8Call entries set frequency, offset and speed (Normal, Fast, Turbo, Slow); FLDIGI entries set frequency, offset and mode, with the mode list read from FLDIGI itself - Status panel: ON PRIMARY or ON SCHEDULE (with what it will return to), the program's current settings, the next switch with a countdown, and a local/UTC clock - Overlap warnings when an entry is saved or enabled, compared over the coming year so that UTC and local entries that collide only part of the year are caught. Two kinds: a full overlap (the later entry takes over at its start time) and an early-start overlap (the later entry doesn't start early) - Copy to Other Days: independent per-day copies, skipping days that already have the same entry - Copy Table: the schedule as aligned or tab-separated text, for pasting into a document or spreadsheet and printing - Return to Primary, Pause Scheduling, and Test Selected Entry Now (try an entry for a few minutes) - Activity pane and rotating log file, all times in UTC - Settings > Time Zone for computers whose clock is set to UTC (common on a Raspberry Pi) - Update check, the same as SitRepMapper's - Runs on Raspberry Pi, Linux and Windows with nothing to install beyond Python itself RELIABILITY ----------- The Scheduler changes a radio's frequency without anyone watching, so it is built to fail safe: - Never mid-transmission. It waits for the program to stop transmitting before any change (JS8Call: 8 seconds after the last frame, since JS8Call drops PTT between frames). At switch time it gives up after a set limit and skips the window; when returning to primary it goes ahead after the limit, since staying away is worse. - Survives restarts. The primary settings are on disk before the first change. If the Scheduler or the computer stops mid-window, the next start either stays on the window until it ends or returns to primary at once. If the settings can't be saved, it doesn't switch. - Checks its work. Every change is read back. A switch that only partly took (for example, the program was still starting) is retried while the window lasts; a failed return to primary is retried until it works. - Waits for the program. If JS8Call or FLDIGI isn't running, it warns a minute before a switch and keeps retrying, logging the first failure and then a summary every 10 minutes rather than flooding the log. When the program comes back, it waits 20 seconds for it to finish starting before changing anything. - Catches up after sleep. A window that started while the computer was asleep is joined if enough of it remains. - One copy at a time. A second copy refuses to start, so two Schedulers can't fight over the radio. - Protects the schedule. A schedule file that can't be read is never overwritten; damaged entries are skipped or disabled with a warning, and the original is kept as a backup. PROGRAM CONTROL --------------- JS8Call JS8Call's TCP API (port 2442), one persistent connection that reconnects automatically. Uses RIG.GET_FREQ / RIG.SET_FREQ for frequency and offset, MODE.GET_SPEED / MODE.SET_SPEED for speed, and JS8Call's PTT and frame messages plus its TX text to tell when it is transmitting. Works with both the standard JS8Call (2.2–2.3) and JS8Call-improved (3.0 and later), which answer some requests differently; JS8Call-improved also reports its version. Requires "Enable TCP Server API" and "Accept TCP Requests" in JS8Call. FLDIGI FLDIGI's XML-RPC interface (port 7362). Reads and sets the rig frequency, the modem (mode) by name, and the audio carrier (offset); checks the transmit/receive state before any change. In both cases the program itself must have working rig control (CAT) — the Scheduler asks JS8Call or FLDIGI to change, and they change the radio. FILES ----- Program folder (from the release ZIP): main.py and the other .py modules, assets/ (icons), sitrepnetscheduler.desktop, requirements.txt, and the documentation. Config folder — ~/.config/sitrepnetscheduler/ (Linux/Pi) or C:\Users\\.config\sitrepnetscheduler\ (Windows): config.json Settings schedule.json The schedule (plain JSON; one record per entry) state.json Only during a scheduled window: the primary settings scheduler.log Activity log, times in UTC, rotated at 1 MB scheduler.lock Single-copy lock Updating the program never touches the config folder. TECHNOLOGY ---------- - Python 3.9 or newer with Tkinter — the standard library only; no pip packages - JS8Call TCP API over standard-library sockets (newline-delimited JSON) - FLDIGI XML-RPC via the standard library's xmlrpc.client - zoneinfo (standard library) for the optional Time Zone setting; the computer's own zone needs no time zone database - A scheduling engine driven by the GUI's timer every couple of seconds, with the slow work (waiting for TX, talking to the program) on a background thread so the window never freezes - Unit tests (not shipped) cover the time rules across daylight saving, the overlap rules, the engine against a simulated program and a fake clock, and both clients against fake JS8Call and FLDIGI servers Main modules: app.py Main window engine.py When to switch and return; snapshot and recovery timecalc.py Local day / UTC rule, early start, daylight saving overlap.py Overlap detection and warning text js8call_client.py JS8Call API client fldigi_client.py FLDIGI XML-RPC client schedule_store.py Reading and writing schedule.json (plus the dialogs, settings, Copy Table, and update check) SEE ALSO -------- SitRepNetScheduler_Installation_Guide.txt Installing; setting up JS8Call and FLDIGI SitRepNetScheduler_User_Manual.txt Using the program SitRepNetScheduler_CHANGELOG.txt Version history ================================================================================ End of Program Overview ================================================================================