Mikkeli Matlock 58a523aab2 ui: gps compass widget layout changes
- angular direction (0-359) + 16ths compassrose
- documented in ui README
2026-02-08 03:06:52 +09:00
2026-02-04 09:59:25 +09:00
2026-02-04 23:19:24 +09:00
2026-02-08 03:06:52 +09:00
2026-01-24 23:18:06 +09:00
2026-01-26 01:03:23 +09:00

Smart Serow

Pi Zero 2W + Arduino Nano motorcycle info terminal.

Architecture

┌─────────────────┐      ┌─────────────────┐
│  Arduino Nano   │──────│  Pi Zero 2W     │
│  (sensors)      │ UART │  (Flutter UI)   │──── Display
└─────────────────┘      └─────────────────┘
  • Pi Zero 2W: Runs Flutter UI via DRM/KMS (direct framebuffer, no X11)
  • Arduino Nano: Sensor interface (future)

Project Structure

smart-serow/
├── arduino/                # Arduino sketches (sensor interface)
├── extra/                  # Assets deployed alongside app
│   ├── fonts/              # Custom fonts
│   ├── images/             # Static images
│   └── themes/             # Theme JSON files (→ generate_theme.py)
├── pi/
│   ├── ui/                 # Flutter app
│   │   ├── lib/
│   │   │   ├── main.dart           # Entry point
│   │   │   ├── app_root.dart       # Screen state management
│   │   │   ├── screens/            # Full-screen views
│   │   │   ├── widgets/            # Reusable components
│   │   │   ├── services/           # Singletons (config, sensors, theme)
│   │   │   └── theme/              # Colors and theme provider
│   │   └── config.json             # Runtime config (navigator, paths)
│   └── backend/            # Python GPS service (Flask + gpsd)
├── scripts/                # Build, deploy, and setup helpers
└── pi_sysroot/             # Pi libraries for cross-linking (gitignored)

Theme System

The UI uses JSON-based themes for different navigator models.

  • Theme files: extra/themes/{navigator}.json (e.g., extra/themes/zumo.json)
  • Generation: scripts/generate_theme.py converts JSON → pi/ui/lib/theme/app_colors.dart
  • Auto-generation: build.py runs theme generation before each Flutter build
  • Fallback chain: Tries {navigator}.jsondefault.json → hardcoded defaults

To add a new theme, create extra/themes/yourmodel.json and set "navigator": "yourmodel" in pi/ui/config.json.


Build Environment Setup (WSL2)

Requirements

Pi Sysroot (for cross-linking)

The ARM64 linker needs Pi's shared libraries to resolve symbols at link time. These don't execute locally - the linker just reads their symbol tables.

On the Pi, grab the libs:

tar czf pi_libs.tar.gz \
    /lib/aarch64-linux-gnu \
    /usr/lib/aarch64-linux-gnu

In WSL2, extract to project root:

mkdir -p pi_sysroot
tar xzf pi_libs.tar.gz -C pi_sysroot --strip-components=1

Key libraries needed:

  • libxkbcommon, libEGL, libdrm, libgbm, libinput
  • libudev, libsystemd, libfontconfig

Target Environment (Pi Zero 2W)

Requirements

  • Debian Trixie (glibc 2.38 - must match build host!)
  • Display connected via HDMI/DSI

First-Time Setup

# Copy scripts to Pi
scp scripts/pi_setup.sh scripts/smartserow-ui.service user@pi.local:~/

# Run setup on Pi
ssh user@pi.local
chmod +x pi_setup.sh
./pi_setup.sh

This installs:

  • Runtime dependencies (libgl, libgles, libdrm, libgbm, libinput, fonts)
  • Systemd service for auto-start
  • User permissions for DRM/KMS access

Build & Deploy

python3 scripts/build-deploy.py          # Build, deploy, restart
python3 scripts/build-deploy.py --clean  # Clean build first
python3 scripts/build-deploy.py --no-restart  # Don't restart service

Individual scripts

# Build only
python3 scripts/build.py
python3 scripts/build.py --clean

# Deploy only
python3 scripts/deploy.py
python3 scripts/deploy.py --restart

Build output: pi/ui/build/elinux/arm64/release/bundle/

Deploy config

Copy and edit scripts/deploy_target.sample.jsonscripts/deploy_target.json:

{
  "user": "pi",
  "host": "raspberrypi.local",
  "remote_path": "/opt/smartserow",
  "service_name": "smartserow-ui"
}

Verify

ssh user@pi.local 'systemctl status smartserow-ui'
ssh user@pi.local 'journalctl -u smartserow-ui -f'  # Live logs

Display Backends

Flutter-elinux supports multiple backends. We use GBM (DRM/KMS direct).

Backend Use Case Notes
gbm Production Direct framebuffer, fast boot, no X11
x11 Debug Needs X server, mouse/keyboard friendly
wayland - Requires compositor, more dependencies

The backend is compiled in (we build with --target-backend-type=gbm). The -b flag is for bundle path, not backend selection.

For X11 debugging, you'd need to rebuild with --target-backend-type=x11.


Known Issues / Gotchas

glibc version mismatch

Build host and Pi must have matching glibc. We use Debian Trixie on both. Symptom: GLIBC_2.xx not found at runtime.

CMake caches compiler

If you change cross-compiler settings, run ./scripts/build.sh --clean.

flutter-elinux generates all platforms

The flutter-elinux create command scaffolds android/ios/web/etc. These are gitignored - we only need elinux/ and linux/.

Libs not found at runtime

If libflutter_engine.so not found, check LD_LIBRARY_PATH in the service file. Should point to /opt/smartserow/bundle/lib.


Development Tips

Local testing (Linux desktop)

cd pi/ui
flutter-elinux run -d linux

Check what a binary needs

# On Pi
ldd /opt/smartserow/bundle/smartserow_ui

Pi service management

sudo systemctl start smartserow-ui
sudo systemctl stop smartserow-ui
sudo systemctl restart smartserow-ui
journalctl -u smartserow-ui -f
Description
Onboard computer for a Serow 250.
Readme WTFPL 328 KiB
Languages
Dart 49.6%
Python 37.8%
C++ 7.7%
Shell 3.1%
C 1.8%