Releases: bakstaaj/N0JCG-SCANNER
Release list
N0JCG Scanner v5.0.0
N0JCG Scanner v4.2.7
N0JCG Scanner v4.2.7
Persistent P25 service recovery
The P25 decoder now remains owned by the radio service when the web backend is
restarted. The backend follows the persistent OP25 event log, reconnects to an
already-running decoder, and avoids starting a duplicate process. Decoder
process detection validates the actual command line so transient shell matches
cannot be mistaken for a healthy receiver.
Operator documentation and packaging
- Documented backend-only restart behavior and the correct Stop workflow.
- Refreshed the branded user manual to v4.2.7.
- Published the reproducible N0JCG Scanner v4.2.7 release archive and checksum.
N0JCG Scanner v4.2.5
Updated N0JCG Scanner release including the guided new-Pi installation wizard, automatic required RTL-SDR serial assignment, first-run Radio Setup routing, and updated user documentation.
N0JCG Scanner v4.1.0
N0JCG Scanner v4.1.0
Release date: 2026-08-10
N0JCG Scanner v4.1.0 updates the v4 licensed scanner for the recombined
Raspberry Pi deployment model. The Pi is the complete scanner host; the ROC
provides navigation to the Pi service.
Highlights
- Recombined the web application, API, audio fanout, P25 decoder, VHF FFT
scanner, and UHF FFT scanner on the Pi runtime at/home/pi/n0jcg-scanner. - Updated deployment and operator documentation to reflect Pi-only runtime
ownership and the direct scanner URL on port 8070. - Corrected production licensing activation payload and Cloudflare-safe client
identification, including the exactscannerproduct binding. - Fixed dynamic return navigation and refreshed the N0JCG branded desktop and
mobile assets. - Fixed registered-badge visibility and cache invalidation so registered
installations do not show the registration pill on the main UI.
Validation
- Full Python suite: 189 tests passed.
- Browser asset and deployment checks passed.
- Release archive and SHA-256 checksum generated from the current
main
commit.
N0JCG-SCANNER v3.0.0
PI-SCANNER v3.0.0
This major release separates the browser application from the radio runtime
and hardens continuous audio delivery for multiple simultaneous listeners.
Major changes
- Hosts the browser application under the existing N0JCG ROC
/pi-scanner/
mount while retaining all RTL-SDR, OP25, FFT scanning, demodulation, and
audio arbitration on the radio Pi. - Adds explicit ROC and radio deployment manifests with role-specific dry-run,
backup, checksum, deployment, restart, and live-validation commands. - Uses relative browser navigation and base-path-aware API/audio requests, so
the application does not depend on hardcoded browser-facing host addresses. - Restores the ROC-dashboard back control adjacent to the menu button.
- Lets each desktop or mobile browser attach to an already-running scanner
without restarting the P25, VHF, or UHF services. - Replaces per-frame browser playback nodes with a bounded continuous PCM ring
buffer. The player resamples 8 kHz scanner audio to the browser device rate,
corrects slow clock drift, and reports underrun and dropped-sample metrics. - Retains AudioWorklet support for secure deployments and supplies an
HTTP-compatible continuous-node implementation for the current LAN ROC. - Adds a bounded radio-side jitter recovery window so slightly late decoder
frames are recovered instead of immediately being replaced by silence. - Adds audio packet-gap, late-frame recovery, and active-gap counters to the
arbitrator status contract.
Runtime ownership
- ROC application host: static PI Scanner assets and reverse-proxy routes.
- Radio Pi: P25 decoder, VHF and UHF FFT workers, RTL-SDR ownership, radio API,
and unified PCM fanout. - VHF RTL-SDR serial:
00000144. - UHF RTL-SDR serial:
00000440.
Audio validation
- ROC PCM proxy cadence: 500 consecutive 20 ms frames with zero gaps over
100 ms and a measured maximum gap near 30 ms. - Chromium continuous-player validation: native 48 kHz output, clock-recovered
queue settling near 110 ms, and no new underruns or dropped samples during
the extended validation interval. - Controlled UHF input test: 750 frames received during a 15-second
transmission with 749 forwarded by the unified arbitrator. - Operator acceptance after the bounded backend jitter update: longer messages
reported improved.
Validation
PYTHONPATH=src python3 -m pytest -q: 169 tests passed.- JavaScript syntax checks pass for desktop, mobile, AudioWorklet, and
HTTP-compatible ring-buffer players. - Split-host runtime validation passes ROC health, proxied radio status,
proxied audio status, direct radio API, direct audio fanout, and served web
asset checks. - Live deployments created recoverable, application-specific backups on both
the ROC and radio Pi.
Upgrade
From MSYS2 UCRT64, configure the non-secret host and repository fields in
.env, then run:
./tools/deploy_application_to_roc.sh --dry-run
./tools/deploy_radio_to_pi.sh --dry-run
./tools/deploy_application_to_roc.sh --deploy --yes
./tools/deploy_radio_to_pi.sh --deploy --yes --restart
./tools/validate_split_runtime.shDeployment credentials remain local in the ignored .env file and are never
included in release artifacts.
N0JCG-SCANNER v2.0.0
PI-SCANNER v2.0.0
This major release replaces the retired v1.0.19 patched VHF path with a
single-owner FFT-directed NFM scanner validated on the deployed Raspberry Pi.
Major changes
- Binds the VHF scanner to RTL-SDR serial
00000144and the UHF scanner to
serial00000440; the VHF worker fails closed if its serial is reversed. - Replaces
persistent_vhf_fft_scanner.pyand the
90-persistent-fft.confservice override with the maintained
vhf_fft_scanner.pyworker behind the stableanalog_vhf_workerentry point. - Surveys only enabled uploaded VHF FM/NFM frequencies across grouped FFT
spans, validates candidates away from the tuner DC spike, demodulates NFM
in-process, and forwards 8 kHz mono PCM to the unified audio arbitrator on
UDP port23458. - Actively drains and discards queued
rtl_tcpIQ after sample-rate and tuner
changes so FFT and narrowband validation use samples from the requested RF
center. - Rejects weak, off-frequency, silent, and noise-only candidates using
multi-slice carrier and audio evidence while preserving complete calls
through modulation-related metric dips. - Adds learned artifact baselines, signal-rise ranking, cooldown override,
priority-channel short-circuiting, and separate strong-call carrier hang. - Preserves per-frequency validation history, the last successful lock, and a
boundedvhf_last_call.wavdiagnostic containing the exact PCM sent to the
browser. - Makes the analog channel API honor
PI_SCANNER_ANALOG_ROOT, keeping channel
uploads and worker runtime configuration on the same checkout. - Updates deployment, service installation, role mapping, hardware smoke
tests, tuning capture tools, and documentation for the corrected serial
assignments and new VHF state machine.
Live acceptance
- VHF receiver: serial
00000144 - UHF receiver: serial
00000440 - N0JCG simplex test:
146.600 MHz - Measured VHF carrier: approximately
50 dBnarrowband SNR - Measured frequency error: approximately
27 Hz - Result: continuous NFM audio heard in the web application through key-down
- Additional result: a complete live VHF fire-dispatch transmission was heard
- Idle noise check: 44 FFT sweeps, 45 candidates rejected, zero false locks,
and zero unwanted frames before final strong-call tuning - Unified audio arbitrator: VHF packets accepted and forwarded with zero
rejected packets during acceptance testing
Validation
- 17 focused VHF unit and regression tests pass.
- Python compilation, JSON/schema checks, shell syntax, whitespace checks,
isolated RTL hardware PCM smoke, UDP-to-HTTP bridge smoke, serial ownership,
FFT sweep, service state, and web channel API checks pass. - The deployment workflow creates a recoverable Pi backup before replacing
files. The final acceptance deployment backup is under
/home/pi/PI-SCANNER/runtime/patch_backups/.
Upgrade note
Run tools/msys2_deploy_vhf_fft_scanner.sh from MSYS2 UCRT64. The deployment
backs up the current Pi files, removes the exact retired v1.0.19 systemd
override, installs the maintained worker, verifies serial ownership, runs the
isolated hardware/audio smoke tests, restarts the VHF and backend services, and
checks the live channel API.
N0JCG-SCANNER v1.0.19
PI-SCANNER v1.0.19
Current deployed Pi state
This release intentionally captures and commits the exact VHF implementation
currently deployed on the PI-SCANNER device.
No additional troubleshooting, runtime repair, tuning changes, or source
transformation was performed as part of this release.
Captured VHF implementation
- Worker:
persistent_vhf_fft_scanner.py - Service override:
90-persistent-fft.conf - VHF receiver serial:
00000144 - VHF audio UDP port:
23458 - Separate
rtl_fmaudio handoff - Generic candidate ranking by RF margin
- Three PCM frames required before confirming a lock
- No channel-specific priority behavior
Runtime state at release capture
- VHF systemd service:
active - UHF systemd service:
active - VHF status:
state=stopped, search_mode=persistent_fft_rtl_tcp, voice_demodulator=separate_vhf_rtl_fm_dc_deemp, locks=0, frames=0
The VHF status record reported state=stopped at capture time. This release
preserves that current state rather than claiming the VHF runtime is validated
or fully operational.
Included snapshots
- Current analog receiver configuration
- Current VHF runtime status JSON
- Effective VHF systemd unit and overrides
- Effective VHF ExecStart
N0JCG-SCANNER v1.0.0
PI-P25-SCANNER v1.0.0
PI-P25-SCANNER v1.0.0 is the first major stable release of the dedicated
Raspberry Pi P25 trunked-radio scanner. It establishes a validated
multi-receiver OP25 architecture with independent control and voice
demodulation, reliable browser audio, receiver-role protection, and truthful
runtime status.
Validated production architecture
- Raspberry Pi 5 running the P25 scanner backend and web interface.
- Dedicated control receiver:
- RTL serial
00000251 - CQPSK demodulation
LNA:40
- RTL serial
- Dedicated voice receiver:
- RTL serial
00000252 - FSK4 demodulation
LNA:49
- RTL serial
- OP25
multi_rx.pyruntime with one protected control receiver and scalable
dedicated voice receivers. - Backend and web interface on TCP port
8070. - Raw browser-audio endpoint on TCP port
8072. - OP25 per-receiver UDP audio pool on ports
23500through23509. - Selected audio forwarded to the existing browser bridge on UDP port
23456.
P25 control-channel behavior
- Sticky control-channel operation tolerates consecutive framing timeouts before
hunting fallback channels. - Tenderfoot II effective control-channel list:
853.300000 MHz853.537500 MHz853.750000 MHz
852.225000 MHzis excluded from control-channel scanning but remains
available for dynamically assigned voice traffic.- The dedicated control receiver uses an impossible TGID whitelist entry so it
cannot be consumed by a voice grant.
Voice and browser-audio behavior
- Independent control and voice demodulator settings.
- FSK4 voice decoding produces active, intelligible Phase I PCM where CQPSK
voice produced effectively silent PCM. - Audio-pool minimum RMS threshold:
25. - Per-burst acquisition warm-up: eight 20 ms frames, approximately
160 ms. - OP25
DRAINandDROPUDP flags are decoded as explicit audio-burst
boundaries. - The selected voice source remains held through quiet speech while PCM packets
continue arriving. - Lost-packet safety release occurs after
2.5 secondswithout PCM. - Audio sources are selected without mixing.
Runtime and UI improvements
- Receiver inventory and persistent receiver-role registry.
- Scalable multi-receiver state and configuration telemetry.
- Truthful control and voice frequency reporting.
- Voice-assignment and audio-pool activity counters.
- Balanced UI polling to avoid excessive backend load.
- Rotating OP25 runtime log:
- 8 MiB active log
- five retained backups
- Control-frequency parsing no longer misclassifies unqualified voice tuning
messages as control-channel changes.
Hardware role registry
The validated seven-receiver inventory preserves these assignments:
| Role | RTL serial |
|---|---|
| P25 control | 00000251 |
| P25 voice | 00000252 |
| NOAA / airband | 00000162 |
| ADS-B 1090 | 00001090 |
| UAT 978 | 00000978 |
| Analog 2 m | 00000440 |
| Analog 70 cm | 00000144 |
Only the P25 services are part of this release runtime. Other assigned receivers
remain reserved for their associated applications or later phases.
Final hardware validation
The v1.0.0 release state was validated on July 23, 2026 against Colorado DTRS
Tenderfoot II, RFSS 6, Site 017.
Final flag-aware audio validation observed:
- three actual decoded audio bursts;
- 216 PCM frames;
- 64 active PCM frames;
- 24 acquisition frames suppressed, exactly eight per audio burst;
- 122 stabilized PCM frames forwarded;
- 15 OP25 DRAIN flags;
- three selected-stream boundary events;
- zero timeout-driven source releases;
- zero audio output errors.
The user confirmed that audio quality and continuity were substantially improved
after the flag-aware call-boundary and source-hold changes.
Important limitations
- Encrypted P25 traffic cannot be decoded.
- The first approximately 160 ms of each selected voice burst is intentionally
suppressed to remove unstable acquisition audio. - v1.0.0 was hardware-validated with one dedicated voice receiver. The
architecture supports adding more matching P25 voice receivers. - This source release does not contain site credentials, RadioReference
credentials, runtime logs, generated local settings, or other device-specific
secrets.
Release lineage
- Recovery/main checkpoint:
a83da5307636ebf32deece49b2ad9a2639837c44 - Validated Phase 32 audio-boundary commit:
1de841591071fb693f20aa40929cd707cb6d0d07 - Release branch:
feature/scalable-p25-multi-rx-v2