tracpulse/docs/superpowers/specs/2026-04-30-traccar-client-design.md

274 lines
8.9 KiB
Markdown

# 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}&timestamp={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