Cover every option in the help, the manual and the readme, and say what to install

An audit rather than a feature, prompted by wanting this fit to hand to
somebody else.

Five options had no command-line flag written down in the table the manual
is generated from -- location, hold, schedules, tile_url and speed_unit --
so five flags that exist were missing from the manual.  Four of them did
exist under other names and are now recorded; hold had no flag at all and
has one.

Four switches could be turned off from the command line and not back on:
--no-lookup, --no-basemap, --no-airports and --no-labels had no positive
halves, so an option turned off in the saved settings could not be turned on
again for one run.  All four now have both.

And adsb, which opens the window and draws a map when it stops, could not be
given any of the settings that decide what those look like: no --at, no
--radius, no --tiles, no --map-brightness, no --width, --fps, --trail,
--fade, --stale, --airports or --labels.  It takes all of them now.

The manual had no list of the aircraft options at all -- the ADS-B sections
were hand-written prose -- so five of them appeared nowhere in it.  It now
generates an AIRCRAFT OPTIONS section from the same table the menu and the
flags come from, and the readme carries a table of all thirty-four with
their flags and defaults.  Three tests hold the three of them together: one
that every option records its flag, one that every flag the table claims
actually exists on a command, and one that the readme names them all.

The installing instructions now list every dependency rather than only the
optional ones: the four Python packages with their names in Debian, Fedora
and Arch, and librtlsdr, which is a C library and therefore the one thing
pip cannot bring and a virtual environment cannot supply.  What reaches a
network is written down too -- which host, when, and which file it is cached
in -- since somebody installing this on a metered or air-gapped machine has
to be able to see that nothing is fetched behind their back.  build-repo.sh
needs dpkg-dev and apt-utils, which a minimal system does not have, and now
says so.

Verified rather than asserted: a clean virtual environment, pip install from
this tree, and a real log read back through the installed command.  It pulls
seven wheels rather than the four the page claimed, the other three being
what Rich brings with it.

Also: matplotlib is gone from the readme's dependency table, nothing having
imported it; ffmpeg and Qt are in it, both having been missing; ffmpeg is a
Suggests on the package; and resume.sh is ignored.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016PsWPTweCT6pwxKngvVxcg
This commit is contained in:
The Dust Council 2026-09-06 14:12:33 -07:00
parent 6d2436cde1
commit 8ed01f991f
16 changed files with 1012 additions and 46 deletions

View file

@ -1,5 +1,5 @@
.\" Generated by packaging/make-man.py -- do not edit by hand.
.TH BANDSAUNTER 1 "2026-09-06" "bandsaunter 2026-09-06_02" "User Commands"
.TH BANDSAUNTER 1 "2026-09-06" "bandsaunter 2026-09-06_03" "User Commands"
.SH NAME
bandsaunter \- scan, record and identify radio signals with an RTL-SDR
.SH SYNOPSIS
@ -1651,6 +1651,306 @@ instead goes straight to that option, and part of a name lists everything it
could mean; a name that matches exactly wins outright, so "speed" reaches the
setting called speed rather than that one and every other whose description
mentions the word.
.SS The card behind a box
.BI \-\-box\-opacity " PERCENT"
is how solid the card behind each information box is. The words beside an
aircraft are readable over water and not over a city, so a card goes behind
them: at nothing they sit straight on the map and at the whole way the map
does not show through at all. An indexed picture cannot blend, so in the
animation this darkens the ground under the box instead, which leaves the
coastline faintly visible through it. The animated pictures had no card at all
before, so nothing is what they used to look like.
.PP
The flag marking the receiver is drawn after everything else on both pictures
\[em] after the aircraft, their trails and their boxes \[em] since it says
where the receiver is standing and that is the one mark that must not end up
behind an aeroplane that happened to fly over it. A vector theme's halo cannot
cover it either, a halo only ever going on the ground, the grid and the
background.
.SH AIRCRAFT OPTIONS
Every option the ADS-B side takes, in the six groups the menu shows them in.
Each is a flag here and a line in the menu, and both come from one table in
the program, so they cannot disagree.
.SS Receiver
.TP
.B --device
Receiver \[em] which receiver to use, when more than one is plugged in.
.br
Setting name \fBdevice\fR, default \fB0\fR.
.br
Accepts: at least 0.
.TP
.B --gain
Gain \[em] tuner gain in dB, or automatic.
.br
Setting name \fBgain\fR, default \fBauto\fR.
.TP
.B --rate
Sample rate \[em] how fast to sample; two megasamples a second is the minimum (Hz).
.br
Setting name \fBrate\fR, default \fB2 MHz\fR.
.br
Accepts: at least 2e+06.
.TP
.B --at
Receiver at \[em] where the receiver is, as latitude,longitude (blank = work it out).
.br
Setting name \fBlocation\fR, default \fBblank\fR.
.TP
.B --simulate
Invent a sky \[em] fly imaginary aircraft past an imaginary receiver.
.br
Setting name \fBsimulate\fR, default \fBno\fR.
.RS
.PP
Turn this on to see what the whole thing does without hardware. Turn it off to hear real aircraft.
.RE
.TP
.B --near
Imaginary sky near \[em] where the simulated aircraft are flying.
.br
Setting name \fBnear\fR, default \fB47.55,-122.30\fR.
.PP
.SS Listening
.TP
.B --seconds
Listen for \[em] how long to listen before stopping (0 = until interrupted) (s).
.br
Setting name \fBseconds\fR, default \fBuntil stopped\fR.
.br
Accepts: at least 0.
.RS
.PP
Sixty seconds is enough to know whether aircraft are being heard. An evening of traffic wants no limit.
.RE
.TP
.B --frames
Show every frame \[em] print each frame as it arrives, rather than a running count.
.br
Setting name \fBframes\fR, default \fBno\fR.
.TP
.B --log / --no-log
Write the log \[em] write every frame to a file as it arrives.
.br
Setting name \fBlog\fR, default \fByes\fR.
.TP
.B --kml
Also write a KML \[em] write the flight paths for Google Earth as well.
.br
Setting name \fBkml\fR, default \fBno\fR.
.TP
.B --hold
Keep on screen for \[em] how long an aircraft stays on the display after its last frame (s).
.br
Setting name \fBhold\fR, default \fB45 s\fR.
.br
Accepts: at least 1.
.RS
.PP
Long enough that a gap in reception does not make rows jump about; short enough that the screen is the sky now.
.RE
.TP
.B --map
Draw when finished \[em] draw the map as soon as the listening stops.
.br
Setting name \fBdraw_after\fR, default \fBno\fR.
.PP
.SS Aircraft
.TP
.B --lookup / --no-lookup
Look the aircraft up \[em] ask the public registers who each aircraft is.
.br
Setting name \fBlookup\fR, default \fByes\fR.
.TP
.B --schedules
Schedule services \[em] which paid schedule services to ask, in order (blank = all with keys).
.br
Setting name \fBschedules\fR, default \fBblank\fR.
.RS
.PP
Leave it blank unless you want one service tried before another. With no keys set, nothing changes.
.RE
.TP
.B --recheck
Check the positions \[em] throw out positions the aircraft could not have been in.
.br
Setting name \fBrecheck\fR, default \fBno\fR.
.RS
.PP
Worth turning on for anything recorded before this version. Newer logs have the check applied as they are written, so it finds almost nothing.
.RE
.PP
.SS Animation
.TP
.B --out
Picture \[em] what kind of picture to draw.
.br
Setting name \fBpicture\fR, default \fBgif\fR.
.br
Accepts: one of: gif, mp4, png.
.RS
.PP
Start with gif. Use png when you want one picture to look at or send.
.RE
.TP
.B --seconds
Animation length \[em] how long the animation should run for (s).
.br
Setting name \fBlength\fR, default \fB30 s\fR.
.br
Accepts: at least 1.
.TP
.B --speed
Speed \[em] seconds of flying per second of animation (0 = fit to the length) (x).
.br
Setting name \fBspeed\fR, default \fBfit to the length\fR.
.br
Accepts: at least 0.
.TP
.B --fps
Frames a second \[em] how many frames of animation each second holds.
.br
Setting name \fBfps\fR, default \fB12\fR.
.br
Accepts: at least 1.
.TP
.B --width
Picture width \[em] how many pixels across the picture is (px).
.br
Setting name \fBwidth\fR, default \fB960 px\fR.
.br
Accepts: at least 160.
.TP
.B --trail
Trail \[em] how much of the path to leave behind each aircraft (0 = all of it) (s).
.br
Setting name \fBtrail\fR, default \fBthe whole path\fR.
.br
Accepts: at least 0.
.TP
.B --fade
Fade out over \[em] how long an aircraft takes to fade away once it has gone quiet (s).
.br
Setting name \fBfade\fR, default \fB20 s\fR.
.br
Accepts: at least 0.
.RS
.PP
Long enough to notice, short enough that a busy sky is not half ghosts.
.RE
.TP
.B --stale
Forget after \[em] stop drawing an aircraft this long after its last report (s).
.br
Setting name \fBstale\fR, default \fB300 s\fR.
.br
Accepts: at least 1.
.PP
.SS The map
.TP
.B --basemap / --no-basemap
Map underneath \[em] draw a real map under the flight paths.
.br
Setting name \fBbasemap\fR, default \fByes\fR.
.RS
.PP
Turn it off for a picture with nothing but the tracks on it, or where there is no network and no cached tiles.
.RE
.TP
.B --tiles
Tile server \[em] where the map tiles come from.
.br
Setting name \fBtile_url\fR, default \fBblank\fR.
.TP
.B --theme
Colour theme \[em] how the map looks: the colours, and whether the lines glow.
.br
Setting name \fBtheme\fR, default \fBnight\fR.
.br
Accepts: one of: night, digital, phosphor, amber, red.
.RS
.PP
night to read it, the others to look at it.
.RE
.TP
.B --map-brightness
Map brightness \[em] how bright the map under the aircraft is drawn, as a percentage (%).
.br
Setting name \fBmap_brightness\fR, default \fB70 %\fR.
.br
Accepts: at least 10, at most 100.
.RS
.PP
Turn it up until the coast and the roads are readable, and no further. On a vector theme it takes rather more turning up than on the default one.
.RE
.TP
.B --radius
Map radius \[em] how far around the receiver the map reaches (0 = fit whatever was heard).
.br
Setting name \fBradius\fR, default \fB100\fR.
.br
Accepts: at least 0.
.RS
.PP
Set it to what your aerial can really hear. Zero goes back to fitting whatever turned up, mistakes and all.
.RE
.TP
.B --airports / --no-airports
Mark the airports \[em] mark every aerodrome on the map, not only the ones flown between.
.br
Setting name \fBairports\fR, default \fByes\fR.
.RS
.PP
Turn it off for a picture with nothing but the aircraft on it, or where there is no network and nothing cached.
.RE
.TP
.B --rings / --no-rings
Range rings on the pictures \[em] faint discs at a quarter, a half and three quarters of the radius.
.br
Setting name \fBrings\fR, default \fByes\fR.
.RS
.PP
Turn it off for a picture with nothing on it but the aircraft and the ground.
.RE
.TP
.B --window-rings / --no-window-rings
Range rings in the window \[em] the same discs on the realtime display.
.br
Setting name \fBwindow_rings\fR, default \fByes\fR.
.RS
.PP
Turn it off if the window is busy enough already.
.RE
.PP
.SS Labels
.TP
.B --box-opacity
Box translucency \[em] how solid the card behind each information box is, as a percentage (%).
.br
Setting name \fBbox_opacity\fR, default \fB85 %\fR.
.br
Accepts: at least 0, at most 100.
.RS
.PP
Turn it up over a busy map and down over an empty one.
.RE
.TP
.B --labels / --no-labels
Label the aircraft \[em] write the callsign, height and speed beside each aircraft.
.br
Setting name \fBlabels\fR, default \fByes\fR.
.TP
.B --speed-unit
Speed in \[em] what to show speeds and distances in.
.br
Setting name \fBspeed_unit\fR, default \fBknots\fR.
.br
Accepts: one of: knots, mph, kph.
.RS
.PP
knots is what aviation uses and what the aircraft actually said. mph or kph if that is what means something to you.
.RE
.PP
.SS Range rings
.B \-\-rings
puts faint discs at a quarter, a half and three quarters of the radius,

View file

@ -77,7 +77,7 @@ Architecture: ${arch}
Depends: python3 (>= 3.10), python3-numpy, python3-scipy, python3-rich,
python3-yaml, librtlsdr0
Recommends: bandsaunter-transcribe, espeak-ng
Suggests: rtl-sdr, python3-pyqt6
Suggests: rtl-sdr, python3-pyqt6, ffmpeg
Maintainer: bandsaunter
Installed-Size: $(du -ks "$pkgdir" | cut -f1)
Description: signal scanner and recorder for RTL-SDR receivers

View file

@ -56,6 +56,43 @@ def settings_section() -> list[str]:
return out
def aircraft_section() -> list[str]:
"""Every ADS-B option, from the same table the menu and flags come from.
Written out rather than described in prose, so that an option added to
the program cannot quietly fail to appear in its manual.
"""
from bandsaunter import aircraft as air
out = []
defaults = air.AircraftOptions()
for group in air.OPTION_GROUPS:
out.append(f'.SS {esc(group)}')
for o in air.in_group(group):
flags = " ".join(o.flags)
if o.off_flags:
flags += " / " + " ".join(o.off_flags)
shown = air.format_option(o, getattr(defaults, o.key))
unit = f" ({o.unit})" if o.unit and o.kind != "bool" else ""
out.append('.TP')
out.append(f'.B {esc(flags) if flags else esc(o.key)}')
out.append(f'{esc(o.label)} \\[em] {esc(o.help)}{esc(unit)}.')
out.append('.br')
out.append(f'Setting name \\fB{esc(o.key)}\\fR, '
f'default \\fB{esc(shown) if shown else "blank"}\\fR.')
accepts = o.describe_range()
if accepts:
out.append('.br')
out.append(f'Accepts: {esc(accepts)}.')
if o.guidance:
out.append('.RS')
out.append('.PP')
out.append(esc(o.guidance))
out.append('.RE')
out.append('.PP')
return out
HEAD = r'''.\" Generated by packaging/make-man.py -- do not edit by hand.
.TH BANDSAUNTER 1 "{date}" "bandsaunter {version}" "User Commands"
.SH NAME
@ -1044,6 +1081,27 @@ instead goes straight to that option, and part of a name lists everything it
could mean; a name that matches exactly wins outright, so "speed" reaches the
setting called speed rather than that one and every other whose description
mentions the word.
.SS The card behind a box
.BI \-\-box\-opacity " PERCENT"
is how solid the card behind each information box is. The words beside an
aircraft are readable over water and not over a city, so a card goes behind
them: at nothing they sit straight on the map and at the whole way the map
does not show through at all. An indexed picture cannot blend, so in the
animation this darkens the ground under the box instead, which leaves the
coastline faintly visible through it. The animated pictures had no card at all
before, so nothing is what they used to look like.
.PP
The flag marking the receiver is drawn after everything else on both pictures
\[em] after the aircraft, their trails and their boxes \[em] since it says
where the receiver is standing and that is the one mark that must not end up
behind an aeroplane that happened to fly over it. A vector theme's halo cannot
cover it either, a halo only ever going on the ground, the grid and the
background.
.SH AIRCRAFT OPTIONS
Every option the ADS-B side takes, in the six groups the menu shows them in.
Each is a flag here and a line in the menu, and both come from one table in
the program, so they cannot disagree.
.AIRCRAFT_OPTIONS_HERE
.SS Range rings
.B \-\-rings
puts faint discs at a quarter, a half and three quarters of the radius,
@ -1282,6 +1340,8 @@ def main() -> int:
out += settings_section()
out.append(TAIL)
text = "\n".join(out)
text = text.replace(".AIRCRAFT_OPTIONS_HERE",
"\n".join(aircraft_section()))
text = text.replace("\n\n", "\n") # troff dislikes blank lines
target = Path(sys.argv[1] if len(sys.argv) > 1
else Path(__file__).parent / "bandsaunter.1")