flutter_traccar_api 0.1.1 
flutter_traccar_api: ^0.1.1 copied to clipboard
Dart package for Traccar GPS tracking server integration with authentication, device management, and real-time WebSocket updates.
๐ Flutter Traccar API #
A powerful, feature-rich Flutter package for seamless integration with Traccar GPS tracking servers
๐ Documentation โข ๐ Quick Start โข ๐ก Examples โข ๐ค Contributing
โจ Features #
๐ Authentication & Security #
 ๐ฑ Device Management #
  | 
๐ Position Tracking #
 ๐ Advanced Reporting #
 ๐ Real-time WebSocket #
  | 
๐ Performance & Optimization #
| Feature | Description | Benefits | 
|---|---|---|
| ๐ง Intelligent Caching | Smart cache management with TTL | Faster responses, offline support | 
| โก Rate Limiting | Built-in API rate limiting | Prevents server overload | 
| ๐ Request Batching | Automatic request optimization | Improved performance | 
| ๐ฆ Offline Mode | Cache-based offline functionality | Works without internet | 
| ๐๏ธ Type Safety | Full OpenAPI-generated models | Compile-time error checking | 
๐ฆ Installation #
Add this package to your pubspec.yaml:
dependencies:
  flutter_traccar_api: ^0.1.0
  # Required for secure storage
  flutter_secure_storage: ^9.0.0
  # Required for caching
  shared_preferences: ^2.2.0
Then run:
flutter pub get
๐ง Platform Setup #
๐ฑ Android Setup
Add to android/app/src/main/AndroidManifest.xml:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
๐ iOS Setup
No additional setup required for iOS.
๐ Web Setup
Ensure your Traccar server supports CORS for web applications.
๐ Quick Start #
1๏ธโฃ Initialize the API #
import 'package:flutter_traccar_api/flutter_traccar_api.dart';
void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  
  // ๐ฏ Basic initialization
  await FlutterTraccarApi.initialize('https://your-traccar-server.com');
  
  // ๐ Advanced initialization with performance features
  await FlutterTraccarApi.initialize(
    'https://your-traccar-server.com',
    config: HttpClientConfig(
      enableCaching: true,
      enableRateLimiting: true,
      enableBatching: true,
      enableOfflineMode: true,
      cacheConfig: CacheConfig(
        maxCacheSize: 50 * 1024 * 1024, // 50MB
        defaultTtl: Duration(minutes: 15),
        enableCompression: true,
      ),
      rateLimitConfig: RateLimitConfig(
        requestsPerSecond: 10,
        burstSize: 20,
        enableBackoff: true,
      ),
    ),
  );
  
  runApp(MyApp());
}
2๏ธโฃ Authentication #
class AuthService {
  final api = FlutterTraccarApi.instance;
  Future<bool> login(String username, String password) async {
    try {
      final user = await api.login(username, password);
      print('โ
 Logged in as: ${user.name}');
      return true;
    } on TraccarApiException catch (e) {
      print('โ Login failed: ${e.message}');
      return false;
    }
  }
  Future<void> logout() async {
    await api.logout();
    print('๐ Logged out successfully');
  }
  Future<bool> isLoggedIn() async {
    return await api.isAuthenticated();
  }
}
3๏ธโฃ Device Management #
class DeviceService {
  final api = FlutterTraccarApi.instance;
  Future<List<Device>> getAllDevices() async {
    try {
      final devices = await api.getDevices();
      print('๐ฑ Found ${devices.length} devices');
      return devices;
    } catch (e) {
      print('โ Error fetching devices: $e');
      return [];
    }
  }
  Future<Device?> getDeviceById(int deviceId) async {
    try {
      return await api.getDevice(deviceId);
    } catch (e) {
      print('โ Device not found: $e');
      return null;
    }
  }
}
4๏ธโฃ Position Tracking #
class PositionService {
  final api = FlutterTraccarApi.instance;
  Future<List<Position>> getRecentPositions(int deviceId) async {
    final now = DateTime.now();
    final yesterday = now.subtract(Duration(days: 1));
    
    return await api.getPositions(
      deviceId: deviceId,
      from: yesterday,
      to: now,
    );
  }
  Future<Position?> getLatestPosition(int deviceId) async {
    final positions = await getRecentPositions(deviceId);
    return positions.isNotEmpty ? positions.first : null;
  }
}
5๏ธโฃ Real-time WebSocket Updates #
class WebSocketService {
  final api = FlutterTraccarApi.instance;
  Future<void> startRealTimeUpdates() async {
    // Connect to WebSocket
    final connected = await api.connectWebSocket();
    if (!connected) {
      print('โ Failed to connect to WebSocket');
      return;
    }
    // Listen to real-time device updates
    api.deviceUpdatesStream.listen((devices) {
      print('๐ฑ Device updates: ${devices.length} devices');
    });
    // Listen to real-time position updates
    api.positionUpdatesStream.listen((positions) {
      print('๐ Position updates: ${positions.length} positions');
    });
    // Listen to real-time events (alarms, geofences, etc.)
    api.eventUpdatesStream.listen((events) {
      print('๐จ Events: ${events.length} events');
    });
    // Monitor connection status
    api.webSocketStatusStream.listen((status) {
      print('๐ WebSocket status: ${status.name}');
    });
  }
  Future<void> stopRealTimeUpdates() async {
    await api.disconnectWebSocket();
    print('๐ WebSocket disconnected');
  }
}
๐ก Examples #
๐ฏ Complete Flutter App Example #
import 'package:flutter/material.dart';
import 'package:flutter_traccar_api/flutter_traccar_api.dart';
class TraccarDashboard extends StatefulWidget {
  @override
  _TraccarDashboardState createState() => _TraccarDashboardState();
}
class _TraccarDashboardState extends State<TraccarDashboard> {
  final api = FlutterTraccarApi.instance;
  List<Device> devices = [];
  bool isLoading = true;
  @override
  void initState() {
    super.initState();
    _loadDevices();
  }
  Future<void> _loadDevices() async {
    try {
      final fetchedDevices = await api.getDevices();
      setState(() {
        devices = fetchedDevices;
        isLoading = false;
      });
    } catch (e) {
      setState(() => isLoading = false);
      _showError('Failed to load devices: $e');
    }
  }
  void _showError(String message) {
    ScaffoldMessenger.of(context).showSnackBar(
      SnackBar(content: Text(message), backgroundColor: Colors.red),
    );
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('๐ Traccar Dashboard'),
        actions: [
          IconButton(
            icon: Icon(Icons.refresh),
            onPressed: _loadDevices,
          ),
        ],
      ),
      body: isLoading
          ? Center(child: CircularProgressIndicator())
          : devices.isEmpty
              ? Center(
                  child: Column(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: [
                      Icon(Icons.devices, size: 64, color: Colors.grey),
                      SizedBox(height: 16),
                      Text('No devices found'),
                    ],
                  ),
                )
              : ListView.builder(
                  itemCount: devices.length,
                  itemBuilder: (context, index) {
                    final device = devices[index];
                    return DeviceCard(device: device);
                  },
                ),
    );
  }
}
class DeviceCard extends StatelessWidget {
  final Device device;
  const DeviceCard({Key? key, required this.device}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return Card(
      margin: EdgeInsets.all(8),
      child: ListTile(
        leading: CircleAvatar(
          backgroundColor: device.status == 'online' ? Colors.green : Colors.red,
          child: Icon(Icons.gps_fixed, color: Colors.white),
        ),
        title: Text(device.name ?? 'Unknown Device'),
        subtitle: Text('ID: ${device.id} โข Status: ${device.status}'),
        trailing: Icon(Icons.arrow_forward_ios),
        onTap: () {
          Navigator.push(
            context,
            MaterialPageRoute(
              builder: (context) => DeviceDetailPage(device: device),
            ),
          );
        },
      ),
    );
  }
}
๐ Advanced Reporting Example #
class ReportService {
  final api = FlutterTraccarApi.instance;
  Future<Map<String, dynamic>> generateComprehensiveReport(
    List<int> deviceIds,
    DateTime from,
    DateTime to,
  ) async {
    try {
      // ๐ Get trip reports
      final trips = await api.getTripReports(
        deviceIds: deviceIds,
        from: from,
        to: to,
      );
      // ๐ Get summary reports
      final summaries = await api.getSummaryReports(
        deviceIds: deviceIds,
        from: from,
        to: to,
      );
      // ๐ Get stop reports
      final stops = await api.getStopReports(
        deviceIds: deviceIds,
        from: from,
        to: to,
      );
      return {
        'trips': trips,
        'summaries': summaries,
        'stops': stops,
        'totalDistance': summaries.fold<double>(
          0,
          (sum, summary) => sum + (summary.distance ?? 0),
        ),
        'totalDuration': trips.fold<Duration>(
          Duration.zero,
          (sum, trip) => sum + (trip.duration ?? Duration.zero),
        ),
      };
    } catch (e) {
      throw Exception('Failed to generate report: $e');
    }
  }
}
๐ Real-time WebSocket Updates #
The package provides powerful WebSocket functionality for real-time updates without polling:
๐ Basic WebSocket Usage
class RealTimeTracker {
  final api = FlutterTraccarApi.instance;
  late StreamSubscription<List<Device>> _deviceSubscription;
  late StreamSubscription<List<Position>> _positionSubscription;
  late StreamSubscription<List<Event>> _eventSubscription;
  late StreamSubscription<WebSocketStatus> _statusSubscription;
  Future<void> startRealTimeTracking() async {
    // Connect to WebSocket
    final connected = await api.connectWebSocket();
    if (!connected) {
      throw Exception('Failed to connect to WebSocket');
    }
    // Listen to real-time device updates
    _deviceSubscription = api.deviceUpdatesStream.listen(
      (devices) {
        print('๐ฑ Received ${devices.length} device updates');
        // Handle device updates (status changes, etc.)
      },
      onError: (error) => print('โ Device stream error: $error'),
    );
    // Listen to real-time position updates
    _positionSubscription = api.positionUpdatesStream.listen(
      (positions) {
        print('๐ Received ${positions.length} position updates');
        // Handle position updates (location changes)
      },
      onError: (error) => print('โ Position stream error: $error'),
    );
    // Listen to real-time events
    _eventSubscription = api.eventUpdatesStream.listen(
      (events) {
        print('๐จ Received ${events.length} events');
        // Handle events (alarms, geofence violations, etc.)
      },
      onError: (error) => print('โ Event stream error: $error'),
    );
    // Monitor WebSocket connection status
    _statusSubscription = api.webSocketStatusStream.listen(
      (status) {
        switch (status) {
          case WebSocketStatus.connected:
            print('โ
 WebSocket connected');
            break;
          case WebSocketStatus.disconnected:
            print('โ WebSocket disconnected');
            break;
          case WebSocketStatus.connecting:
            print('๐ WebSocket connecting...');
            break;
          case WebSocketStatus.reconnecting:
            print('๐ WebSocket reconnecting...');
            break;
          case WebSocketStatus.error:
            print('โ WebSocket error');
            break;
        }
      },
    );
  }
  Future<void> stopRealTimeTracking() async {
    // Cancel all subscriptions
    await _deviceSubscription.cancel();
    await _positionSubscription.cancel();
    await _eventSubscription.cancel();
    await _statusSubscription.cancel();
    
    // Disconnect WebSocket
    await api.disconnectWebSocket();
  }
  bool get isConnected => api.isWebSocketConnected;
}
๐ฏ Advanced WebSocket Configuration
// Initialize with custom WebSocket configuration
await FlutterTraccarApi.initialize(
  'https://your-traccar-server.com',
  config: HttpClientConfig(
    webSocketConfig: WebSocketConfig(
      enableAutoReconnect: true,
      maxReconnectAttempts: 5,
      reconnectInterval: Duration(seconds: 5),
      heartbeatInterval: Duration(seconds: 30),
    ),
  ),
);
๐ฑ Flutter Widget Integration
class LiveTrackingWidget extends StatefulWidget {
  @override
  _LiveTrackingWidgetState createState() => _LiveTrackingWidgetState();
}
class _LiveTrackingWidgetState extends State<LiveTrackingWidget> {
  final api = FlutterTraccarApi.instance;
  List<Device> devices = [];
  List<Position> positions = [];
  WebSocketStatus connectionStatus = WebSocketStatus.disconnected;
  @override
  void initState() {
    super.initState();
    _initializeWebSocket();
  }
  Future<void> _initializeWebSocket() async {
    // Connect to WebSocket
    await api.connectWebSocket();
    // Listen to streams
    api.deviceUpdatesStream.listen((updatedDevices) {
      setState(() => devices = updatedDevices);
    });
    api.positionUpdatesStream.listen((updatedPositions) {
      setState(() => positions = updatedPositions);
    });
    api.webSocketStatusStream.listen((status) {
      setState(() => connectionStatus = status);
    });
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Live Tracking'),
        actions: [
          Icon(
            connectionStatus == WebSocketStatus.connected
                ? Icons.wifi
                : Icons.wifi_off,
            color: connectionStatus == WebSocketStatus.connected
                ? Colors.green
                : Colors.red,
          ),
        ],
      ),
      body: Column(
        children: [
          // Connection status
          Container(
            padding: EdgeInsets.all(8),
            color: connectionStatus == WebSocketStatus.connected
                ? Colors.green.withOpacity(0.1)
                : Colors.red.withOpacity(0.1),
            child: Row(
              children: [
                Icon(
                  connectionStatus == WebSocketStatus.connected
                      ? Icons.check_circle
                      : Icons.error,
                  color: connectionStatus == WebSocketStatus.connected
                      ? Colors.green
                      : Colors.red,
                ),
                SizedBox(width: 8),
                Text('Status: ${connectionStatus.name}'),
              ],
            ),
          ),
          // Live device list
          Expanded(
            child: ListView.builder(
              itemCount: devices.length,
              itemBuilder: (context, index) {
                final device = devices[index];
                final position = positions
                    .where((p) => p.deviceId == device.id)
                    .lastOrNull;
                
                return ListTile(
                  leading: CircleAvatar(
                    backgroundColor: device.status == 'online'
                        ? Colors.green
                        : Colors.grey,
                    child: Icon(Icons.device_hub, color: Colors.white),
                  ),
                  title: Text(device.name ?? 'Unknown Device'),
                  subtitle: position != null
                      ? Text(
                          'Lat: ${position.latitude?.toStringAsFixed(6)}, '
                          'Lng: ${position.longitude?.toStringAsFixed(6)}\n'
                          'Speed: ${position.speed?.toStringAsFixed(1)} km/h',
                        )
                      : Text('No position data'),
                  trailing: Text(
                    position?.deviceTime ?? 'No update',
                    style: TextStyle(fontSize: 12),
                  ),
                );
              },
            ),
          ),
        ],
      ),
    );
  }
  @override
  void dispose() {
    api.disconnectWebSocket();
    super.dispose();
  }
}
๐๏ธ Advanced Configuration #
๐ง Cache Management #
// Get cache statistics
final stats = await api.getCacheStats();
print('๐ Cache Stats:');
print('  Size: ${(stats.totalSize / 1024 / 1024).toStringAsFixed(2)} MB');
print('  Hit Rate: ${stats.hitRate.toStringAsFixed(1)}%');
print('  Entries: ${stats.entryCount}');
// Clear specific caches
await api.invalidateDeviceCache();
await api.invalidatePositionCache();
// Clear all cache
await api.clearCache();
โก Rate Limiting #
// Check rate limit status
final status = api.getRateLimitStatus();
if (status != null) {
  print('โก Rate Limit Status:');
  print('  Remaining: ${status.remainingRequests}');
  print('  Reset: ${status.resetTime}');
  print('  Limit: ${status.requestLimit}');
}
// Reset rate limiter
api.resetRateLimit();
๐ Request Batching #
// Get batching statistics
final batchStats = api.getBatchingStats();
if (batchStats != null) {
  print('๐ Batch Stats:');
  print('  Total Batches: ${batchStats.totalBatches}');
  print('  Avg Size: ${batchStats.averageBatchSize.toStringAsFixed(1)}');
  print('  Pending: ${batchStats.pendingRequests}');
}
// Flush pending batches
await api.flushAllBatches();
๐ ๏ธ API Reference #
๐ Authentication Methods
// Login with credentials
Future<User> login(String email, String password);
// Logout and clear session
Future<void> logout();
// Check authentication status
Future<bool> isAuthenticated();
// Get current username
Future<String?> currentUsername();
// Check for cached credentials
Future<bool> hasCachedCredentials();
๐ฑ Device Management
// Get all devices
Future<List<Device>> getDevices();
// Get specific device
Future<Device> getDevice(int deviceId);
// Get device with caching
Future<List<Device>> getDevicesCached();
๐ Position Tracking
// Get positions with filters
Future<List<Position>> getPositions({
  int? deviceId,
  List<int>? deviceIds,
  DateTime? from,
  DateTime? to,
});
// Get latest positions
Future<List<Position>> getLatestPositions(List<int> deviceIds);
๐ Reporting
// Trip reports
Future<List<TripReport>> getTripReports({
  required List<int> deviceIds,
  required DateTime from,
  required DateTime to,
});
// Summary reports
Future<List<SummaryReport>> getSummaryReports({
  required List<int> deviceIds,
  required DateTime from,
  required DateTime to,
});
// Stop reports
Future<List<StopReport>> getStopReports({
  required List<int> deviceIds,
  required DateTime from,
  required DateTime to,
});
// Distance reports
Future<List<ReportDistance>> getDistanceReports({
  required List<int> deviceIds,
  required DateTime from,
  required DateTime to,
});
๐๏ธ Architecture #
flutter_traccar_api/
โโโ ๐ lib/
โ   โโโ ๐ flutter_traccar_api.dart          # Public API
โ   โโโ ๐ src/
โ       โโโ ๐ models/                       # Data models
โ       โ   โโโ ๐ device.dart
โ       โ   โโโ ๐ position.dart
โ       โ   โโโ ๐ user.dart
โ       โ   โโโ ๐ ...
โ       โโโ ๐ services/                     # Core services
โ       โ   โโโ ๐ auth_manager.dart         # Authentication
โ       โ   โโโ ๐ http_service.dart         # HTTP client
โ       โ   โโโ ๐ cache_manager.dart        # Caching
โ       โ   โโโ ๐ rate_limiter.dart         # Rate limiting
โ       โ   โโโ ๐ request_batcher.dart      # Request batching
โ       โโโ ๐ exceptions/                   # Error handling
โ       โโโ ๐ utils/                        # Utilities
โโโ ๐ example/                              # Example app
โโโ ๐ test/                                 # Unit tests
๐งช Testing #
Run the test suite:
# Run all tests
flutter test
# Run with coverage
flutter test --coverage
# Run specific test file
flutter test test/services/auth_manager_test.dart
๐ฏ Test Coverage #
- โ Authentication flows
 - โ Device management
 - โ Position tracking
 - โ Report generation
 - โ Error handling
 - โ Cache management
 - โ Rate limiting
 - โ Request batching
 
๐ Requirements #
| Component | Version | 
|---|---|
| ๐ฏ Dart SDK | >=3.0.0 <4.0.0 | 
| ๐ฑ Flutter | >=3.0.0 | 
| ๐ฅ๏ธ Traccar Server | >=5.0 | 
๐ฆ Dependencies #
dependencies:
  dio: ^5.3.0                    # HTTP client
  flutter_secure_storage: ^9.0.0 # Secure storage
  shared_preferences: ^2.2.0     # Local storage
  crypto: ^3.0.3                 # Cryptographic functions
  intl: ^0.18.0                  # Internationalization
๐ค Contributing #
We welcome contributions! Here's how you can help:
๐ Getting Started #
- Fork the repository
 - Clone your fork: 
git clone https://github.com/yourusername/flutter_traccar_api.git - Create a feature branch: 
git checkout -b feature/amazing-feature - Make your changes
 - Test your changes: 
flutter test - Commit your changes: 
git commit -m 'Add amazing feature' - Push to the branch: 
git push origin feature/amazing-feature - Open a Pull Request
 
๐ Development Guidelines #
- Follow Effective Dart guidelines
 - Write tests for new features
 - Update documentation for API changes
 - Use conventional commit messages
 
๐ Reporting Issues #
Found a bug? Please open an issue with:
- ๐ฑ Flutter version
 - ๐ฆ Package version
 - ๐ Steps to reproduce
 - ๐ Expected vs actual behavior
 
๐ Documentation #
- ๐ API Documentation
 - ๐ฏ Traccar API Reference
 - ๐ฑ Flutter Documentation
 
๐ Support #
Need help? We're here for you!
- ๐ฌ GitHub Discussions
 - ๐ Issue Tracker
 - ๐ง Email Support
 - ๐ฌ Discord Community
 
๐ License #
This project is licensed under the MIT License - see the LICENSE file for details.
๐ Acknowledgments #
- ๐ Traccar - Open source GPS tracking system
 - ๐ฑ Flutter Team - Amazing cross-platform framework
 - ๐ฏ Dart Team - Powerful programming language
 - ๐ค All our contributors
 
Made with โค๏ธ by the Flutter community
โญ Star this repo if it helped you! โญ