RotorHazard Plugin: Operator Setup¶
How to use RaceLink inside RotorHazard once the
RaceLink_RH_Plugin is installed. For installation
itself (online vs. offline), see README.md.
Audience. Operators running RotorHazard who want to use RaceLink to control the LED nodes during a race.
Where RaceLink lives in the RotorHazard UI¶
The plugin registers two panels in RotorHazard's UI:
rl_settings— RaceLink device and group configuration. Devices, group assignment, "force groups" action, defaults.rl_quickset— quick-fire controls. Group selector, preset selector, brightness slider, and the Run quickset action.
Both panels are bootstrapped on first plugin sync and are guarded
by _settings_panel_bootstrapped / _quickset_panel_bootstrapped
flags so repeated syncs do not produce RHUI Redefining ... log
spam.
The full mapping of which UI element refreshes on which state-scope
token (GROUPS, DEVICES, DEVICE_MEMBERSHIP, DEVICE_SPECIALS,
PRESETS) is in
../host/ARCHITECTURE.md §"UI Scope
Matrix".
Quickbuttons in the RaceLink panels¶
| Button | What it does |
|---|---|
rl_btn_set_defaults |
Apply preset defaults across the fleet |
rl_btn_force_groups |
Re-broadcast every device's stored groupId — the recovery action when nodes have been reflashed or moved between gateways |
rl_btn_get_devices |
Run Discover Devices |
rl_run_autodetect |
Trigger the auto-detect workflow |
run_quickset |
Apply the currently-selected preset and brightness to the selected group |
The quickset drop-downs (group, preset) re-populate via state-scope events; if a drop-down looks stale, click the RaceLink Refresh button or trigger any other action that fires a state update.
Race-event integration¶
RotorHazard fires events on Evt.STARTUP, Evt.SHUTDOWN,
Evt.RACE_START, Evt.RACE_FINISH, Evt.RACE_STOP etc. The plugin's
onStartup is wired to claim the gateway via discoverPort({});
onShutdown releases it via transport.close().
Race-event-bound effects. The plugin's ActionEffect hooks let you bind RaceLink scenes or presets to RotorHazard race events (e.g. "fire scene
Race StartonEvt.RACE_START"). The binding shape is currently RotorHazard-side configuration — see the RotorHazard documentation for ActionEffect basics.
Gateway ownership in plugin mode¶
The plugin owns the USB-LoRa gateway exclusively. RotorHazard does not open the dongle; only the plugin does. Consequence:
- Do not run
racelink-standaloneand the plugin against the same dongle. The second one fails withPORT_BUSY. - On RotorHazard restart, the plugin re-claims the port. If a
WebUI tab is open during the restart, it briefly shows the
"Gateway not available" banner; it self-clears once
discoverPortsucceeds.
For the architecture-level rule see
../host/ARCHITECTURE.md §"Gateway
Ownership".
What the plugin does NOT do¶
Some host-side features are only exposed in the shared WebUI
(mounted at /racelink inside the RotorHazard process), not in
the RotorHazard side panels. These include:
- The Scenes page (full editor with cost estimator).
- The OTA / Firmware Update dialog.
- The RL Presets dialog.
- The Specials dialog per device.
Open the RaceLink WebUI by navigating to <rotorhazard-host>:5000/racelink
(or whatever path RotorHazard mounts the plugin at — typically
/racelink). The shared WebUI is the same UI that
racelink-standalone exposes.
Online vs. offline installation¶
The plugin supports two installation modes; both load
racelink-host from the same RotorHazard Python environment:
| Mode | What happens |
|---|---|
| Online | RotorHazard installs the plugin and resolves the host wheel from the immutable Git tag declared in the manifest. Requires internet. |
| Offline | The release ZIP contains the host wheel under custom_plugins/racelink_rh_plugin/offline_wheels/. On first plugin start, the bundled host wheel is installed locally before the plugin continues. The first offline start can take a moment. |
See README.md §"Installation Modes" for the full
flow. The online installation uses a git+https://... dependency
format because that is what RHFest accepts — see
ADR-0001.
Troubleshooting¶
- "RaceLink Gateway is not available" stays red after a
RotorHazard restart. Click Retry connection in the WebUI.
The plugin's startup hook claims the gateway on
Evt.STARTUP; if the event sequence misfires, the explicit retry forces anotherdiscoverPortattempt. PORT_BUSYon plugin start. Another process owns the dongle. Most commonlyracelink-standaloneleft running. Stop it, then Retry connection.- RaceLink panels are stale or blank. A state-scope sync failure during plugin bootstrap. Restart RotorHazard once; the plugin's bootstrap re-registers the panels.
RHUI Redefining ...log spam. Should not happen post-D4 (audit batch). If it does, the bootstrap-flag mechanism in the plugin'sui.pyis regressed; file a bug.