System States Documentation¶
Vehicle States¶
The scooter's operational mode is tracked via the vehicle:state Redis key and BLE characteristic 9a590021.
Canonical Vehicle States¶
These are the exact string values that appear in Redis and BLE:
- "unknown" - Initial/uninitialized state
- "stand-by" - Systems powered but motor disabled, ready for authentication
- "parked" - Vehicle unlocked with kickstand down or not ready to drive
- "hop-on" - Locked hop-on / hop-off mode: rider briefly off, motor disabled, optional steering lock; dashboard renders a lock overlay
- "hop-on-learning" - Combo-learning sibling of hop-on: same input gating but no user-facing LED cue, no steering-lock attempt, no lock screen
- "ready-to-drive" - Full system power, motor enabled, kickstand up, all conditions met
- "waiting-seatbox" - Transitional state waiting for seatbox to close
- "shutting-down" - Transitional state before powering down (~5s)
- "updating" - OTA firmware update in progress
- "waiting-hibernation" - Manual hibernation sequence initiated (60s timeout)
- "waiting-hibernation-advanced" - Advanced hibernation wait (brakes held for 10s+)
- "waiting-hibernation-seatbox" - Hibernation wait with seatbox open notification
- "waiting-hibernation-confirm" - Hibernation confirmation screen (3s)
At-rest grouping. Internally, parked, hop-on, and hop-on-learning are children of an at-rest parent state in the FSM. The parent owns the auto-standby timer, so the timer keeps running across hop-on detours without manual handoff. The parent is never published as vehicle:state — only its leaves are.
External representation of the hop-on family. vehicle-service publishes the leaf states as-is. Downstream consumers collapse them when their audience does not need to distinguish:
| Leaf state | Cloud (uplink, radio-gaga) | nRF wire value | BLE characteristic 9a590021 string |
|---|---|---|---|
hop-on |
stand-by (locked) |
6 (HOP_ON) |
stand-by (cloaked by firmware) |
hop-on-learning |
parked |
1 (PARKED) |
parked |
The wire value 6 is dedicated so the firmware picks POWER_MODE_ACTIVE (parked-equivalent rails: PMIC_EN2 on, AUX battery) while still surfacing the BLE state-string as stand-by to mobile apps that have no concept of hop-on. See nRF UART Protocol and BLE Services.
Note: Vehicle states are separate from power manager states (tracked in power-manager:state). Vehicle states represent the operational mode of the scooter, while power manager states represent the system's power/suspend state.
Vehicle State Transitions¶
stateDiagram-v2
[*] --> unknown
unknown --> stand-by: init complete (initial state)
unknown --> updating: init complete (updating)
unknown --> ready-to-drive: init complete (default)
stand-by --> ready-to-drive: keycard auth / unlock request
ready-to-drive --> parked: kickstand down (after 1s timer)
ready-to-drive --> ready-to-drive: conditions still met
parked --> ready-to-drive: kickstand up + all conditions met
parked --> waiting-seatbox: keycard auth (when not activating)
parked --> shutting-down: lock request
parked --> waiting-hibernation-confirm: lock-hibernate request
parked --> waiting-hibernation: hibernation timer (manual)
parked --> hop-on: scooter:hop-on engage
parked --> hop-on-learning: scooter:hop-on engage-learning
hop-on --> parked: scooter:hop-on release / unlock request
hop-on-learning --> parked: scooter:hop-on release / unlock request
hop-on --> shutting-down: lock / keycard / auto-standby
hop-on-learning --> shutting-down: lock / keycard / auto-standby
waiting-seatbox --> ready-to-drive: seatbox closed + conditions met
waiting-seatbox --> parked: seatbox closed (not ready)
waiting-seatbox --> shutting-down: keycard auth / lock request
waiting-seatbox --> ready-to-drive: unlock request
waiting-seatbox --> waiting-hibernation-confirm: lock-hibernate request
shutting-down --> stand-by: timeout (~5s)
updating --> shutting-down: update complete / not updating
updating --> shutting-down: timeout (30min abort)
updating --> ready-to-drive: keycard auth / unlock request
waiting-hibernation --> waiting-hibernation-seatbox: keycard tap (seatbox open)
waiting-hibernation --> waiting-hibernation-advanced: brakes held (10s timer)
waiting-hibernation --> ready-to-drive: timeout (60s) / kickstand raised / unlock
waiting-hibernation --> shutting-down: lock request
waiting-hibernation --> waiting-hibernation-confirm: lock-hibernate request
waiting-hibernation-advanced --> ready-to-drive: brakes released
waiting-hibernation-advanced --> waiting-hibernation-confirm: keycard auth
waiting-hibernation-seatbox --> waiting-hibernation: seatbox closed
waiting-hibernation-seatbox --> waiting-hibernation-confirm: keycard auth
waiting-hibernation-confirm --> shutting-down: timeout (3s, then hibernate)
Key Transition Conditions¶
is_ready_to_drive()¶
Vehicle can enter "ready-to-drive" when ALL conditions are met: - Dashboard ready - Kickstand up - Seatbox lock closed - Not activating - Handlebar unlocked - Battery on
Hibernation Sequence¶
Manual hibernation requires: 1. Both brakes pressed 2. Dashboard ready 3. Not activating
Flow: parked (15s) → waiting-hibernation (brakes held 10s) → waiting-hibernation-advanced → waiting-hibernation-confirm (keycard) → shutting-down (3s) → stand-by (with hibernation flag)
Park Protection¶
1-second timer prevents rapid drive → park → drive oscillations
Power Manager States¶
The power manager (unu-pm) tracks system power states separately from vehicle states. These are exposed via power-manager:state Redis key and BLE characteristic 9a5900a1:
Power States¶
- "booting" - System starting up
- "running" - System fully operational
- "suspending" - System entering suspend mode
- "suspending-imminent" - Suspend about to occur (pre-suspend delay active)
- "hibernating" - System in hibernation
- "hibernating-imminent" - Hibernation about to occur
- "hibernating-manual" - Manual hibernation requested
- "hibernating-manual-imminent" - Manual hibernation about to occur
- "hibernating-timer" - Timer-based hibernation (configurable, default 5 days)
- "hibernating-timer-imminent" - Timer hibernation about to occur
- "reboot" - System reboot
- "reboot-imminent" - Reboot about to occur
State Suffixes¶
The "-imminent" suffix indicates that a power state change is about to occur but the pre-suspend delay is still active. This gives services time to complete operations and prevents data loss.
Power State Transitions¶
stateDiagram-v2
[*] --> booting
booting --> running: boot complete (~5s)
running --> suspending-imminent: suspend request
suspending-imminent --> suspending: pre-suspend delay (~60s)
suspending-imminent --> running: abort suspend
suspending --> hibernating-imminent: low battery / hibernate request
suspending --> running: wakeup
hibernating-imminent --> hibernating: iMX6 power down (~20s)
hibernating-imminent --> running: abort hibernation
hibernating --> booting: wakeup (brakes/BLE)
running --> reboot-imminent: reboot request
reboot-imminent --> reboot: pre-reboot delay
reboot --> booting: system restart
nRF Hibernation Levels¶
When in "hibernating" power state, the nRF firmware distinguishes between two hibernation levels based on CB battery charge:
- L1 (Level 1) - Triggered at CB battery ≤25% SoC
- CB battery continues to power control electronics
- Periodic wakeup checks for brake lever activation
-
Low battery wakeup at 10% SoC
-
L2 (Level 2) - Triggered at CB battery ≤5% SoC
- System switches to AUX battery to preserve CB battery
- Minimal power consumption
- Wakeup only via brake levers
See nRF Power Management for details.
Battery States¶
Main Battery¶
Tracked per battery slot (battery:0, battery:1) via Redis and BLE:
- "unknown" - State cannot be determined
- "asleep" - Lowest power state, NFC wake detection active
- "idle" - Systems powered, high current path disabled
- "active" - Full power state, high current path enabled, required for driving/charging
Connectivity Battery (CB)¶
- "not-charging" - Battery discharging
- "charging" - Battery charging (current > ~100mA)
- "unknown" - State cannot be determined
Auxiliary Battery (AUX)¶
Hardware-controlled charging states:
- "not-charging" - Not charging
- "bulk-charge" - Maximum current charging for depleted battery
- "absorption-charge" - Constant voltage as battery approaches full charge
- "float-charge" - Maintenance mode for fully charged battery