Extensible Infotainment System for Automotive Applications
- Overview
- Key Features
- Architecture
- Quick Start
- Installation
- User Stories
- Development
- Performance
- Documentation
- Contributing
- License
- Community
Crankshaft is a modern, extensible infotainment system designed for automotive applications running on Raspberry Pi 4 and compatible Linux platforms. Built with C++20 and Qt6, Crankshaft provides a slim, high-performance core with a robust extension framework that supports multiple programming languages (C/C++, Python, Node.js).
The system features Android Auto integration (wired and wireless), multi-display support, and a responsive, driver-safe UI that follows Design for Driving guidelines. Crankshaft is production-ready with comprehensive testing, security hardening, and performance monitoring.
- Extensibility: Plugin-based architecture with sandboxed extensions
- Performance: Cold start ≤10s, Android Auto connect ≤15s, UI interactions ≤200ms
- Safety: Driver-focused UX with limited distractions and large touch targets
- Modularity: Loosely coupled core with event-driven communication
- Security: Validated inputs, sandboxed extensions, secure WebSocket (wss) ready
- Resource Efficiency: Optimised for embedded systems (≤1.5 GB memory target)
-
Android Auto Integration: Full support for wired and wireless Android Auto via AASDK
- Media playback, navigation, messaging, and voice assistant
- Automatic device detection and connection
- Session persistence and reconnection
-
Multi-Display Support: Run on physical (EGLFS) and virtual (VNC) displays
- Independent displays for navigation, media controls, and settings
- Hot-plug detection for USB displays
- Resolution-adaptive layouts
-
Extension Framework: Robust plugin system with manifest-based configuration
- Sandboxed extension processes with permission model
- WebSocket-based event bus for inter-process communication
- REST API for diagnostics and health checks
- Support for C/C++, Python, Node.js extensions
-
Modern, Responsive Design: Built with Qt6/QML
- Light and dark themes (toggle via Settings)
- Smooth animations and transitions
- Touch-optimised with 48dp minimum targets
- Automotive-grade contrast ratios (4.5:1 minimum)
-
Internationalisation: Multi-language support (i18n ready)
- Default: English (UK)
en-GB - Included: German (Germany)
de-DE - Easy addition of new locales
- Default: English (UK)
-
Driver Safety: Compliant with Design for Driving principles
- Limited keyboard input while driving
- Simplified navigation with minimal steps
- High-contrast glanceable information
-
Media Services: Audio playback with PipeWire (preferred) or PulseAudio
- Bluetooth audio streaming
- Radio tuner integration
- USB media playback
-
Database: SQLite-backed persistence
- User preferences and settings
- Android Auto device and session history
- Extension configuration
-
Diagnostics & Monitoring: Real-time performance profiling
- Memory and CPU metrics
- WebSocket connection tracking
- Request latency monitoring with percentiles (p50, p95, p99)
- Alert system with WARNING/CRITICAL thresholds
- Prometheus export for Grafana integration
-
Security & Compliance: Production-ready hardening
- Input validation with JSON schema
- Allowlisted service commands
- Extension sandboxing with manifest permissions
- Audit logging for sensitive operations
- GDPR-compliant data handling
Crankshaft uses a multi-process architecture with loosely coupled components communicating via WebSocket and Qt signals:
┌─────────────────────────────────────────────────────────────┐
│ Crankshaft System │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ Core Daemon │◄───────►│ UI Client │ │
│ │ (C++/Qt6) │ WS/QT │ (Qt6/QML) │ │
│ └──────┬───────┘ └──────────────┘ │
│ │ │
│ │ WebSocket Event Bus (JSON Messages) │
│ │ │
│ ┌──────┴─────────────────────────────────────────┐ │
│ │ │ │
│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────┐│ │
│ │ │ Extension 1 │ │ Extension 2 │ │ Ext N ││ │
│ │ │ (Media) │ │ (Radio) │ │ (Custom)││ │
│ │ └─────────────┘ └─────────────┘ └─────────┘│ │
│ │ │ │
│ └──────────────────────────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ External Integrations │ │
│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │
│ │ │Android Auto │ │ PipeWire │ │ SQLite │ │ │
│ │ │ (AASDK) │ │ /PulseAudio│ │ Database │ │ │
│ │ └─────────────┘ └─────────────┘ └─────────────┘ │ │
│ └──────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
| Component | Description | Technologies |
|---|---|---|
| Core Daemon | Central service manager, event bus, Android Auto integration, extension lifecycle management | C++20, Qt6 Core, QWebSocket, AASDK |
| UI Client | User interface for touch displays, theme support, localization | Qt6 QML/Quick, Qt Declarative |
| Extensions | Pluggable services (media, radio, Bluetooth, custom), sandboxed processes | C/C++, Python, Node.js |
| WebSocket Server | Event bus for publish/subscribe messaging, service commands, authentication | Qt6 QWebSocket, JSON validation |
| Diagnostics API | REST endpoints for health checks, metrics, alerts | OpenAPI 3.0, Qt HTTP server |
| Database | Persistent storage for preferences, sessions, device history | SQLite (Qt SQL module) |
WebSocket Messages (JSON over WS):
subscribe/unsubscribe: Topic-based subscriptionspublish/event: Broadcast events to subscribersservice_command/service_response: Request/response RPC pattern- Schema validation:
contracts/ws-schema.json
Event Bus Topics (Examples):
android_auto.device.connected→ New Android Auto device detectedmedia.playback.state_changed→ Media playback state updateui.theme.changed→ User toggled light/dark themeextension.lifecycle.started→ Extension process started successfully
Service Commands (Allowlisted):
get_session_info: Retrieve current Android Auto sessionstart_extension: Launch an extension by IDstop_extension: Gracefully stop an extensionget_preferences: Fetch user preferences by key
- OS: Ubuntu 22.04 LTS or later (native Linux or WSL2)
- RAM: 2 GB minimum (4 GB recommended for build)
- Disk: 6 GB free space
- CPU: 2 cores minimum (4+ recommended for faster builds)
# 1. Install dependencies (Ubuntu 22.04)
sudo apt-get update && sudo apt-get install -y \
build-essential cmake ninja-build pkg-config \
qt6-base-dev qt6-declarative-dev qt6-websockets-dev \
libsqlite3-dev libpipewire-0.3-dev libpulse-dev
# 2. Clone the repository
git clone https://github.com/opencardev/crankshaft-mvp.git
cd crankshaft-mvp
# 3. Build core and UI
mkdir build && cd build
cmake -G Ninja -DCMAKE_BUILD_TYPE=Debug ..
ninja
# 4. Run the application (VNC for testing)
./ui/crankshaft-ui -platform vnc:size=1024x600,port=5900
# Connect via VNC client to localhost:5900For detailed instructions, see Quick Start Guide.
Recommended: Use pre-built DEB packages from the OpenCarDev APT repository:
# Add OpenCarDev repository
curl -fsSL https://packages.opencardev.org/opencardev-apt.asc | sudo gpg --dearmor -o /usr/share/keyrings/opencardev-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/opencardev-archive-keyring.gpg] https://packages.opencardev.org/debian trixie stable" | sudo tee /etc/apt/sources.list.d/opencardev.list
# Install Crankshaft
sudo apt-get update
sudo apt-get install crankshaft-core crankshaft-ui
# Enable and start services
sudo systemctl enable crankshaft-core
sudo systemctl start crankshaft-core
sudo systemctl enable crankshaft-ui
sudo systemctl start crankshaft-uiArchitecture Support:
arm64(64-bit Raspberry Pi OS, recommended)armhf(32-bit legacy support)amd64(Development workstations)
For custom builds or development:
# Cross-compile for Raspberry Pi (on x86_64 host)
./scripts/build-rpi.sh --arch arm64 --build-type Release --package
# Native build (on Raspberry Pi)
./scripts/build.sh --build-type Release --package
# Output: build/*.deb packagesBuild Options:
--build-type: Debug (with symbols) or Release (optimised)--component: Build specific components (core, ui, extensions)--package: Generate DEB packages with CPack--with-tests: Include test executables
US-001: As a driver, I want to connect my Android phone to display Android Auto on the head unit, so I can safely access navigation, media, and messaging while driving.
US-002: As a driver, I want to switch between light and dark themes, so the display is comfortable in different lighting conditions.
US-003: As a driver, I want the system to remember my preferences (volume, last media source, theme), so I don't have to reconfigure after every ignition cycle.
US-004: As a driver, I want large, touch-friendly controls, so I can operate the system safely while the vehicle is in motion.
US-010: As an extension developer, I want to publish events to the event bus, so my extension can notify the UI and other extensions of state changes.
US-011: As an extension developer, I want to declare required permissions in a manifest, so users understand what resources my extension needs.
US-012: As an extension developer, I want a documented REST API for diagnostics, so I can query system health and metrics programmatically.
US-020: As a system integrator, I want to deploy Crankshaft via DEB packages, so I can automate fleet installations with standard package managers.
US-021: As a system integrator, I want to run 24-hour soak tests, so I can validate stability before production deployments.
US-022: As a system integrator, I want Prometheus-compatible metrics, so I can monitor fleet performance with existing observability tools.
Crankshaft uses CMake with Ninja generator for fast incremental builds:
# Configure build
cmake -G Ninja -DCMAKE_BUILD_TYPE=Debug -S . -B build
# Build all targets
cmake --build build --parallel
# Build specific component
cmake --build build --target crankshaft-core
cmake --build build --target crankshaft-ui
# Install to system (requires sudo)
sudo cmake --install build# Run all tests
ctest --test-dir build --output-on-failure
# Run specific test suite
ctest --test-dir build -R WebSocket
# Run with verbose output
ctest --test-dir build --verbose
# Generate coverage report (Debug build with --coverage)
cmake --build build --target coverageTest Coverage (Current):
- Integration Tests: 55/60 passing (91.7%)
- Unit Tests: Core services, WebSocket validation, AndroidAuto lifecycle
- Contract Tests: JSON schema validation for WS messages
# Format C++ code (clang-format)
./scripts/format_cpp.sh fix
# Check formatting
./scripts/format_cpp.sh check
# Lint with clang-tidy
./scripts/lint_cpp.sh clang-tidy
# Static analysis with cppcheck
./scripts/lint_cpp.sh cppcheck
# Check license headers
./scripts/check_license_headers.sh
# Pre-commit checks (format, lint, tests)
# (Automatically runs on git commit if using pre-commit hooks)Real-Time Metrics Dashboard:
# Start metrics collection
curl http://localhost:8080/metrics/summary
# View active alerts
curl http://localhost:8080/metrics/alerts
# Export Prometheus format
curl http://localhost:8080/metrics/prometheus24-Hour Soak Test:
# Run stability test (24 hours)
./tests/integration/soak_test.sh
# Quick validation (1 hour)
./tests/integration/soak_test.sh 1
# Monitor progress
tail -f soak-logs/soak_test.log
# View report
cat docs/SOAK_TEST_RESULTS.mdProfiling Tools:
- Valgrind: Memory leak detection (
valgrind --leak-check=full ./build/core/crankshaft-core) - Heaptrack: Heap profiler (
heaptrack ./build/core/crankshaft-core) - perf: Linux profiler (
perf record -g ./build/core/crankshaft-core)
Creating a New Extension:
- Define Manifest (
extension.json):
{
"id": "org.example.myextension",
"name": "My Extension",
"version": "1.0.0",
"entrypoint": "/usr/lib/crankshaft/extensions/myextension",
"permissions": ["websocket.publish", "preferences.read"],
"resources": {
"cpu_limit": "50%",
"memory_limit": "128MB"
}
}- Implement Extension (Python example):
import json
import websocket
def on_message(ws, message):
event = json.loads(message)
if event['type'] == 'event' and event['topic'] == 'system.startup':
# Publish response
response = {
'type': 'publish',
'topic': 'myextension.ready',
'payload': {'status': 'initialized'}
}
ws.send(json.dumps(response))
if __name__ == '__main__':
ws = websocket.WebSocketApp("ws://localhost:8080/ws",
on_message=on_message)
ws.run_forever()- Register Extension:
# Copy manifest to extensions directory
sudo cp extension.json /etc/crankshaft/extensions/
# Restart core service to load extension
sudo systemctl restart crankshaft-coreExtension API Documentation: See Extension Developer Guide for complete API reference and examples.
| Metric | Target | Measured | Status |
|---|---|---|---|
| Cold Start (Core + UI) | ≤10s | 3.2s avg | ✅ PASS (68% below target) |
| Android Auto Connect | ≤15s | 12.5s avg | ✅ PASS (17% below target) |
| Media Latency (p95) | <200ms | 186ms | |
| Touch Latency | <50ms | 35ms avg | ✅ PASS |
| State | Core Memory | UI Memory | Total | CPU Usage |
|---|---|---|---|---|
| Idle (no AA) | 125 MB | 180 MB | 305 MB | 5% |
| Active (AA + media) | 285 MB | 320 MB | 605 MB | 30.8% |
| Peak (AA + 3 extensions) | 420 MB | 350 MB | 770 MB | 45% |
Performance Monitoring:
- Real-time metrics collected every 60 seconds
- Historical data: 24 hours (1440 samples)
- Alert thresholds: Memory (1536 MB warning, 2048 MB critical), CPU (70% warning, 90% critical)
- Overhead: <0.01% CPU for monitoring
Validated Platforms:
- Raspberry Pi 4 (4GB RAM, arm64, Raspberry Pi OS Bookworm)
- Raspberry Pi 4 (2GB RAM, arm64, optimised build)
- Ubuntu 22.04 LTS (x86_64, WSL2, development)
- Quick Start Guide - Build and run in 5 minutes
- User Manual - Complete feature guide
- FAQ - Common questions and troubleshooting
- Implementation Plan - Technical architecture and decisions
- Data Model - Entities, relationships, schemas
- API Contracts - WebSocket schema, OpenAPI spec
- Extension Development - Create and publish extensions
- Performance Monitoring - Metrics, alerts, dashboards
- Security Guide - Input validation, sandboxing, audit logging
Complete GitHub Actions CI/CD system for building, testing, and releasing Crankshaft:
- CI/CD Overview - Start here for all CI/CD topics
- Workflow Guide - All 6 workflows (quality, build, APT, release, pi-gen, docs)
- Developer Handbook - Your first PR, debugging, best practices
- Maintainer Handbook - Releases, monitoring, incident response
- Troubleshooting Guide - Top 10 issues and solutions
- Architecture Decisions - Why we made key design choices
- Success Criteria Checklist - Validation template
- Soak Test Guide - 24-hour stability testing
- Quickstart Validation - Build validation on Ubuntu 22.04
- Test Plan - Unit, integration, and contract tests
We welcome contributions! Crankshaft is an open-source project under the GPL-3.0 license.
- Fork the repository on GitHub
- Create a feature branch:
git checkout -b feature/my-amazing-feature - Follow coding standards:
- C++: Google C++ Style Guide
- Python: PEP 8
- Use project file headers (see
.github/copilot-instructions.md)
- Write tests: Add unit/integration tests for new features
- Run pre-commit checks:
./scripts/pre-commit-check.sh - Commit with conventional commits:
feat:,fix:,docs:,test:, etc. - Push to your fork:
git push origin feature/my-amazing-feature - Open a Pull Request on GitHub
- All PRs require one approval from a maintainer
- CI must pass (build, tests, linting)
- PRs should address a single concern (no mega-PRs)
- Include documentation updates for user-facing changes
- Bugs: Use the Bug Report template
- Features: Use the Feature Request template
- Security: Email [email protected] (do not open public issues)
This project follows the Contributor Covenant Code of Conduct. Please be respectful and inclusive.
Crankshaft is licensed under the GNU General Public License v3.0.
Project: Crankshaft
Copyright (C) 2025 OpenCarDev Team
Crankshaft is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
Crankshaft is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Crankshaft. If not, see <http://www.gnu.org/licenses/>.
Third-Party Licenses:
- Qt6: LGPL v3
- AASDK: MIT License
- PipeWire: MIT License
- Documentation: docs/ and specs/002-infotainment-androidauto/
- GitHub Discussions: opencardev/crankshaft-mvp/discussions
- Issue Tracker: Report bugs or request features
- GitHub Releases: opencardev/crankshaft-mvp/releases
- Changelog: CHANGELOG.md
- Blog: opencardev.org/blog
Current Status: Production-ready MVP (v1.0.0)
Upcoming Features (v1.1+):
- Extension store with web-based marketplace
- Wireless Android Auto improvements (Wi-Fi Direct)
- Bluetooth hands-free calling (HFP)
- Backup camera integration (V4L2)
- Fleet management API
Long-Term Vision:
- Multi-user profiles with cloud sync
- Voice assistant integration (offline-capable)
- OBD-II diagnostics and vehicle telemetry
- Automotive-grade Linux (AGL) compliance
Crankshaft builds on the excellent work of:
- OpenCarDev community
- AASDK for Android Auto transport layer
- Qt Project for cross-platform UI framework
- PipeWire for modern Linux audio
Special thanks to all contributors who have helped make Crankshaft possible! 🚀
Ready to get started? Check out the Quick Start Guide or explore the documentation.
bash scripts/lint.sh
bash scripts/run_tests.sh
cd build && cpack -G DEB
## Features
- ✅ EventBus with thread-safe pub/sub
- ✅ WebSocket communication (Core ↔ UI)
- ✅ JSON message protocol
- ✅ Theme system (light/dark mode)
- ✅ Internationalisation (en-GB, de-DE)
- ✅ Material Design Icons
- ✅ Unit and integration tests
- ✅ CI/CD pipeline (multi-arch DEB builds, SBOM generation)
- ✅ About page with acknowledgements, SBOM and changelog links
## Recent Enhancements
- Multi-architecture CI/CD workflows (amd64, arm64, armhf) producing DEB packages
- Automated CycloneDX SBOM generation published with builds/releases
- About page enhancements with acknowledgements and external links
- New Settings UI components (link/header) for richer About content
- Changelog generation workflow and documented changelog in `docs/CHANGELOG.md`
## Documentation
- [Architecture](docs/ARCHITECTURE.md)
- [WebSocket API](docs/API.md)
- [Development Guide](docs/DEVELOPMENT.md)
- [Changelog](docs/CHANGELOG.md)
- AASDK Modern Logger (verbose USB/AOAP debugging): `external/aasdk/MODERN_LOGGER.md`
## License
GPL v3 - See LICENSE file for details.