Live Status
Doppler shift is measured from a spectrum window centred on each carrier (…), using a power-weighted centroid over the 3 dB peak region — the same algorithm used by the UberSDR frequency reference monitor. Typical precision is ~0.01 Hz at SNR > 20 dB. Spectrum updates every ~2 seconds; minute means average ~30 samples. Once a station drops to No signal, it will not return to a valid state until the signal has been continuously above the SNR threshold for a full minute.
| Station | Frequency | Doppler Shift | SNR | Signal | Noise Floor | Updated (UTC) | State |
|---|---|---|---|---|---|---|---|
| Loading stations… | |||||||
Signal Lock
… centred on each carrier. Green dashed = nominal frequency. Red marker = detected peak (power-weighted centroid, ~0.01 Hz precision at high SNR). Scroll to zoom · drag to pan · double-click to reset.
Doppler Shift History
Zero line = no Doppler shift. Positive = ionosphere falling (layer compressed). Negative = ionosphere rising. Gaps = signal below SNR threshold. "Absolute frequency" mode shows received Hz.
🗺 Propagation Map
Manage Stations
Settings
Download CSV
Downloads a HamSCI Grape-format CSV file. The file begins with a # metadata
header block: the first line is #,<timestamp>,<node>,<grid>,<lat>,<lon>,<elev>,<location>,G1,<station>,
followed by a ####### comment block containing station metadata (node number, callsign, grid square,
lat/lon/elevation, city/state, beacon, nominal frequency, frequency standard, radio). The final header line is the column header
UTC,Freq,Vpk. Each subsequent data row is one 1-second observation:
UTC (HH:MM:SS), Freq (received frequency in Hz = nominal + Doppler), Vpk (peak amplitude, linear 0–1).
All endpoints are read-only GET requests unless noted. Responses are JSON unless the endpoint returns CSV. The curl examples below use the URL you are currently viewing this page on.
CSV Download — GET /api/csv
Returns 1-second Grape-format CSV data for a station. Three mutually exclusive time-range modes:
| Mode | Parameters | curl example |
|---|---|---|
| Full UTC day | station= & date=YYYY-MM-DD |
curl "http://localhost:8080/api/csv?station=WWV-10&date=2026-05-04" -o wwv10.csv |
| Relative window | station= & last=<N>[s|m|h] |
curl "http://localhost:8080/api/csv?station=WWV-10&last=15m" -o wwv10_15m.csv |
| Absolute range | station= & start=<RFC3339> [& end=<RFC3339>] |
curl "http://localhost:8080/api/csv?station=WWV-10&start=2026-05-04T16:45:00Z&end=2026-05-04T17:00:00Z" -o wwv10_range.csv |
last=units:sseconds,mminutes,hhours (e.g.last=15m,last=1h,last=3600s).- When
end=is omitted withstart=, end defaults to now. - Windows that span midnight automatically read from both UTC day files.
- Output format: Grape
#metadata header +UTC,Freq,Vpkrows (identical to the full-day download).
Live Station Data — GET /api/stations
Returns a JSON array of all stations with their current reading, 60-minute baseline mean, and latest spectrum snapshot.
curl http://localhost:8080/api/stationsLive SSE Stream — GET /api/events
Server-Sent Events stream of 1-second Doppler readings. Optional station= filter; omit to receive all stations.
curl -N "http://localhost:8080/api/events?station=WWV-10"- Event types:
connected(on connect),heartbeat(every 15 s),spectrum(FFT bins), unnamed data events (readings).
| Field | Type | Description |
|---|---|---|
station | string | Station label as configured. |
server_time | RFC 3339 | Wall-clock time the server emitted this event. |
| reading fields | ||
timestamp | RFC 3339 | UTC time of this 1-second measurement. |
doppler_hz | float64 | Measured carrier offset from nominal frequency (Hz). Positive = higher than nominal. |
corrected_doppler_hz | float64 | omitted | Doppler after subtracting the reference station's clock error (Hz). Omitted when no reference station is configured or the reference has no valid signal. |
snr_db | float32 | Signal-to-noise ratio of the carrier peak (dB above noise floor). |
signal_dbfs | float32 | Peak carrier power (dBFS). |
noise_dbfs | float32 | Estimated noise floor — 5th-percentile power across the full 100 Hz window (dBFS). |
valid | bool | true when SNR ≥ threshold and the carrier peak passes all quality gates. false readings still carry snr_db, signal_dbfs, and noise_dbfs. |
| propagation metrics — omitted until ≥10 valid samples; always omitted when valid = false | ||
doppler_spread_hz | float64 | omitted | Standard deviation of doppler_hz over the last ≤60 valid samples. Elevated values (>0.1 Hz) indicate ionospheric spread-F, multipath, or rapid fading. Typical quiet-ionosphere value: <0.05 Hz. |
scintillation_s4 | float64 | omitted | Amplitude scintillation index S4 = stddev(A)/mean(A) where A = 10^(signal_dbfs/20) (linear amplitude), over the same rolling window. Values >0.3 indicate moderate scintillation. |
multipath_index | float64 | omitted | Ratio of sideband energy to carrier energy in the FFT window: sum of linear power in ±10 Hz sideband (excluding ±4 Hz guard) divided by carrier linear power. Higher values indicate stronger multipath or adjacent interference. Typical clean-path value: <0.01. |
Minute-Mean History — GET /api/history
Returns a JSON array of 1-minute mean readings for a station.
| Parameter | Description |
|---|---|
station= | Required. Station label. |
date=YYYY-MM-DD | Optional. Return a specific UTC day from disk. Omit for the rolling 24 h in-memory window. |
smooth=N | Optional. Rolling average window in minutes (1–10). Default 1 (no smoothing). |
curl "http://localhost:8080/api/history?station=WWV-10&smooth=5"Global Settings — GET / POST /api/settings
GET returns current settings JSON. POST updates settings (requires auth if a UI password is configured).
curl http://localhost:8080/api/settingsAudio Preview — GET /api/audio/preview
Streams a live mono WAV audio preview of the station's carrier frequency. The connection is established on demand and dropped when the client disconnects. Useful for verifying the carrier is audible.
| Parameter | Description |
|---|---|
station= | Required. Station label. |
- Response:
audio/wavwith a streaming WAV header (mono, S16LE PCM). Sample rate is read from the UberSDR audio stream (default 12000 Hz). - The audio is centred 1 kHz below the carrier frequency (dial frequency = carrier − 1000 Hz), so the carrier tone appears at 1 kHz in the audio.
GET /api/audio/info?station=<label>returns{ sample_rate, dial_freq_hz, carrier_freq_hz, label }without opening the stream.
| Use case | Command |
|---|---|
| Play directly (Linux, ALSA) | curl -sN "http://localhost:8080/api/audio/preview?station=WWV-10" | aplay -f S16_LE -r 12000 -c 1 |
| Play with ffmpeg upsample to 48 kHz (Linux/macOS) | curl -sN "http://localhost:8080/api/audio/preview?station=WWV-10" | ffmpeg -i pipe:0 -af aresample=48000 -f wav pipe:1 | aplay |
| Play with ffmpeg on macOS (CoreAudio) | curl -sN "http://localhost:8080/api/audio/preview?station=WWV-10" | ffmpeg -i pipe:0 -af aresample=48000 -f wav pipe:1 | afplay - |
| Save to file | curl -sN "http://localhost:8080/api/audio/preview?station=WWV-10" -o wwv10_audio.wav |
Raw IQ Stream — GET /api/iq/stream
Streams a live stereo WAV of raw IQ samples centred on the station's carrier frequency (±6 kHz, 12 kHz total bandwidth). Compatible with SDR tools and the Web Audio API.
| Parameter | Description |
|---|---|
station= | Required. Station label. |
- Response:
audio/wavwith a streaming WAV header. Format: 2 channels (I = left, Q = right), S16LE PCM, sample rate from UberSDR IQ stream (default 12000 Hz). - Centre frequency is the station's nominal carrier frequency. The ±6 kHz window captures the full 100 Hz Doppler monitoring band with wide margin.
GET /api/iq/info?station=<label>returns{ sample_rate, centre_freq_hz, bandwidth_hz, label }without opening the stream.
| Use case | Command |
|---|---|
| Save to WAV file | curl -sN "http://localhost:8080/api/iq/stream?station=WWV-10" -o wwv10_iq.wav |
| Pipe to GNU Radio / SDR tools (raw S16LE interleaved IQ) | curl -sN "http://localhost:8080/api/iq/stream?station=WWV-10" | ffmpeg -i pipe:0 -f s16le -ar 12000 -ac 2 pipe:1 | your-sdr-tool |
| Upsample to 48 kHz stereo WAV with ffmpeg | curl -sN "http://localhost:8080/api/iq/stream?station=WWV-10" | ffmpeg -i pipe:0 -af aresample=48000 wwv10_iq_48k.wav |
| Convert to complex float32 for numpy / scipy | curl -sN "http://localhost:8080/api/iq/stream?station=WWV-10" | ffmpeg -i pipe:0 -f f32le -ar 12000 -ac 2 pipe:1 > wwv10_iq.cf32 |