Radio Gaga Configuration
Every option in the radio-gaga config file, what it does, and the values we recommend.
Contents
Overview
Radio Gaga is the small Go service that connects your scooter to Sunshine. It reads a single YAML config file at startup: scooter identity, broker connection, how often to report telemetry, which remote commands are allowed, and optional notifications.
You normally never write this file by hand. When you generate a token in Sunshine, the installer drops a ready-to-run config on the scooter. This page documents what is in that file and what you can change if you want to tune behaviour.
Durations use Go syntax: 500ms, 10s, 5m, 2h, 24h. There is no d unit, so a day is 24h.
The config file
The file location depends on the firmware:
- Stock ScooterOS:
/etc/rescoot/radio-gaga.yml - LibreScoot:
/data/radio-gaga/config.yaml
The systemd unit starts the service with radio-gaga -config <path>. After editing the file, restart the service to apply changes:
systemctl restart radio-gaga
A minimal config, unix style
The generated config keeps only the keys that matter: your scooter's identity, the broker, and the handful of values that differ from radio-gaga's built-in defaults. Everything else is left commented out so you can see the option and uncomment it to override. Anything you delete falls back to its default.
scooter:
identifier: WUN... # your VIN (MQTT username)
token: 64charsha256... # MQTT password
mqtt:
broker_url: ssl://mqtt.sunshine.rescoot.org:8883
keepalive: 180s
ca_cert_embedded: |
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
telemetry:
intervals:
standby: 30m
standby_no_battery: 2h
transmit_period: 15m
buffer:
enabled: true
max_retries: 50
retry_interval: 5m
The full annotated example with every option lives in the radio-gaga repo as radio-gaga.example.yml.
Connection: scooter, MQTT, Redis
scooter
| Key | Default | What it does |
|---|---|---|
| identifier | required | Vehicle id (VIN). Used as the MQTT username. |
| token | required | Authentication token (MQTT password). |
| name | - | Optional friendly name, cosmetic only. |
mqtt
| Key | Default | What it does |
|---|---|---|
| broker_url | required | ssl://mqtt.sunshine.rescoot.org:8883 |
| ca_cert | - | Path to the broker CA certificate file. |
| ca_cert_embedded | - | CA certificate inline (PEM). Takes precedence over ca_cert. This is what the installer uses. |
| keepalive | 30s | MQTT keepalive. Sunshine ships 180s to be gentle on flaky cellular links. |
redis_url, ntp, environment
| Key | Default | What it does |
|---|---|---|
| redis_url | redis://127.0.0.1:6379 | On-board Redis the scooter's services use. Leave as-is. |
| ntp.enabled | true | Sync the clock on boot (the scooter has no RTC battery). |
| ntp.server | pool.ntp.rescoot.org | NTP server to use. |
| environment | production | production or development. The shell command only works in development. |
Telemetry intervals and priorities
Two mechanisms decide when the scooter publishes data. They work together.
telemetry.intervals - periodic snapshots
A full telemetry snapshot is sent on a timer chosen by the vehicle's power state. Lower values mean fresher data but more cellular traffic.
| Key | Default | Recommended | When it applies |
|---|---|---|---|
| driving | 30s | 30s or higher | While moving. Keep this at 30s or more; lower floods the broker. |
| standby | 5m | 30m | Parked, battery present. |
| standby_no_battery | 8h | 2h - 8h | Parked, no main battery. |
| hibernate | 24h | 24h | Deep sleep. Minimal keepalive. |
telemetry.priorities - change-driven flushing
Between snapshots, when a field changes, radio-gaga schedules an early publish. Each field has a priority, and the priority sets the deadline: the longest a changed field waits before being sent. This stops analog noise on battery and engine fields from firing a publish on every millivolt blip, while still pushing important changes quickly.
The four deadlines must stay ordered: immediate ≤ quick ≤ medium ≤ slow. Lower is more responsive but costs more traffic.
| Priority | Default | Fields |
|---|---|---|
| immediate | 10s | Vehicle state, lock status, blinkers. |
| quick | 30s | GPS, battery charge level. |
| medium | 5m | Most other fields. |
| slow | 1h | Aux battery, connectivity battery, BLE status. |
Dropping immediate too low brings back the data spam these deadlines exist to prevent. 10s keeps lock and state changes timely without publishing on every toggle.
Buffering and events
When the broker is unreachable (tunnel, dead spot, maintenance), telemetry is buffered and replayed on reconnect with the original timestamps. The on-disk path is auto-detected; you cannot set it in the config (older configs that did are ignored).
| Key | Default | What it does |
|---|---|---|
| telemetry.buffer.enabled | false | Buffer telemetry while offline. Sunshine ships true. |
| telemetry.buffer.max_size | 1000 | Max buffered records before the oldest are dropped. |
| telemetry.buffer.max_retries | 5 | Send attempts per batch. |
| telemetry.buffer.retry_interval | 1m | Gap between retries. |
| telemetry.transmit_period | 5m | How often the buffer is drained. |
| events.enabled | true | Detect and publish discrete events (alarm, movement, faults). |
| events.max_retries | 10 | Send attempts per event before giving up. |
Commands
Remote commands are enabled by default. You only list a command under commands: to disable it or to tune its parameters. ping and get_state can never be disabled.
To disable a command:
commands:
shell:
disabled: true
Some commands take parameters. These go under a params: map. The alarm params can be written either nested (shown) or as flat dotted keys (hazards.flash: true); both resolve the same way.
commands:
honk:
params:
on_time: 100ms # horn pulse for a single honk
locate:
params:
honk_time: 40ms # length of each locate beep
honk_interval: 80ms # gap between the two beeps in a pair
interval: 4s # gap between the two beep pairs
alarm:
params:
hazards:
flash: true
horn:
honk: true
on_time: 400ms
off_time: 400ms
Telegram notifications
Radio Gaga can send alerts straight to a Telegram chat (alarm triggered, unauthorized movement, low battery, and so on) without going through Sunshine. Setting it up takes about five minutes.
-
1
Create a bot. In Telegram, message @BotFather, send
/newbot, and follow the prompts (pick a name and a username ending inbot). BotFather replies with a bot token that looks like123456789:AAH.... -
2
Start a chat with your bot. Open your new bot and send it any message (for example
hi). A bot cannot message you until you have messaged it first. -
3
Find your chat id. Open this URL in a browser, replacing
<token>with your bot token:
https://api.telegram.org/bot<token>/getUpdates
Look for "chat":{"id":123456789 in the JSON. That number is your chat id. For a group chat the id is negative (for example -1001234567890); add the bot to the group first, then send a message there.
Now add the block to your config:
telegram:
enabled: true
bot_token: "123456789:AAH..."
chat_id: "123456789"
rate_limit: 1s # minimum gap between messages
queue_size: 100
daily_limit: 0 # 0 = unlimited
events:
alarm: true
unauthorized_movement: true
battery_warning: true
temperature_warning: true
state_change: false
connectivity: false
fault: false
If you leave out the events: map, the first four (alarm, unauthorized movement, battery warning, temperature warning) are on and the rest are off. Restart radio-gaga and trigger the alarm once to confirm a message arrives.
Rule-based notifications and SMS
Beyond the built-in Telegram events, you can write your own rules. Each rule watches a Redis field (or a raw message), and when its conditions match, it routes a message to Telegram, SMS, or both. Rules are checked on every change, so a cooldown is usually a good idea.
notifications:
rules:
- name: "cbb_low"
conditions:
- source: "cb-battery" # Redis hash to watch
field: "charge"
operator: "<" # <, >, <=, >=, ==, !=
value: "50"
channels: [telegram]
cooldown: "30m"
message: "CB battery at {{cb-battery.charge}}%" # {{source.field}} placeholders
- name: "alarm_while_parked" # multiple conditions are ANDed
conditions:
- source: "alarm"
field: "status"
operator: "=="
value: "triggered"
- source: "vehicle"
field: "state"
operator: "=="
value: "standby"
channels: [telegram, sms]
A condition matches either a hash field (field + operator + value) or a raw pub/sub payload (message: "==" or message: "contains" + value). You cannot set both on one condition.
SMS goes out through the cellular modem via ModemManager (mmcli), so it only works on hardware with a modem:
notifications:
sms:
enabled: false
phone_number: "+491234567890"
rate_limit: "30s" # minimum gap between messages
daily_limit: 20 # 0 = unlimited
queue_size: 20
Command-line flags
Most settings live in the config file, but a few flags are handy for one-off runs and debugging. Flags override the config file. The systemd unit only passes -config.
-config string path to config file (default: radio-gaga.yml) -identifier string vehicle identifier (MQTT username) -token string authentication token (MQTT password) -mqtt-broker string MQTT broker URL -mqtt-cacert string path to MQTT CA certificate -mqtt-keepalive MQTT keepalive (default: 30s) -redis-url string Redis URL (default: redis://localhost:6379) -environment string production or development -debug enable debug logging -driving-interval telemetry interval while driving (default: 30s) -standby-interval telemetry interval in standby (default: 5m) -transmit-period buffer transmission period (default: 5m) -version print version and exit
Changing config at runtime
You do not have to SSH in and restart the service to change a setting. Radio Gaga accepts remote config commands that take effect immediately, addressing keys with dot notation:
config:get- read a key, for exampletelemetry.intervals.drivingconfig:set- change a key. Applies right away, in memory.config:del- remove a key (reverting it to its default).config:save- persist the current in-memory config to disk. Creates a backup of the previous file first.
So the usual flow is config:set to try a value, then config:save once you are happy with it. Without a save, the change is lost on the next restart. These commands are issued for you from Sunshine's admin scooter config editor; you rarely send them by hand.
Other options
| Key | Default | What it does |
|---|---|---|
| unu_uplink.enabled | false | On stock firmware, point the legacy unu-uplink service at this broker and restart it. Only touches the config if it still points at the defunct unu cloud. |
| service_name | auto-detected | systemd unit radio-gaga manages itself as (for self-update). |
| debug | false | Verbose logging. Same as the -debug flag. |
Need to get a scooter online in the first place? See the setup guide.