Kozai::Config
Configuration: a small key = value format with sections, plus environment
overrides.
Why not YAML
Because YAML in the standard library links libyaml, and this program has no C dependencies beyond the language runtime. That constraint is not an affectation — it is what makes the binary a single self-contained file — but it is not the only reason.
This file gets edited over ssh, on a station in a shed, possibly at night,
possibly on a phone. It wants to be the kind of format where a missing
character produces an error naming a line, not a silently different meaning.
Indentation-sensitive formats are a poor fit for that. So: a section header
in brackets, key = value beneath it, # starts a comment.
# Where the antenna is.
[station]
name = Shed
latitude = 52.3676 # degrees north
longitude = 4.9041 # degrees east
altitude = 5 # metres above the ellipsoid
[prediction]
minimum_elevation = 10
horizon_hours = 48
Environment overrides
Any setting can be overridden by an environment variable named
KOZAI_<SECTION>_<KEY> in upper case — KOZAI_STATION_LATITUDE,
KOZAI_SERVER_PORT. This is what makes the container image useful
without a config file at all, and it is how docker-compose.yml is written.
Constants
Prefix for environment variable overrides.
Section used for keys that appear before any section header.
Constructors
Reads and parses a configuration file.
Raises Config::ParseError if the file cannot be read.
Reads a configuration file if it exists, otherwise returns the defaults.
Instance methods
A boolean setting, or default.
Accepts true/false, yes/no, on/off and 1/0, in any case,
because all of them turn up in configuration files written by humans.
How long a cached element set stays fresh.
NOTE: the default is 24 hours, and it is deliberately not shorter. CelesTrak asks that clients cache and not poll, element sets are typically regenerated once or twice a day, and a station that re-downloads every few minutes gains nothing and costs someone else bandwidth.
An independent copy.
NOTE: needed because the settings page can clear a setting, and clearing cannot be expressed by writing over a live configuration — there is nothing to write. Rebuilding from a copy of everything the page did not set is the only way a cleared value goes back to whatever the file and the environment say, without a restart.
A floating-point setting, or default.
Raises Config::ValueError if present but not a number, or outside
range. Reporting a bad value beats silently substituting the default:
a station configured with a typo'd latitude should refuse to start, not
quietly point at the equator.
An integer setting, or default.
A comma-separated list setting.
Empty entries are dropped, so a trailing comma is harmless.
The observing station.
NOTE: altitude is given in metres in the file, because that is what a map or a GPS reports, and converted to kilometres here, because that is what the geometry works in. Getting this backwards would put the station a thousand times too high and is exactly the sort of thing that produces plausible, wrong answers.
Where a setting came from — a file and line, or an environment variable.
Reported when a value fails validation, so that the operator is told which of the two won.
Elevation a pass must reach to be worth scheduling.
Separate from #minimum_elevation, which decides what is worth showing.
A station will happily list a nine-degree pass and want nothing to do with
swinging an antenna for it.
Shared secret required on requests that move hardware, if set.
NOTE: empty by default, and that is safe only because the server binds to
loopback by default. The moment [server] host is changed to reach the
interface from a phone, every device on the network can point the antenna;
Cli.serve says so on the way up when this is unset.
Sets a value, replacing any existing one.
Where settings written from the interface are kept.
Next to the element cache, because that is the one directory a station is already required to have writable — the container image is read-only everywhere else by design.
Whether a station position was configured at all.
Without one every answer is about the Gulf of Guinea, which is a confusing way to be wrong.
A string setting, or default.
A required string setting.
Raises Config::ValueError if absent.
Remote element set sources.
Ignored by a -Dno_network build, which has no way to fetch them.
Path to a transponder file, if one is configured.
Its entries are laid over the ones compiled into the binary, section by section, so a station corrects a single frequency by writing a section of the same name rather than by restating the whole table.
Sun elevation below which the sky counts as dark, in degrees.
A satellite is only worth going outside for when it is in sunlight and the
observer is not, so this is half of what makes a pass visual — see
Illumination.
NOTE: −6 degrees, civil twilight, and that is a convention rather than a measurement. It is where visual pass predictions are usually quoted, so it is the value that makes this software's answers comparable with everybody else's. It is also generous: at −6 the brightest stars are out and the ISS is unmistakable, but a fainter satellite will not be. Nautical twilight (−12) or astronomical (−18) are the stricter readings, and a station under a bright sky may want them.
Zero would mean "the Sun has set", which is not the same thing at all: the sky stays too bright to see anything for another half hour.
The satellites this station works, as written.
Empty means the whole catalogue. Entries may carry a priority after a
colon — 25544:10 — which only the scheduler reads.