Skip to content

librescoot-vehicle (vehicle-service)

Description

The vehicle service implements the vehicle state machine, managing transitions between states like stand-by, parked, ready-to-drive, and shutting-down. It monitors GPIO inputs (kickstand, brakes, blinker switch, seatbox button, handlebar sensors), controls PWM outputs (8-channel LED system, blinker LEDs, seatbox lock, handlebar lock), and coordinates with other services via Redis to determine when the vehicle is ready to drive.

Command-Line Options

Usage of vehicle-service:
  -log int
        Service log level (0=NONE, 1=ERROR, 2=WARN, 3=INFO, 4=DEBUG) (default 3)

Note: vehicle-service has minimal command-line options. Redis host and port are hardcoded to 127.0.0.1:6379. Most configuration is done via Redis and hardware interfaces.

Redis Operations

Hash: vehicle

Fields written:

  • state - Vehicle state (see States section below)
  • brake:left - Left brake state ("on", "off")
  • brake:right - Right brake state ("on", "off")
  • blinker:state - Blinker active state ("on", "off")
  • blinker:start_nanos - Monotonic start time of current blinker cycle (for UI sync)
  • blinker:switch - Blinker switch position ("left", "right", "both", "off") (horn:button and seatbox:button are not written to the vehicle hash in this release. Each horn/seatbox edge is latched into a separate buttons hash instead, as horn:on / horn:off / seatbox:on / seatbox:off set to the literal "1" and never cleared.)

  • seatbox:lock - Seatbox lock state ("open", "closed")

  • kickstand - Kickstand position ("up", "down")
  • handlebar:position - Handlebar position ("on-place", "off-place")
  • handlebar:lock-sensor - Handlebar lock sensor ("locked", "unlocked")
  • dbc-updating - DBC update in progress flag
  • dashboard:power - Dashboard power state ("on", "off")
  • update:status - Aggregated update status surface for UI
  • auto-standby-remaining - Seconds remaining until auto-standby (absent when timer not running)
  • auto-standby-deadline - Unix timestamp of auto-standby deadline (absent when timer not running)

Published channel: vehicle

Lists consumed (BRPOP)

  • scooter:state - State change commands ("lock", "unlock", "lock-hibernate", "force-lock")
  • scooter:seatbox - Seatbox commands ("open")
  • scooter:horn - Horn commands ("on", "off")
  • scooter:blinker - Blinker commands ("left", "right", "both", "off")
  • scooter:hop-on - Hop-on mode commands:
  • engage - Enter the locked hop-on state (lock screen, LED cue, steering lock with the same positioning grace window as parked->stand-by: locks at once if the handlebar is already in position, otherwise the rider has the lock window to move it fully left; publishes state=hop-on)
  • engage-learning - Enter combo-learning state quietly (no LED cue, no steering lock, no lock screen; publishes state=hop-on-learning)
  • release - Exit either hop-on sub-state back to parked
  • scooter:led:cue - LED cue playback commands (integer cue index)
  • scooter:led:fade - LED fade playback commands ("channel:fadeIndex")
  • scooter:update - Update commands ("start", "complete", "start-dbc", "complete-dbc", "cycle-dashboard-power")
  • scooter:hardware - Hardware control commands ("dashboard:on", "dashboard:off", "engine:on", "engine:off", "handlebar:lock", "handlebar:unlock")

Hashes read

  • dashboard - Reads ready field to check if dashboard initialized
  • settings - Reads behavior settings (e.g., scooter.brake-hibernation)
  • ble - Reads status field (Bluetooth link "connected"/"disconnected") to drive lock-on-disconnect
  • ota - Reads OTA status for DBC updates (status:dbc)
  • system - Reads keycard-master-count and keycard-authorized-count to resolve the usb0 gate

Channels subscribed (PUBSUB)

  • dashboard - Dashboard ready notifications (payload: "ready")
  • keycard - Keycard authentication events (payload: "authentication")
  • ota - OTA update notifications
  • power-manager - Power manager events
  • vehicle - Vehicle state change notifications
  • settings - Settings update notifications (payload: setting key that changed)
  • ble - Bluetooth link status change notifications (payload: "status")

Channels published

  • vehicle - All vehicle state changes and sensor updates
  • buttons - Raw input edges for immediate UI response (horn, seatbox, brakes, blinkers)
  • input-events - Synthesized gestures (tap, long-tap, hold, double-tap) over the same inputs

Commands sent to other services

  • scooter:power - Hibernation command ("hibernate-manual")

Vehicle States

The service implements the canonical vehicle state machine with these states:

  • init - Initial/uninitialized state
  • stand-by - Powered but motor disabled
  • parked - Unlocked with kickstand down
  • ready-to-drive - All conditions met, motor enabled
  • waiting-seatbox - Waiting for seatbox to close
  • shutting-down - Transitioning to power down (~4s)
  • updating - OTA firmware update in progress
  • hibernation - Manual hibernation super-state (entered via brake-lever hold from parked)
  • hibernation-initial-hold - 15-second initial brake hold phase
  • hibernation-awaiting-confirm - Confirmation phase (30s timeout after brakes released; continuous hold also auto-confirms)
  • hibernation-seatbox - Confirmation blocked by open seatbox; prompts user to close it
  • hibernation-confirm - Final 3-second non-abortable hibernation confirmation
  • at-rest - Parent state grouping parked, hop-on, hop-on-learning. Owns the auto-standby timer; sibling transitions inside the group don't disturb it. Never the leaf, so vehicle:state never reads at-rest.
  • hop-on - Hop-on/hop-off mode (rider briefly off, motor disabled, optional steering lock, lock screen rendered by dashboard). Physical inputs are gated declaratively via BlockedEvents on the FSM state.
  • hop-on-learning - Combo-learning sibling of hop-on: same input gating (no horn / blinker / brake LED / seatbox open / hibernation hold) but no LED cue, no steering-lock attempt, no lock screen. The dashboard renders its own learn overlay.

Hibernation State Machine

The manual hibernation sequence works as follows:

  1. parkedhibernation-initial-hold (15s): Both brakes pressed continuously
  2. hibernation-initial-holdhibernation-awaiting-confirm: After 15s, enter confirmation phase
  3. hibernation-awaiting-confirm: User can release brakes or keep holding
  4. If brakes released: 30s timeout starts (can be reset by touching brakes)
  5. If brakes held continuously for 30s total: auto-confirm (skip seatbox check)
  6. If brakes re-pressed after release: hold for 15s to auto-confirm
  7. Keycard tap or continuous hold timeout: Check safety conditions (kickstand down, seatbox closed)
  8. If seatbox open: transition to hibernation-seatbox and wait for user to close it
  9. hibernation-confirm: 3-second final countdown before hibernation

See States Documentation for complete state machine.

Hardware Interfaces

GPIO Inputs (via /dev/input)

  • Input device: /dev/input/by-path/platform-gpio-keys-event

Monitored inputs:

  • kickstand - Kickstand position sensor (true = down, false = up)
  • brake_left - Left brake lever sensor (true = pressed)
  • brake_right - Right brake lever sensor (true = pressed)
  • blinker_left - Left blinker button
  • blinker_right - Right blinker button
  • horn_button - Horn button
  • seatbox_button - Seatbox unlock button
  • seatbox_lock_sensor - Seatbox lock position sensor (true = closed, false = open)
  • handlebar_position - Handlebar position sensor (true = on-place, false = off-place)
  • handlebar_lock_sensor - Handlebar lock sensor (true = unlocked, false = locked)
  • 48v_detect - 48V power detection

GPIO Outputs (via gpiocdev)

Digital outputs:

  • seatbox_lock - Seatbox lock solenoid (GPIO chip 2, line 10) - pulsed for 200ms
  • horn - Horn control (GPIO chip 2, line 9)
  • engine_brake - Motor brake control (GPIO chip 2, line 11)
  • handlebar_lock_close - Handlebar lock motor close (GPIO chip 4, line 6) - pulsed for 1100ms
  • handlebar_lock_open - Handlebar lock motor open (GPIO chip 4, line 7) - pulsed for 1100ms
  • dashboard_power - Dashboard power enable (GPIO chip 1, line 18)
  • engine_power - Motor controller power enable (GPIO chip 2, line 17)

PWM LED System

The service controls 8 PWM LED channels via the imx_pwm_led kernel module:

LED device paths: /dev/pwm_led0 through /dev/pwm_led7

PWM Configuration:

  • Period: 12000 ticks
  • Prescaler: 0 (default)
  • Invert: 0 (default)
  • Repeat: 3

LED patterns:

  • Fades: /usr/share/led-curves/fades/fade* (up to 4096 samples per fade)
  • Cues: /usr/share/led-curves/cues/cue* (up to 16 cues)

Blinker timing:

  • Blinker interval: 800ms

Configuration

Systemd Unit

  • Unit file: /usr/lib/systemd/system/librescoot-vehicle.service
  • Binary: /usr/bin/vehicle-service
  • Started by: systemd at boot (after valkey.service; redis.service before Librescoot 1.2)
  • Restart policy: Always
  • Priority: Nice value -10
  • User: root
  • Type: idle

Observable Behavior

Startup Sequence

  1. Connects to Redis at 127.0.0.1:6379
  2. Reads saved vehicle state from Redis (if any)
  3. Reads brake hibernation setting from Redis (settings hash, scooter.brake-hibernation)
  4. Checks if DBC update is in progress (restores dbcUpdating flag if needed)
  5. Reloads PWM LED kernel module (rmmod imx_pwm_led && modprobe imx_pwm_led)
  6. Waits for /dev/pwm_led0 to appear (up to 1 second)
  7. Initializes hardware:
  8. Opens all 8 LED device files (/dev/pwm_led0 through /dev/pwm_led7)
  9. Configures PWM parameters for each channel
  10. Sets adaptive mode for non-blinker LEDs (channels 0, 1, 2, 5)
  11. Activates all LED channels
  12. Loads LED fades and cues from /usr/share/led-curves/
  13. Plays initial LED cue (cue 0)
  14. Opens GPIO input device
  15. Opens GPIO output lines
  16. Reads settings[scooter.usb0-policy] and brings usb0 up unless the auto policy is already effective (see below)
  17. Checks initial handlebar lock sensor state
  18. Registers input callbacks for all monitored inputs
  19. Publishes initial sensor states to Redis
  20. Restores LED state based on saved vehicle state (if parked or ready-to-drive)
  21. Marks system as initialized
  22. Handles initial dashboard ready state (if dashboard was already ready)
  23. Publishes initial vehicle state to Redis
  24. Transitions from init to stand-by if still in init state
  25. Starts Redis listeners (PUBSUB and BRPOP)

vehicle-service owns whether usb0 (the USB gadget link to the DBC, 192.168.7.1) is administratively up. 10-usb0.network carries no ActivationPolicy, so networkd configures the address and raises the link; vehicle-service takes it down again once it applies the policy.

The scooter.usb0-policy setting picks the intent:

Value Meaning
auto Default. The link tracks vehicle[dashboard:power], so it is down whenever the DBC is off.
always-on The link is held up regardless of dashboard power, for installer and diagnostic reachability.

auto is gated on keycard pairings, because usb0 is also the way back into a scooter whose cards do not work. The gate is closed (the policy takes effect) only once (master >= 1 AND authorized >= 1) OR authorized >= 2, read from system[keycard-master-count] and system[keycard-authorized-count]. Below that threshold the link is held up as if the policy were always-on.

An absent count reads as zero rather than as "not yet known", so during the first seconds of a boot the gate resolves as if no cards were paired and the link is simply held up. There is no waiting resolver, no system[usb0-gate] field and no boot failsafe timer in this release.

The gate is re-read at each existing decision point (startup, a dashboard:power change, and a scooter.usb0-policy change) rather than subscribed to. Pairing a second card mid-install therefore does not take usb0 away from a running installer session; the tighter policy applies from the next transition.

State Machine Behavior

Ready-to-Drive Conditions

Vehicle enters ready-to-drive when ALL are true:

  • Dashboard ready (dashboard hash ready field = "true")
  • Kickstand up
  • Current state is parked

Manual Ready-to-Drive Activation: In parked state, if dashboard is not ready, pressing the seatbox button while:

  • Kickstand is up
  • Both brakes are held

Will manually transition to ready-to-drive and blink the main light once for confirmation.

Lock/Unlock Handling

Lock command (LPUSH scooter:state lock):

  1. Must be in parked state
  2. Transitions to shutting-down
  3. After ~4 seconds, transitions to stand-by
  4. Power manager then suspends/hibernates

Unlock command (LPUSH scooter:state unlock):

  1. Reads kickstand state
  2. If dashboard ready and kickstand up: transitions to ready-to-drive
  3. Otherwise: transitions to parked (if currently in stand-by)

Lock-Hibernate command (LPUSH scooter:state lock-hibernate):

  1. Must be in parked state
  2. Sets hibernation request flag
  3. Transitions to shutting-down
  4. Sends "hibernate-manual" command to power manager via scooter:power list

Force-Lock command (LPUSH scooter:state force-lock):

  1. Sets forceStandbyNoLock flag
  2. Immediately transitions to stand-by without handlebar locking
  3. Used for emergency shutdown or special cases (e.g., DBC update)

Hibernation Sequence

Brake-lever hibernation (can be disabled via settings hash scooter.brake-hibernation = "disabled"):

  1. Trigger: Both brakes pressed in parked state for 15 seconds
  2. Initial Hold (15s): Brakes must be held continuously
  3. If brakes released: sequence cancelled, return to parked
  4. After 15s: transition to waiting-hibernation state
  5. Confirmation Phase:
  6. User can release brakes or keep holding
  7. If brakes released: 30-second timeout starts
    • Timeout can be reset by touching brakes again
    • If timeout expires: cancel hibernation, return to parked
  8. If brakes held continuously for 30s total from start: auto-confirm (warehouse mode)
  9. If brakes re-pressed after release: hold for 15s to auto-confirm
  10. Keycard tap during confirmation: triggers immediate safety check and confirmation
  11. Safety Checks:
  12. Kickstand must be down (always required)
  13. Seatbox must be closed (skipped for auto-confirm scenarios)
  14. If seatbox open: transition to waiting-hibernation-seatbox state to notify user
  15. Final Confirmation:
  16. Transition to waiting-hibernation-confirm state
  17. 3-second non-abortable countdown
  18. Then transition to shutting-down with hibernation flag
  19. Send "hibernate-manual" command to power manager

Keycard force-standby:

  • Tap keycard 3 times while holding brake lever
  • Immediately transitions to stand-by without handlebar lock
  • Useful for emergency situations or servicing

Blinker Control

The service implements automatic blinker logic:

  • Blink interval: 800ms
  • Physical blinker switches only work in active states (parked, ready-to-drive, waiting states)
  • In other states, blinker control comes from software commands only
  • LED cues used:
  • Cue 9: LED_BLINK_NONE (blinkers off)
  • Cue 10: LED_BLINK_LEFT (left blinker)
  • Cue 11: LED_BLINK_RIGHT (right blinker)
  • Cue 12: LED_BLINK_BOTH (hazard lights)
  • Publishes blinker switch and state changes to Redis
  • Publishes immediate button events to buttons channel for UI response
Hazard switch detection - Librescoot 1.2+

The stock handlebar switch offers left and right only, on separate GPIO inputs (blinker_left, blinker_right). Aftermarket switch assemblies with a physical hazard button close both inputs at once, which the earlier code could not represent: the press registered as left or right, never both.

handleBlinkerChange now reads the peer switch out of the activeKeys cache when a blinker event fires. io.go updates activeKeys before invoking each callback, so the second event's handler always sees the first switch as already active. Both active means a combined blinker:switch of both and LED cue 12, which drives the hazard lights. If the peer read fails the handler falls back to the last known state rather than assuming off, since assuming off would collapse a real hazard state into left/right/off and publish a misleading edge.

The buttons PUBSUB event always reflects the triggering channel's own edge, independently of the combined switch state. Releasing one side of a hazard pair therefore emits blinker:right:off even though the combined state moves to left rather than off. Consumers that track edges stay correct; consumers that want the combined position read blinker:switch.

Stock switches are unaffected: the peer input is never active, so every transition behaves exactly as before.

Seatbox Control

Open command (LPUSH scooter:seatbox open):

  1. Pulses seatbox lock solenoid for 200ms
  2. Publishes seatbox opened event to vehicle channel (payload: "seatbox:opened")

Button press:

  • In parked state: pressing seatbox button opens seatbox
  • In other states: button press is logged but no action taken
  • Button events published to buttons channel for UI feedback
  • Pressing seatbox button cancels any active hibernation sequence

Brake Control

Brake state handling:

  • Brake pressed: plays LED cue 4 (LED_BRAKE_OFF_TO_BRAKE_ON)
  • Brake released: plays LED cue 5 (LED_BRAKE_ON_TO_BRAKE_OFF)
  • Engine brake logic:
  • In ready-to-drive: engine brake follows brake levers (engaged if either pressed)
  • In all other states: engine brake always engaged (motor disabled)
  • Brake state published to Redis (vehicle hash, brake:left and brake:right)
  • Button events published to buttons channel for immediate UI response

Park debounce:

  • After entering ready-to-drive, kickstand down events are ignored for 1 second
  • Prevents accidental transition to parked during kickstand retraction

Gesture Detection (input-events) - Librescoot Only

Alongside the raw edges on buttons, vehicle-service runs a gesture detector (internal/core/input_gestures.go) over the horn button, seatbox button and both brake levers, publishing <source>:<gesture> on the input-events channel.

Sources: horn, seatbox, brake:left, brake:right.

Gesture Fires when Threshold
press Input goes active -
release Input goes inactive -
long-tap Still held after the long-tap delay 800 ms
hold Still held after the hold delay 3 s
tap Released before the long-tap threshold -
double-tap Second tap within the double-tap window 800 ms

long-tap and hold fire while the input is still down, so a 4-second press emits press, long-tap, hold, release and no tap. Emitting a long-tap or hold clears the pending tap, so a long press between two taps does not glue them into a double-tap.

Each gesture is emitted exactly once, which makes input-events the channel to use for anything counting or reacting to discrete user actions. buttons carries the raw edges; the vehicle hash carries the current level. See the Redis reference.

Command Processing

Commands are consumed via BRPOP with 5-second timeout:

  • scooter:state - State change commands
  • scooter:seatbox - Seatbox control
  • scooter:horn - Horn control
  • scooter:blinker - Blinker control
  • scooter:led:cue - LED cue playback
  • scooter:led:fade - LED fade playback
  • scooter:update - Update coordination
  • scooter:hardware - Direct hardware control

Fault Detection

The service supports fault reporting via Redis:

  • Faults are added to the vehicle:fault set (using SADD)
  • Fault events are logged to the events:faults stream (using XADD)
  • Fault notifications published to vehicle channel (payload: "fault")
  • Fault codes are numeric identifiers
  • Cleared faults are reported with negative code values

Current implementation does not actively monitor for faults, but the infrastructure is in place for future fault detection.

Log Output

The service logs to journald. Common log patterns:

  • State transitions (e.g., "Transitioning from PARKED to READY_TO_DRIVE")
  • Input events (e.g., "Input kickstand => true")
  • Command processing (e.g., "Received command from scooter:state: lock")
  • Redis operations (e.g., "Publishing vehicle state: parked")
  • Hardware operations (e.g., "Seatbox lock toggled for 0.2s")
  • LED operations (e.g., "Playing LED cue 4")
  • Hibernation sequence events
  • Button events published to UI
  • Settings updates

Log levels:

  • 0 = NONE: No logging
  • 1 = ERROR: Fatal errors only
  • 2 = WARN: Warnings and errors
  • 3 = INFO: Informational messages (default)
  • 4 = DEBUG: Detailed debugging output

View logs:

journalctl -u librescoot-vehicle.service
journalctl -u librescoot-vehicle.service -f  # Follow mode
journalctl -u librescoot-vehicle.service --since "10 minutes ago"

Dependencies

Required:

  • Redis server - Must be running at 127.0.0.1:6379
  • GPIO input device - /dev/input/by-path/platform-gpio-keys-event
  • GPIO chip devices - For digital outputs (gpiochip1, gpiochip2, gpiochip4)
  • PWM LED kernel module - imx_pwm_led must be loadable
  • PWM LED device files - /dev/pwm_led0 through /dev/pwm_led7
  • LED curve files - /usr/share/led-curves/fades/ and /usr/share/led-curves/cues/

Optional:

  • dashboard - Service waits for dashboard ready = "true" before allowing ready-to-drive
  • keycard - Authentication via keycard events
  • settings-service - For persistent settings like brake-hibernation
  • update-service - For OTA update coordination
  • power-manager - For hibernation execution

Librescoot Implementation Details

The Librescoot vehicle-service is a Go-based implementation with the following architecture:

Technical Implementation

  • Language: Go (Golang)
  • Concurrency: Uses goroutines for parallel I/O handling
  • GPIO library: github.com/warthog618/go-gpiocdev for digital I/O
  • Redis library: github.com/redis/go-redis/v9 for Redis operations
  • System calls: golang.org/x/sys/unix for low-level hardware access
  • Binary size: Optimized for ARM Cortex-A7 architecture
  • Cross-compilation: Supports AMD64 for development/testing

Key Features

  • Enhanced LED control: Full 8-channel PWM LED system with adaptive and active/inactive modes
  • Robust hibernation: Multi-stage hibernation state machine with safety checks
  • Settings integration: Dynamic settings updates via Redis PUBSUB
  • Update coordination: Handles DBC dashboard updates with power state management
  • Button feedback: Immediate button event publishing for responsive UI
  • State persistence: Saves and restores vehicle state across reboots
  • Graceful shutdown: Proper cleanup of hardware resources and timers

LED Channel Mapping

Librescoot vehicle-service controls 8 PWM LED channels:

Index LED Name Description Mode
0 Headlight Main front illumination Adaptive
1 Front ring Front accent lighting Adaptive
2 Brake light Rear brake indicator Adaptive
3 Blinker front left Left front turn signal Active/Inactive
4 Blinker front right Right front turn signal Active/Inactive
5 Number plates License plate illumination Adaptive
6 Blinker rear left Left rear turn signal Active/Inactive
7 Blinker rear right Right rear turn signal Active/Inactive

LED Channel Modes

  • Adaptive Mode (channels 0,1,2,5): When enabled, the channel adapts fade playback by finding the first duty-cycle value in the fade that is nearest to the current duty-cycle, then starting the fade from that point. This prevents abrupt brightness jumps during transitions between different LED states. Non-blinker channels use adaptive mode for smooth transitions.

  • Active/Inactive Mode (channels 3,4,6,7): Controls whether fade values are actually output to the LED. When active, fade values are set as the channel's duty-cycle normally. When inactive, the output is forced to 0% regardless of the fade being played. Blinker channels rely on precise active/inactive control for their flashing patterns and do NOT use adaptive mode.

Kernel module: The PWM LED system is implemented via the imx_pwm_led kernel module, which provides /dev/pwm_led* character devices for each channel. The service reloads this module on startup to ensure clean state.

See i.MX PWM LED kernel module documentation for detailed mode specifications and ioctl interface.

Special Features

DBC Update Support: During DBC (Dashboard Controller) firmware updates:

  • Dashboard power is kept on regardless of vehicle state
  • Power state changes are deferred until update completes
  • Dashboard power can be cycled remotely via scooter:update command
  • Service tracks update status via ota hash status:dbc field

Force Standby: Three keycard taps while holding brake lever triggers immediate transition to standby without handlebar lock. Useful for:

  • Emergency situations
  • Service/warehouse operations
  • Forcing standby when handlebar lock is non-functional

Settings Integration: The service responds to settings changes via PUBSUB:

  • scooter.brake-hibernation: "enabled" or "disabled"
  • Changes take effect immediately
  • Active hibernation sequences are cancelled when disabled

Architecture

Package structure:

  • cmd/vehicle-service/ - Main entry point
  • internal/core/ - Core system logic and state machine
  • internal/hardware/ - Hardware I/O abstraction (GPIO, LED)
  • internal/messaging/ - Redis communication layer
  • internal/types/ - Shared type definitions
  • internal/logger/ - Leveled logging implementation

Concurrency model:

  • Main goroutine handles system coordination
  • Separate goroutines for:
  • Redis PUBSUB listener
  • 8 Redis BRPOP command listeners (one per list)
  • Blinker timer (when active)
  • Various hardware timers (hibernation, shutdown, handlebar lock)
  • Thread-safe state access via sync.RWMutex

Error handling:

  • Hardware errors are logged but don't crash the service
  • Redis disconnection causes service exit (systemd will restart)
  • Invalid commands are logged and rejected
  • State transition errors are logged and may be retried

Building

# Build for ARM Cortex-A7 (default target)
make build

# Build for AMD64 (development/testing)
make build-amd64

# Output: bin/vehicle-service

Compatibility

Librescoot vehicle-service maintains Redis protocol compatibility:

  • Same hash fields and structure as original implementation
  • Same command interface (LPUSH to command lists)
  • Same PUBSUB channel usage
  • Compatible with any dashboard that follows the Librescoot Redis protocol
  • No changes required to other services

Integration Points

Librescoot vehicle-service integrates with:

  • Redis - Central message bus (required)
  • Dashboard service - Waits for ready signal before allowing drive
  • Settings service - Reads persistent behavior settings
  • Update service - Coordinates OTA firmware updates
  • Power manager - Sends hibernation commands
  • Keycard service - Receives authentication events
  • UI/HMI - Publishes button events for immediate feedback