docs: add traccar client design spec
This commit is contained in:
commit
f1c076d71a
1 changed files with 274 additions and 0 deletions
274
docs/superpowers/specs/2026-04-30-traccar-client-design.md
Normal file
274
docs/superpowers/specs/2026-04-30-traccar-client-design.md
Normal file
|
|
@ -0,0 +1,274 @@
|
||||||
|
# Traccar Client Rewrite - Specification
|
||||||
|
|
||||||
|
**Date**: 2026-04-30
|
||||||
|
**Project**: traccar_client
|
||||||
|
**Type**: Fresh Flutter + Native Android GPS tracking app
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Project Overview
|
||||||
|
|
||||||
|
- **Purpose**: Reliable background GPS location tracking app for Android that reports to a self-hosted Traccar server
|
||||||
|
- **Target Platform**: Android only
|
||||||
|
- **Traccar Protocol**: Standard HTTP-based protocol (compatible with any self-hosted Traccar server)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Architecture
|
||||||
|
|
||||||
|
### 2.1 Technology Stack
|
||||||
|
|
||||||
|
| Layer | Technology | Responsibility |
|
||||||
|
|-------|------------|----------------|
|
||||||
|
| **UI** | Flutter | Settings screen, main screen, status/log viewer |
|
||||||
|
| **Bridge** | Platform Channels | MethodChannel + EventChannel between Flutter and Android |
|
||||||
|
| **Service** | Kotlin Android | Foreground service for reliable background tracking |
|
||||||
|
| **Location** | FusedLocationProviderClient (Google Play Services) | GPS location acquisition |
|
||||||
|
| **Storage** | Room (SQLite) | Offline location buffer + event log |
|
||||||
|
| **Network** | OkHttp | HTTP POST to Traccar server |
|
||||||
|
| **Background** | WorkManager | Heartbeat scheduling, periodic sync |
|
||||||
|
|
||||||
|
### 2.2 Data Flow
|
||||||
|
|
||||||
|
```
|
||||||
|
[FusedLocationProvider]
|
||||||
|
↓
|
||||||
|
[DistanceFilterProcessor] → (discard if within threshold)
|
||||||
|
↓
|
||||||
|
[LocationTrackingService] → [Room: locations buffer] ← (if offline)
|
||||||
|
↓
|
||||||
|
[TraccarHttpClient] → POST to server → [Room: mark synced]
|
||||||
|
↑ (when online)
|
||||||
|
[WorkManager] → periodic sync attempt
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Components
|
||||||
|
|
||||||
|
### 3.1 Flutter UI Layer
|
||||||
|
|
||||||
|
| Screen | Purpose |
|
||||||
|
|--------|---------|
|
||||||
|
| `main_screen.dart` | Toggle tracking on/off, display last location, speed, timestamp |
|
||||||
|
| `settings_screen.dart` | All configuration options |
|
||||||
|
| `status_screen.dart` | Event log viewer for debugging |
|
||||||
|
| `preferences.dart` | SharedPreferences wrapper for settings persistence |
|
||||||
|
|
||||||
|
### 3.2 Platform Bridge
|
||||||
|
|
||||||
|
| Class | Type | Purpose |
|
||||||
|
|-------|------|---------|
|
||||||
|
| `location_bridge.dart` | Flutter | Platform channel wrapper |
|
||||||
|
| `BridgeModule.kt` | Kotlin | Registers MethodChannel + EventChannel |
|
||||||
|
|
||||||
|
### 3.3 Android Service Layer
|
||||||
|
|
||||||
|
| Class | Purpose |
|
||||||
|
|-------|---------|
|
||||||
|
| `LocationTrackingService` | Foreground service with persistent notification |
|
||||||
|
| `FusedLocationProvider` | Google Play Services location API wrapper |
|
||||||
|
| `DistanceFilterProcessor` | Distance/interval/angle filtering with Haversine |
|
||||||
|
| `HeartbeatScheduler` | Stationary heartbeat via WorkManager |
|
||||||
|
| `AppDatabase` | Room database |
|
||||||
|
| `LocationDao` | CRUD for buffered locations |
|
||||||
|
| `EventLogDao` | CRUD for event log entries |
|
||||||
|
| `TraccarHttpClient` | HTTP POST with retry and auth |
|
||||||
|
| `ConnectivityReceiver` | Network change listener |
|
||||||
|
| `Location` | Data model |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Settings
|
||||||
|
|
||||||
|
| Setting | Type | Default | Description |
|
||||||
|
|---------|------|---------|-------------|
|
||||||
|
| `serverUrl` | String | `https://demo.traccar.org` | Traccar server URL |
|
||||||
|
| `deviceId` | String | Auto-generated 8-digit | Device identifier |
|
||||||
|
| `accuracy` | String | `HIGH` | GPS accuracy: HIGH/HIGH_ACCURACY/BALANCED/LOW |
|
||||||
|
| `distanceFilter` | int | `75` | Min distance between reports (meters) |
|
||||||
|
| `interval` | int | `300` | Time-based fallback filter (seconds) |
|
||||||
|
| `heartbeat` | int | `60` | Stationary heartbeat interval (seconds) |
|
||||||
|
| `offlineBuffer` | bool | `true` | Queue locations when offline |
|
||||||
|
| `stopDetection` | bool | `true` | Auto-stop tracking when stationary |
|
||||||
|
| `password` | String | `""` | Basic auth password for server |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. Foreground Notification
|
||||||
|
|
||||||
|
**Layout**:
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────┐
|
||||||
|
│ 📍 Traccar Client [ON/OFF] │
|
||||||
|
├─────────────────────────────────────────┤
|
||||||
|
│ Lat: 37.7749 Lon: -122.4194 │
|
||||||
|
│ Speed: 45 km/h │
|
||||||
|
│ Last: 09:41:23 │
|
||||||
|
└─────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
**Updates**: Notification content updates in real-time as locations are captured and sent.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. Traccar Protocol
|
||||||
|
|
||||||
|
**Endpoint**: `{serverUrl}/?id={deviceId}&lat={lat}&lon={lon}×tamp={ts}&speed={speed}&...`
|
||||||
|
|
||||||
|
**Parameters**:
|
||||||
|
- `id` - Device identifier
|
||||||
|
- `lat` - Latitude
|
||||||
|
- `lon` - Longitude
|
||||||
|
- `timestamp` - Unix timestamp (milliseconds)
|
||||||
|
- `speed` - Speed in km/h
|
||||||
|
- `bearing` - Heading in degrees
|
||||||
|
- `accuracy` - GPS accuracy in meters
|
||||||
|
- `altitude` - Altitude in meters
|
||||||
|
- `is_moving` - 1 if moving, 0 if stationary
|
||||||
|
|
||||||
|
**Authentication**: HTTP Basic Auth if password is set.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. Offline Buffering
|
||||||
|
|
||||||
|
**When offline**:
|
||||||
|
1. Location is captured and passes filters
|
||||||
|
2. Location is saved to Room `locations` table with `synced=0`
|
||||||
|
3. App continues tracking and buffering
|
||||||
|
|
||||||
|
**When connectivity restored**:
|
||||||
|
1. WorkManager triggers sync
|
||||||
|
2. All buffered locations are sent to server
|
||||||
|
3. Locations marked as `synced=1`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. Heartbeat Behavior
|
||||||
|
|
||||||
|
| State | Behavior |
|
||||||
|
|-------|----------|
|
||||||
|
| **Moving** | Normal location updates based on distance/interval filters |
|
||||||
|
| **Stationary** | Heartbeat fires every N seconds (configurable), triggers single location fix |
|
||||||
|
| **Stop detected** | Tracking auto-stops if `stopDetection=true`, heartbeat continues |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 9. Event Log
|
||||||
|
|
||||||
|
**Logged Events**:
|
||||||
|
| Event Type | When Logged |
|
||||||
|
|------------|-------------|
|
||||||
|
| `LOCATION` | Location captured and accepted |
|
||||||
|
| `FILTERED` | Location filtered (reason: distance/interval/angle) |
|
||||||
|
| `SYNC` | Location successfully sent to server |
|
||||||
|
| `HEARTBEAT` | Heartbeat event fired |
|
||||||
|
| `NETWORK_CHANGE` | Network went online/offline |
|
||||||
|
| `ERROR` | Any error condition |
|
||||||
|
|
||||||
|
**Log Entry Fields**: timestamp, event_type, message
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 10. File Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
traccar_client/
|
||||||
|
├── lib/
|
||||||
|
│ ├── main.dart
|
||||||
|
│ ├── main_screen.dart
|
||||||
|
│ ├── settings_screen.dart
|
||||||
|
│ ├── status_screen.dart
|
||||||
|
│ ├── preferences.dart
|
||||||
|
│ └── bridge/
|
||||||
|
│ └── location_bridge.dart
|
||||||
|
├── android/app/src/main/
|
||||||
|
│ ├── kotlin/com/traccar/traccar_client/
|
||||||
|
│ │ ├── MainActivity.kt
|
||||||
|
│ │ ├── BridgeModule.kt
|
||||||
|
│ │ ├── service/
|
||||||
|
│ │ │ └── LocationTrackingService.kt
|
||||||
|
│ │ ├── location/
|
||||||
|
│ │ │ ├── FusedLocationProvider.kt
|
||||||
|
│ │ │ ├── DistanceFilterProcessor.kt
|
||||||
|
│ │ │ └── HeartbeatScheduler.kt
|
||||||
|
│ │ ├── storage/
|
||||||
|
│ │ │ ├── AppDatabase.kt
|
||||||
|
│ │ │ ├── LocationDao.kt
|
||||||
|
│ │ │ └── EventLogDao.kt
|
||||||
|
│ │ ├── network/
|
||||||
|
│ │ │ ├── TraccarHttpClient.kt
|
||||||
|
│ │ │ └── ConnectivityReceiver.kt
|
||||||
|
│ │ └── model/
|
||||||
|
│ │ └── Location.kt
|
||||||
|
│ └── AndroidManifest.xml
|
||||||
|
├── docs/
|
||||||
|
│ └── superpowers/
|
||||||
|
│ └── specs/
|
||||||
|
│ └── 2026-04-30-traccar-client-design.md
|
||||||
|
└── pubspec.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 11. Dependencies
|
||||||
|
|
||||||
|
### Flutter (pubspec.yaml)
|
||||||
|
```yaml
|
||||||
|
dependencies:
|
||||||
|
flutter:
|
||||||
|
sdk: flutter
|
||||||
|
shared_preferences: ^2.2.0
|
||||||
|
workmanager: ^0.5.0
|
||||||
|
sqflite: ^2.3.0
|
||||||
|
http: ^1.1.0
|
||||||
|
permission_handler: ^11.0.0
|
||||||
|
flutter_local_notifications: ^16.0.0
|
||||||
|
```
|
||||||
|
|
||||||
|
### Android (app/build.gradle)
|
||||||
|
```groovy
|
||||||
|
implementation 'androidx.room:room-runtime:2.5.0'
|
||||||
|
implementation 'com.google.android.gms:play-services-location:21.0.1'
|
||||||
|
implementation 'androidx.work:work-runtime:2.8.0'
|
||||||
|
implementation 'androidx.appcompat:appcompat:1.6.1'
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 12. Android Permissions
|
||||||
|
|
||||||
|
```xml
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
|
||||||
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||||
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_LOCATION" />
|
||||||
|
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||||
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 13. Verification Criteria
|
||||||
|
|
||||||
|
| Test | Expected Result |
|
||||||
|
|------|------------------|
|
||||||
|
| Home→Office route (10km) | 20+ coordinate points captured |
|
||||||
|
| Offline mode | Locations queued, synced when connection restored |
|
||||||
|
| Stationary 5+ minutes | Heartbeat fires every N seconds (configurable) |
|
||||||
|
| Arrival detection | Tracking stops, heartbeat continues |
|
||||||
|
| App restart | Settings persist, tracking resumes |
|
||||||
|
| Notification | Shows ON/OFF status, coordinates, speed, timestamp |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 14. Implementation Phases
|
||||||
|
|
||||||
|
1. **Phase 1**: Project Setup - Flutter project, Android permissions, dependencies
|
||||||
|
2. **Phase 2**: Native Android Layer - Location service, Room database, HTTP client
|
||||||
|
3. **Phase 3**: Flutter UI Layer - Main screen, settings screen, status screen
|
||||||
|
4. **Phase 4**: Platform Channel Bridge - MethodChannel, EventChannel
|
||||||
|
5. **Phase 5**: Integration & Testing
|
||||||
Loading…
Add table
Add a link
Reference in a new issue