Skip to content

lsc - Librescoot Control CLI

lsc is a command-line interface for controlling and monitoring Librescoot electric scooters via Redis. It provides a convenient, user-friendly interface to all Librescoot services and features.

Overview

The lsc tool acts as a bridge between human operators and the Librescoot Redis-based communication system. Instead of manually crafting Redis commands, you can use intuitive commands to:

  • Control vehicle state (lock/unlock, hibernate)
  • Monitor system status and diagnostics
  • Manage OTA updates
  • Configure settings
  • View logs and events
  • Control hardware components

Installation

The lsc binary is typically installed to /usr/bin/lsc on Librescoot systems.

Manual installation:

# From the lsc source directory
make build              # Build for ARM
make build-native       # Build for local platform

# Or manually
GOOS=linux GOARCH=arm GOARM=7 go build -o lsc .

Global Flags

All commands support these global flags:

  • --json - Output in JSON format for automation and scripting
  • --redis-addr <host:port> - Redis server address (default: 192.168.7.1:6379)
  • --no-block - Don't wait for state change confirmation (vehicle commands only)

Commands

Vehicle Control

Control vehicle state and hardware.

# Lock the scooter (also via: lsc lock)
lsc vehicle lock

# Unlock the scooter (also via: lsc unlock)
lsc vehicle unlock

# Force standby without waiting for locks
lsc vehicle force-lock

# Lock and request hibernation
lsc vehicle hibernate

# Open seatbox (also via: lsc open)
lsc vehicle open

Redis operations:

  • Sends commands to scooter:state list (lock, unlock, force-lock, lock-hibernate)
  • Sends commands to scooter:seatbox list (open)
  • Monitors vehicle hash for state changes

Power Management

Control system power states.

# Show power manager status
lsc power status

# Set power state to run (normal operation, highest priority)
lsc power run

# Set power state to suspend (low power)
lsc power suspend

# Set power state to hibernate (power off)
lsc power hibernate

# Hibernate for a specific duration; nRF52 wakes the iMX6 afterwards
lsc hibernate-for 8h
lsc power hibernate-for 30m       # equivalent

# Cancel a pending hibernate-for and disarm the wake timer
lsc hibernate-cancel
lsc power hibernate-cancel        # equivalent

# Reboot the system
lsc power reboot

Schedule a recurring hibernation via the settings interface:

lsc settings set pm.scheduled-hibernate-cron "0 22 * * *"
lsc settings set pm.scheduled-hibernate-duration 8h
lsc settings set pm.scheduled-hibernate-enabled true

Redis operations:

  • Sends commands to scooter:power list
  • Reads from power-manager hash

Service Management

Manage systemd services with convenient shorthand names.

# List all services with status
lsc service list
lsc svc list         # Short alias

# Start/stop/restart a service
lsc svc start vehicle
lsc svc stop battery
lsc svc restart ecu

# Enable/disable service on boot
lsc svc enable alarm
lsc svc disable modem

# Show service status
lsc svc status pm

# View service logs
lsc svc logs vehicle
lsc svc logs battery --follow        # Follow in real-time (-f)
lsc svc logs valkey --lines 100      # Show 100 lines (-n 100)

Service name shortcuts (from serviceNameMap in cmd/lsc/service/service.go; a name with no entry is passed through with .service appended):

  • vehiclelibrescoot-vehicle.service
  • batterylibrescoot-battery.service
  • eculibrescoot-ecu.service
  • modemlibrescoot-modem.service
  • alarmlibrescoot-alarm.service
  • settingslibrescoot-settings.service
  • keycardlibrescoot-keycard.service
  • boot-ledlibrescoot-boot-led.service
  • bluetoothlibrescoot-bluetooth.service
  • umslibrescoot-ums.service
  • brightnesslibrescoot-brightness.service
  • onbootlibrescoot-onboot.service
  • backlightdbc-backlight.service
  • pmlibrescoot-pm.service
  • updatelibrescoot-update.service
  • versionlibrescoot-version.service
  • netconfiglibrescoot-netconfig.service

The datastore alias is special-cased: lsc asks systemd whether valkey.service is loaded and uses it if so, falling back to redis.service. Both shorthands hit whichever unit the image actually ships, so a script written against either name works on both sides of the Librescoot 1.2 switch. lsc service list shows the resolved name in its first row.

Older lsc builds (up to and including v0.6.6) had no such resolution: redis resolved literally, so the datastore row read inactive / not-found on 1.2 images and status, restart and logs failed for it.

System integration:

  • Uses systemctl commands via D-Bus
  • Uses journalctl for log retrieval

LED Control

Control LED cues and fade animations.

# Trigger LED cue by index
lsc led cue <index>

# Trigger LED fade animation
lsc led fade <channel> <index>

Redis operations:

  • Sends commands to scooter:led:cue list
  • Sends commands to scooter:led:fade list

Battery Diagnostics

View detailed battery information.

# Show all batteries
lsc battery
lsc bat              # Short alias

# Show specific battery
lsc battery 0
lsc bat 1

# JSON output for scripting
lsc battery --json

Redis operations:

  • Reads from battery:0 and battery:1 hashes

GPS Tracking

Monitor GPS status and location.

# Show GPS status
lsc gps status

# Watch GPS location in real-time
lsc gps watch

# JSON output
lsc gps status --json

Redis operations:

  • Reads from gps hash
  • Subscribes to gps channel for real-time updates

Alarm System

Control the motion-based alarm system.

# Check alarm status
lsc alarm status

# Enable the alarm
lsc alarm arm

# Disable the alarm
lsc alarm disarm

# Manually trigger the alarm
lsc alarm trigger

Redis operations:

  • Sends commands to scooter:alarm list (enable, disable, start, stop)
  • Reads from alarm hash
  • Reads from settings hash (alarm.enabled, alarm.honk)

Settings Management

View and modify scooter configuration.

# List all settings
lsc settings

# Get a specific setting (also via: lsc get)
lsc settings get alarm.enabled
lsc get scooter.mode

# Set a setting (also via: lsc set)
lsc settings set alarm.honk true
lsc set scooter.speed_limit 25

# Delete a setting (also via: lsc del)
lsc settings del custom.field
lsc del custom.field

Common settings:

  • alarm.enabled - Enable/disable alarm system (true/false)
  • alarm.honk - Enable horn during alarm (true/false)
  • alarm.duration - Alarm duration in seconds
  • alarm.seatbox-trigger - Trigger alarm on unauthorized seatbox opening (true/false)
  • alarm.hairtrigger - Enable hair trigger mode (true/false)
  • alarm.hairtrigger-duration - Hair trigger alarm duration in seconds
  • scooter.speed_limit - Speed limit in km/h
  • scooter.mode - Drive mode (eco/sport)
  • cellular.apn - Cellular APN configuration
  • updates.mdb.channel - MDB update channel (stable/testing/nightly)
  • updates.dbc.channel - DBC update channel

Redis operations:

  • Reads/writes settings hash
  • Publishes to settings channel for changes

OTA Updates

Manage over-the-air updates.

# View OTA update status
lsc ota status

# Install update from local file
lsc ota install /path/to/update.mender

# Install update from URL
lsc ota install https://example.com/update.mender

# JSON output
lsc ota status --json

Redis operations:

  • Reads from ota hash (status:mdb, status:dbc, download-progress, etc.)
  • Sends commands to scooter:update list (check-now)

Diagnostics

System diagnostics and fault monitoring.

# Show firmware versions (also via: lsc ver)
lsc diag version
lsc version

# Show active faults (also via: lsc faults)
lsc diag faults
lsc faults

# View fault event stream (also via: lsc events)
lsc diag events
lsc events

# Follow events in real-time
lsc events --follow

# Show events since duration
lsc events --since 1h
lsc events --since 24h
lsc events --since 7d

# Filter events by regex
lsc events --filter "battery.*"

# Control blinkers
lsc blinkers off
lsc blinkers left
lsc blinkers right
lsc blinkers both

# Control horn
lsc diag horn on
lsc diag horn off

# Control handlebar lock
lsc diag handlebar lock
lsc diag handlebar unlock

Redis operations:

  • Reads firmware versions from the system hash
  • Reads from vehicle:fault, battery:0:faults and battery:1:faults sets
  • Reads from events:faults stream using XREAD
  • Sends commands to scooter:blinker, scooter:horn, scooter:handlebar lists

Hardware Control

Direct hardware control commands.

# Control dashboard power (also via: lsc dbc)
lsc dashboard on
lsc dashboard off
lsc dbc on
lsc dbc off

# Control engine power (also via: lsc engine)
lsc engine on
lsc engine off

Redis operations:

  • Sends commands to scooter:hardware list (dashboard:on, dashboard:off, engine:on, engine:off)

Status Overview

Get overall system status.

# Show comprehensive status
lsc status

# JSON output for automation
lsc status --json

Shows summary of:

  • Vehicle state
  • Motor status (speed, odometer, temperature)
  • Battery status for all batteries
  • Power manager state
  • GPS status
  • Internet connectivity
  • Active faults

Real-time Monitoring

Monitor Redis pub/sub channels and record metrics.

# Watch Redis pub/sub channels
lsc watch

# Record metrics over time
lsc monitor

Redis operations:

  • Subscribes to all channels and displays real-time updates
  • Samples and logs metrics at intervals

Log Extraction

Collect service journals, dmesg and a Redis snapshot into one archive.

# All services, last 24h, into /data/log-bundles
lsc logs

# One service, shorter window
lsc logs vehicle --since 1h

# Several services, explicit window and destination
lsc logs battery ecu --since 24h --output /data/debug

# Errors only
lsc logs all --priority err

Flags:

  • --since <time> - Start of the journal window, default 24h. Bare durations (30m, 1h, 1d, 2w) are rewritten to journalctl's "N units ago"; anything containing a space, - or : is passed through as an absolute timestamp
  • --until <time> - End of the window, default now
  • --priority <level> - journalctl priority filter (err, warning, info, debug)
  • --output <dir> - Where the archive is written, default /data/log-bundles

Service names (from serviceMap in cmd/lsc/logs/logs.go; unknown names are skipped with a warning): vehicle, battery, ecu/motor, modem, pm/power, update, settings, keycard, bluetooth/ble, ums, radio-gaga/uplink, all (the default).

One logs-<timestamp>.tar.gz lands in the output directory. The tree is staged in a .staging-<timestamp> sibling and removed once the archive is written:

logs-2025-10-25-13-54/
  metadata.json               bundle format 2: collected_at, since, until, hosts, tool, services, priority
  mdb/
    metadata.json             hostname, boot_timestamp, uptime_seconds, kernel_release, os_release_*, byte counts
    dmesg.log
    librescoot-vehicle.log    one journalctl dump per requested service, short-monotonic format
    librescoot-battery.log
    redis/
      vehicle.json            one HGETALL snapshot per hash, ':' becomes '-' in the filename
      battery-0.json
      version-mdb.json

Redis operations:

  • HGETALL over settings, vehicle, gps, battery:0, battery:1, aux-battery, cb-battery, engine-ecu, power-manager, modem, internet, alarm, ble, system, dashboard, ota, power-mux, version:mdb, version:dbc. A hash that is missing or empty writes no file

redis/events-faults.log is the fault history, oldest entry first:

# events:faults (Redis stream, oldest first)
# stream-id  time-utc  event  group  code  description
1761400443123-0  2025-10-25T13:54:03.123Z  RAISE  vehicle  3  CAN bus timeout
1761400500456-0  2025-10-25T13:55:00.456Z  CLEAR  vehicle  3

The time comes from the millisecond component of the entry ID, the only clock the stream carries. A clear is stored as the raised code with a leading minus and renders as CLEAR against the code it refers to. Missing fields print -.

The file is always written. A scooter that raised no faults this boot has no events:faults key at all, and that case gets the two header lines plus # no fault events recorded, so an empty history stays distinguishable from a capture that failed. The entry count also lands in mdb/metadata.json as fault_events.

Saved Locations

Manage GPS location bookmarks (if supported by implementation).

# Manage saved locations
lsc locations

JSON Output Mode

All commands support --json flag for automation:

# Get structured output
lsc status --json | jq '.vehicle.state'
lsc battery --json | jq '.[0].charge'
lsc settings --json | jq '.["alarm.enabled"]'

# Check if alarm is enabled
if [ "$(lsc get alarm.enabled --json | jq -r .value)" = "true" ]; then
  echo "Alarm is enabled"
fi

# Get battery charge percentage
CHARGE=$(lsc bat 0 --json | jq '.charge')
echo "Battery charge: $CHARGE%"

Shell Completion

Generate completion scripts for your shell:

# Bash
lsc completion bash > /etc/bash_completion.d/lsc
source /etc/bash_completion.d/lsc

# Zsh
lsc completion zsh > "${fpath[1]}/_lsc"

# Fish
lsc completion fish > ~/.config/fish/completions/lsc.fish

# PowerShell
lsc completion powershell > lsc.ps1

After installing completion, you can use Tab to autocomplete commands, flags, and arguments.

Common Use Cases

Check System Health

# Quick status check
lsc status

# Check for faults
lsc faults

# View battery health
lsc battery

Lock/Unlock Scooter

# Lock (will wait for state change confirmation)
lsc lock

# Unlock
lsc unlock

# Force lock without waiting
lsc lock --no-block

# Lock and hibernate
lsc vehicle hibernate

Configure Alarm

# Enable alarm
lsc set alarm.enabled true

# Enable horn during alarm
lsc set alarm.honk true

# Arm the alarm
lsc alarm arm

# Check alarm status
lsc alarm status

Monitor Updates

# Check update status
lsc ota status

# Watch for update progress
watch -n 1 lsc ota status

# JSON monitoring
watch -n 1 'lsc ota status --json | jq'

Debugging Services

# List all services
lsc svc list

# Check specific service
lsc svc status vehicle

# View logs
lsc svc logs vehicle --follow

# Restart problematic service
lsc svc restart modem

Tracking Location

# Show current GPS status
lsc gps status

# Watch location in real-time
lsc gps watch

# Get coordinates in JSON
lsc gps status --json | jq '.latitude, .longitude'

Architecture

lsc communicates with Librescoot services via Redis:

Command Pattern

Commands are sent using LPUSH to command lists:

LPUSH scooter:state lock
LPUSH scooter:alarm enable
LPUSH scooter:power hibernate

State Reading

Current state is read from Redis hashes:

HGETALL vehicle
HGETALL battery:0
HGETALL power-manager

State Monitoring

Real-time updates via pub/sub:

SUBSCRIBE vehicle
SUBSCRIBE gps
SUBSCRIBE alarm

Event History

Historical events via streams:

XREAD STREAMS events:faults 0

Error Handling

lsc provides clear error messages for common issues:

  • Redis connection failed: Check Redis server is running and accessible
  • Command timeout: Service may not be running or responding
  • Invalid setting: Check setting key spelling and format
  • Permission denied: Check user has access to systemd commands

Development

Source: github.com/librescoot/lsc

# Build for development
cd lsc
go build -o lsc .

# Build for target (ARM)
make build

# Run tests
go test ./...

# Install
sudo cp lsc /usr/bin/