Skip to content

Configuration

Configuration is carried by the root config oneof using ConfigMessage.

Commands

Command Client intent Device response
GET read current config result=OK, current=<snapshot>
SET apply a partial patch result=OK, INVALID, or STORE_ERROR, plus current=<snapshot>
RESET reset to defaults result=OK, INVALID, or STORE_ERROR, plus current=<snapshot>
NOTIFY not a normal client request; used by firmware for change notifications current=<snapshot> when processed

The firmware currently handles any incoming ConfigMessage regardless of the root Reaction.type; test tooling sends GET as Query and SET/RESET as Command.

Patch Semantics

ConfigPatch is partial. Only fields present in the patch are applied.

Color patches are also partial. For example, a patch can update only red inside power_led_color.

After applying a patch, firmware validates the full candidate config before saving it. If validation fails, the previous config remains active and the response result is INVALID.

Defaults

Defaults from DeviceConfig:

Field Default
schema_version 1
revision 0
timer_60_seconds 60
timer_120_seconds 120
timer_530_single_seconds 5
timer_530_double_seconds 30
contest_seconds 150
contest_pause_seconds 30
timer_expired_holdoff_ms 2000
pairing_timeout_ms 60000
contest_gap_ms 4000
buzzer_volume_percent 100
power_led_color { red: 0, green: 0, blue: 20 }
active_top_red_team { red: 25, green: 0, blue: 0 }
active_top_green_team { red: 0, green: 20, blue: 0 }
active_front_red_team { red: 40, green: 0, blue: 0 }
active_front_green_team { red: 0, green: 20, blue: 0 }
idle_front_red_team { red: 1, green: 0, blue: 0 }
idle_front_green_team { red: 0, green: 1, blue: 0 }
idle_top_red_brightness 1
idle_top_green_brightness 1
ble_read_only_color { red: 24, green: 12, blue: 0 }
ble_write_authorized_color { red: 0, green: 24, blue: 0 }
ble_pairing_color { red: 0, green: 20, blue: 20 }
ble_pin_max_failures 3
ble_pin_lockout_ms 300000
ble_stale_bond_quick_timeout_ms 3000
ble_stale_bond_strikes 2
bleed_mode_enabled false

Validation Rules

Validation runs after protobuf fields are converted into the C++ DeviceConfig types. Some protobuf uint32 fields are cast to uint8_t before validation, including colors, buzzer volume, idle top brightness, PIN failure count, and stale-bond strike count. Values above 255 can wrap during that conversion rather than being rejected as large protobuf values.

After conversion, the current firmware rejects configs when:

  • schema_version is not 1
  • any timer duration, timer holdoff, or pairing timeout listed in validation is zero
  • buzzer_volume_percent is greater than 100
  • contest_gap_ms is greater than 30000
  • ble_pin_max_failures is zero or greater than 10
  • ble_pin_lockout_ms is less than 1000 or greater than 3600000
  • ble_stale_bond_quick_timeout_ms is less than 100 or greater than 30000
  • ble_stale_bond_strikes is zero or greater than 10

Color validation currently accepts all converted color values. In C++, colors are stored as uint8_t, and protobuf color components are cast to that width before validation.

Change Notifications

When a config update is committed and BLE peers are connected, the BLE task sends a config notification:

Reaction {
  type: Update
  config {
    command: NOTIFY
    result: OK
    current: ...
  }
}

If no BLE peers are connected, the firmware observes the config change but skips the notification.