OpenMotion
An open-source platform for electric scooters, bikes, boards, and personal electric vehicles.
OpenMotion talks to your vehicle directly over Bluetooth. No manufacturer account, no cloud, no telemetry leaving your phone. If you know your vehicle's local PIN, you can see what it is doing and, once the write path is verified, control it.
Status
The first supported vehicle is the Apollo Go. Read-only support is working against real hardware:
- scan, connect, verify the Apollo GATT services, subscribe
- six-digit PIN authentication with wrong PIN and no response reported separately
- live speed, battery, voltage, current, power, temperatures, trip and odometer
- lock, headlight, atmosphere light, cruise and turn signal state
- clean recovery from Bluetooth drops
- protocol log on device for field debugging
Control writes (lock, unlock, headlight) are implemented and unit tested but disabled by a build constant until they have been compared byte for byte against a capture of the official app. See enableApolloControlWrites in lib/scooters/apollo_scooter.dart.
Architecture
UI -> Scooter -> ApolloScooter -> BleClient
lib/scooters/scooter.dartis the vehicle interface, aChangeNotifierwith a synchronousstate.lib/scooters/apollo_scooter.dartimplements the Apollo flow: connect, discover, subscribe, authenticate, keepalive, frame handling, gated control writes.lib/scooters/apollo_protocol.dartholds pure protocol functions (CRC, framing, parsers, packet builders) so they can be tested without hardware.lib/services/ble_client.dartis the only file that touches the Bluetooth plugin. One active connection at a time.lib/screens/has the scan screen and the dashboard with selectable cluster layouts.
Protocol comments use four confidence levels: STATICALLY CONFIRMED (from the vendor app), LIVE VERIFIED (against a real vehicle), INFERRED, and UNKNOWN.
Building
flutter pub get
flutter test
flutter run
Android needs Bluetooth permissions at runtime, which the app requests on first scan. iOS needs a real device.
Field debugging
The app writes a protocol log with raw bytes to its external files directory. Pull it with:
adb pull /sdcard/Android/data/dev.teamhydra.openscooter/files/openscooter.log
Adding a vehicle
Implement Scooter in one class, keep pure protocol code in one testable file, and match your vehicle by advertised service UUIDs rather than by name. Do not add abstractions until a second implementation proves they are shared.
License and third party notices
OpenMotion uses flutter_blue_plus under its non-commercial license. Check that license before distributing a commercial build.