fwt_software/docs/configuration.md

133 lines
6.7 KiB
Markdown

# Configuration & Commands
Behaviour is controlled by three layers: the **`config.ini`** file, **command-line flags** (which override the
config), and **interactive console commands** typed while running.
## Config file resolution
There are no hardcoded paths. The file is resolved in this order ([src/core/Paths.cpp](../src/core/Paths.cpp)):
1. `--config <path>` CLI flag
2. `$FGC_CONFIG` environment variable
3. `./config.ini` (current directory)
4. `<executable dir>/config.ini`
5. `$XDG_CONFIG_HOME/fire_gimbal_control/config.ini` (else `~/.config/...`)
If none exist, the program prints every location it searched and exits. Start from the template:
```bash
cp config/config.example.ini config.ini
```
## `config.ini` keys
Parsed and validated by `ConfigLoader` ([src/core/Config.cpp](../src/core/Config.cpp)) into a typed
`AppConfig`. Invalid types/values fail fast with a clear message.
| Section | Key | Type | Default | Meaning |
|---------|-----|------|---------|---------|
| `General` | `tower_name` | string | `Unnamed` | Tower identity; used in all MQTT topics/payloads |
| `General` | `image_interval` | int > 0 | `5` | Seconds between captures (→ `image_rate = 1/interval`) |
| `General` | `debug` | bool | `false` | Start with debug-level logging |
| `Network` | `zkms_server_ip` | string | `127.0.0.1` | MQTT broker address |
| `Network` | `mqtt_user` / `mqtt_pw` | string | — | MQTT credentials (see secrets below) |
| `Serial` | `device` | string | `/dev/ttyACM0` | Motor-controller serial device |
| `Serial` | `baud` | int | `115200` | Serial baud rate |
| `Camera` | `id_Cam1`..`id_Cam4` | string | — | Camera IDs (GigE IP or USB `DEV_...`); non-empty ones used in order |
| `Paths` | `output_dir` | string | `$XDG_DATA_HOME/fire_gimbal_control/images` | Image output dir; supports `~`/`$ENV` |
| `Features` | `enable_mqtt` | bool | `true` | Use MQTT (vs null channel) |
| `Features` | `enable_camera` | bool | `true` | (reserved) |
| `Features` | `enable_serial` | bool | `true` | (reserved) |
| `Features` | `mock_camera` | bool | `false` | Use the simulated camera |
| `Features` | `mock_serial` | bool | `false` | Use the simulated motor controller |
| `Logging` | `level` | enum | `info` | Linear log level (`--log-level` overrides) |
| `Logging` | `trace` | csv | — | Wire-trace categories, off by default (`--trace` overrides) |
Camera index → output subfolder defaults to `RGB`, `ACR`, `NIR` (`CameraConfig::labels`).
### Secrets
`mqtt_user` / `mqtt_pw` are read from the environment variables **`FGC_MQTT_USER` / `FGC_MQTT_PW`** first,
falling back to the config file. Keep credentials out of `config.ini` (which is gitignored anyway) by exporting
them or using a systemd `EnvironmentFile`.
## Command-line flags
Parsed by Boost.Program_options ([main.cpp](../main.cpp)). Flags override `[Features]`.
| Flag | Effect |
|------|--------|
| `-h, --help` | Show help and exit |
| `-c, --config <path>` | Explicit config file path |
| `-i, --init` | Run the endstop-finding init sequence before the loop |
| `-s, --start` | Start capture automatically |
| `-d, --demo` | Demo mode: copy the placeholder image instead of encoding |
| `--no-mqtt` | Disable MQTT (use the null channel) |
| `--mock-camera` | Use the simulated camera |
| `--mock-serial` | Use the simulated motor controller |
| `--log-level <lvl>` | `trace`/`debug`/`info`/`warn`/`error`/`off` |
| `--trace <cats>` | Verbatim wire trace; comma list `serial,mqtt,camera,control,all,none` |
Typical headless dev run: `scripts/run.sh --mock-serial --mock-camera --no-mqtt --start`.
### Init sequence (`--init`)
Sends to the motor controller, with delays: `r``e``q`*(wait 60 s)*`y``ud56`
([src/core/Application.cpp](../src/core/Application.cpp), `runInitSequence`).
## Interactive console commands
Lines on stdin are parsed by `parseCommand` ([src/core/CommandParser.cpp](../src/core/CommandParser.cpp)) — a
whitespace tokenizer (`<verb> [device] [option] [value]`) that replaced the old fragile Boost.Spirit grammar.
Handled in `Application::Impl::handleCommand`.
| Type this | Meaning |
|-----------|---------|
| `start` | Start camera acquisition + capture |
| `stop` | Stop acquisition |
| `debug` | Toggle debug logging |
| `trace <cat> [on\|off]` | Toggle a wire-trace category (`serial`/`mqtt`/`camera`/`control`) |
| `trace all` / `trace off` | Enable every category / silence all |
| `set camera jxlq <v>` | JPEG XL distance (0 = lossless) |
| `set camera jxle <v>` | JPEG XL effort |
| `set camera display <0\|1>` | Toggle OpenCV preview window |
| `set camera fps <v>` | Camera acquisition frame rate (real camera only) |
| `set fps <v>` | Capture interval rate (images/second) |
| `set motorctl <cmd>` | Forward a raw command to the motor controller (e.g. `set motorctl kd180`) |
| `exit` | Quit (Ctrl-D also works) |
## Logging: level vs. wire-trace categories
Two **independent** controls, each settable via config (`[Logging]`), CLI, and a console command:
- **Linear level** — `[Logging] level`, `--log-level`, console `debug`. Filters ordinary messages
(`trace<debug<info<warn<error<off`). Default `info`; an active capture is nearly silent at `info`.
- **Wire-trace categories** `[Logging] trace`, `--trace`, console `trace`. Each enabled category
(`serial`, `mqtt`, `camera`, `control`) logs **every** message exchanged with that subsystem,
verbatim. They are **off by default** and **independent of the level**: `--trace serial` prints all
firmware serial traffic even at `info`. Only level `off` silences them. The `camera` category is
high-rate (one line per frame, metadata only no pixel data).
Precedence at startup: config applies first, then CLI overrides (`--trace` replaces the config set,
it does not merge). At runtime the `trace` console command edits categories incrementally.
Trace lines carry a category tag and a `TX`/`RX` direction so one subsystem is easy to follow/grep:
```
[SERIAL] TX kd180 (command to firmware)
[SERIAL] RX $;1234;0;500;1;1;0;180.5;... (telemetry from firmware; RX(unparsed) on a bad line)
[MQTT] PUB GGS/FWT/Tower/StatusCode 0 / [MQTT] RX GGS/FWT/Tower/target_HDG 180
[CAMERA] TX trigger cam0 / [CAMERA] RX frame cam0 1936x1216 7064576B
[CONTROL] motor cmd "p" (auto sweep) (scheduler decisions + inbound console commands)
```
## Motor command vocabulary (emitted by the software)
| Command | When | Meaning |
|---------|------|---------|
| `r`,`e`,`q`,`y`,`ud56` | init sequence | homing / set intervals-per-turn |
| `p` | ControlCode 0 capture | stop / advance to next interval |
| `kd<heading>` | ControlCode 1 capture | drive to target heading |
These are interpreted by the motor-controller firmware (not in this repo).