aiyu-ayaan/RideLink
RideLink
🛵 Open-source TVS Connect alternative for TVS Ntorq 125 (Race XP, XT, SmartXonnect). Google Maps turn-by-turn arrows on the scooter display, caller ID, WhatsApp counts, ride analytics. No account, no cloud, no tracking.
- active
- 1 stars
- Kotlin
- Other
- pushed today

// readmeaiyu-ayaan/RideLink
RideLink
Your scooter display, without the account.
A private, local-first Android companion app for TVS SmartXonnect scooter displays.
RideLink connects your phone to your TVS SmartXonnect scooter display over Bluetooth Low Energy (BLE). It replaces the official TVS Connect app for riding features: it streams Google Maps turn-by-turn directions, forwards caller ID and accepts/rejects calls with handlebar buttons, syncs media info, and keeps time, battery, signal, and local weather up to date.
Zero accounts. Zero cloud servers. Zero tracking. All communications stay between your phone and your scooter.
Highlights
- Turn-by-turn navigation: Reads Google Maps notifications live and maps navigation icons directly to scooter dashboard arrows and distance readouts.
- Call control: Shows caller ID on incoming calls; answer or reject calls using scooter switches or quick auto-SMS templates.
- Media sessions: Syncs track title, artist, playback state, and volume to compatible digital displays.
- Live telemetry & status: Real-time speed, trip meters, odometer, fuel level, range, engine temperatures, service reminders, and MIL diagnostics.
- Ride analytics & history: Automatic ride recording with split distance sourcing (Google Maps route progress vs. odometer vs. speed integration), elevation, speed bands, and SQLite history exportable to CSV.
- Weather & environment: Optional local temperature, AQI, and location sync via Open-Meteo (no API key required).
- Fuel and service: Fuel log with real full-to-full mileage and cost per km (₹), automatic refuel detection from the fuel gauge, low-fuel alert that finds a petrol pump in Maps, and service / insurance / PUC reminders shown on the display.
- Riding safety: WhatsApp auto-reply while riding (one-to-one chats, once per ride), ride check-in SMS with a Google Maps link at start and end, and a precise last-parked spot.
- Multi-scooter garage: Pair and manage multiple scooters with per-bike model profiles and auto-reconnect.
- Material 3 Expressive UI: Built entirely in Jetpack Compose with dynamic color, adaptive layouts, dark/light themes, and floating pill navigation.
- Auto model detection: Recognises the SmartXonnect LCD (Race XP), older Ntorq and 2025+ clusters from their own frames.
- Race XP extras: Race stats, display brightness, SMS sender, birthday greeting, last parked location and missed-call auto-reply.
- Developer tools: Demo navigation through every turn type, arrow and alert code sweeps, and a live frame console.
- In-app updates: Built-in GitHub Releases updater supporting Stable, Beta, and Alpha release channels.
Supported scooters
RideLink detects the display from the frames it sends and picks the right protocol by itself (Settings → Scooter → Auto). You can also pick the model by hand.
| Scooter | Years | Display | Protocol in RideLink | Turn-by-turn | Status |
|---|---|---|---|---|---|
| NTORQ 125 Race XP | 2020 – 2026 | SmartXonnect LCD, arrow pictogram + 2 text lines | SmartXonnect (auto-detected) | Arrow + distance + direction words | ✅ Tested on a 2026 Race XP |
| NTORQ 125 Standard / Race Edition / Super Squad / Marvel editions | 2018 – 2024 | SmartXonnect LCD | SmartXonnect (auto-detected) | Arrow + distance + direction words | 🟡 Same protocol as the Race XP, not yet tested |
| NTORQ 125 XT | 2023+ | Hybrid TFT + LCD | Older Ntorq (U577 premium) | Arrow + distance | 🟡 Untested on a real scooter |
| NTORQ 125 (U716) / U577 base | 2022 – 2024 | LCD | Older Ntorq | Arrow + distance | 🟡 Untested |
| NTORQ 125 2025+ (U812, N251 Standard, U458 Race, U377 Super Squad) | 2025+ | Digital cluster | 2025+ Ntorq | Arrow + distance + text | 🟡 Built from the TVS app, untested |
| NTORQ 150 | 2025+ | TFT / LCD | Not supported yet | – | ❌ |
What works on every supported display: Google Maps turn-by-turn, caller ID with accept/reject from the scooter switch, missed calls, phone battery, signal, clock sync, WhatsApp/Facebook/Instagram counts, rider name and custom text lines, overspeed alert, live ride data and ride analytics.
Extras on the SmartXonnect LCD (Race XP): race stats (best lap, top speed, 0–60), display brightness, SMS sender, birthday / purchase-day greeting, plus experimental notification-light clear, food delivery alerts and last-ride CO2.
Extras on TFT displays: weather + AQI, place name and music info.
Tested your scooter? Open an issue with the model and year and a Console log (Settings → Developer options → Save logs) so it can move to ✅.
Screenshots
| Ride (Demo Mode) | Ride (Dark Theme) | Analytics | Settings | Developer Console |
|---|---|---|---|---|
![]() | ![]() | ![]() | ![]() | ![]() |
| Active navigation turn, speed & live ride telemetry | Material 3 dark theme with scooter chips | Period stats, distance chart & ride records | Modular settings sections and scooter garage | Live BLE frame log & diagnostic test injection |
How it works
flowchart LR
subgraph Phone["Android Device (RideLink)"]
direction TB
Service["ClusterService<br/>Foreground Service"]
Notif["RideNotificationListener<br/>Maps turns · Calls · Media"]
Controller["ClusterController<br/>Session state · Telemetry"]
Recorder["RideRecorder & Store<br/>SQLite v2 · Period stats"]
Link["ClusterLink<br/>BLE GATT engine"]
Notif --> Controller
Controller --> Recorder
Controller <--> Link
Service --> Controller
end
subgraph Scooter["TVS SmartXonnect Display"]
direction TB
GATT["GATT Server"]
Dash["Instrument Cluster<br/>LCD / TFT"]
GATT <--> Dash
end
Link <-->|"BLE (Service 5351 · Write 5352 · Notify 5354)"| GATT
Data flow
- Connection: Scans for BLE advertisements matching TVS displays. Once paired,
ClusterServicemaintains a persistent foreground GATT link with automatic reconnection. - Handshake: Negotiates MTU 512, enables notifications on
5354, authenticates rider profile (5B 52), and syncs media state and social counts. - Heartbeat & Telemetry: Emits status packets (
5B 4A) every 2 seconds with time, battery percentage, signal strength, network status, and ambient temperature. Incoming notify frames (5A 10,5A 11,5A 19) update local speed, trip distance, fuel, range, and diagnostic telemetry. - Navigation: Intercepts Google Maps active navigation steps, converts direction arrows and distance meters into cluster-native control codes (
5B 4Ftext +5A 4Einstruction), and streams them with synchronized timing. - Calls: Injects ringing caller frames (
5B 43) every 500 ms; handles cluster switch presses to answer or reject calls through Android'sTelecomManager.
Full protocol reverse-engineering notes and frame structures are documented in PROTOCOL.md.
Architecture
RideLink is organized into three clean Gradle modules:
graph LR
app[":app<br/>MainActivity · ClusterService · RideNotificationListener · BootReceiver"]
ui[":ui<br/>Compose screens · Theme · Material 3 Expressive · Strings"]
core[":core<br/>Protocol · BLE GATT · ClusterController · Parsers · SQLite stores"]
app --> ui
app --> core
ui --> core
:app: Application entry point, Android manifest, foreground services, broadcast receivers, and application lifecycle.:core: Protocol encoders/decoders, BLE GATT link manager, notification parsers, telecom integration, weather repository, and SQLite databases (garage.db,rides.db).:ui: 100% Jetpack Compose UI, Material 3 Expressive theming, navigation graphs, canvas analytics charts, and localized strings.
For deep dive into state ownership and lifecycle, see development/docs/ARCHITECTURE.md.
Installation
Releases
Download the latest signed release APK from the Releases page.
RideLink features an in-app updater (Settings → About → Updates). Once installed, updates can be checked, downloaded, and installed directly with support for Stable, Beta, and Alpha channels.
Permissions explained
RideLink requests only the permissions needed to replicate dashboard functionality:
| Permission | Purpose |
|---|---|
| Nearby devices / Bluetooth | Connect to the scooter cluster over BLE. |
| Notification access | Read Google Maps navigation steps and incoming caller details. |
| Phone state & call log (Optional) | Display caller names and signal bar status on the speedometer. |
| Answer phone calls (Optional) | Accept incoming calls using the scooter's handlebar switch. |
| Location (Coarse) (Optional) | Fetch local weather and air quality via Open-Meteo for TFT clusters. |
Development & build
Prerequisites
- Android Studio Ladybug / Meerkat or newer
- JDK 17 or 21
- Android SDK 35 (Android 15)
Build commands
# Clone the repository
git clone https://github.com/aiyu-ayaan/RideLink.git
cd RideLink
# Assemble debug APK
./gradlew assembleDebug
# Run unit tests
./gradlew test
# Run protocol verification tests
./gradlew :core:test --tests "com.aiyu.ridelink.core.protocol.*"
The debug APK will be placed at app/build/outputs/apk/debug/app-debug.apk.
Test tools (tools/)
The repository includes desktop Python test utilities (requires BlueZ on Linux, python3-dbus, and python3-gi):
tools/fake_cluster.py: Emulates a TVS SmartXonnect scooter display over BlueZ GATT, printing decoded frames received from the phone.tools/central_test.py: Simulates the phone central and injects pinned test frames into a real or virtual display.
Privacy & ethics
- No telematics sent to third parties: RideLink contains zero analytics SDKs, trackers, or telemetry endpoints.
- Personal use project: RideLink is an independent project and is not affiliated with, endorsed by, or connected to TVS Motor Company. No proprietary TVS code or assets are distributed.
Related docs
PROTOCOL.md— Specification of TVS SmartXonnect BLE frames and opcodesdevelopment/docs/ARCHITECTURE.md— Subsystem architecture and data flowdevelopment/docs/DESIGN_SYSTEM.md— Visual styling, tokens, and motion curvesdevelopment/brand/BRAND.md— Brand identity, geometry, and asset guidelinesCHANGELOG.md— Version history and release notes
License
RideLink is source-available, not open source. The code is public to read and audit; copying, modifying, redistributing or building your own version needs written permission. You may install and use the official release APKs for personal use. See LICENSE for the full terms.
// stack
- Kotlin
- Android
- BLE
- Bluetooth LOW Energy
- Google Maps
- Jetpack Compose
- Material3
- Motorcycle
- android
- ble
- bluetooth-low-energy
- google-maps
- jetpack-compose
- kotlin
- material3
- motorcycle
- ntorq
- ntorq-125
- ntorq-race-xp
- open-source
// specs
- status
- Working
- type
- Mobile
- year
- 2026
- language
- Kotlin
- license
- Other
- stars
- 1
- branch
- master
Repository data last synced



