Custom filtering logic
This commit is contained in:
parent
00599d7b1e
commit
5226e4dd90
6 changed files with 136 additions and 12 deletions
|
|
@ -1,7 +1,11 @@
|
|||
|
||||
import 'dart:developer' as developer;
|
||||
import 'dart:io';
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_background_geolocation/flutter_background_geolocation.dart' as bg;
|
||||
import 'package:traccar_client/location_cache.dart';
|
||||
import 'package:traccar_client/preferences.dart';
|
||||
import 'package:wakelock_partial_android/wakelock_partial_android.dart';
|
||||
|
||||
|
|
@ -13,6 +17,7 @@ class GeolocationService {
|
|||
}
|
||||
bg.BackgroundGeolocation.onEnabledChange(onEnabledChange);
|
||||
bg.BackgroundGeolocation.onMotionChange(onMotionChange);
|
||||
bg.BackgroundGeolocation.onLocation(onLocation);
|
||||
bg.BackgroundGeolocation.onHeartbeat(onHeartbeat);
|
||||
}
|
||||
|
||||
|
|
@ -34,9 +39,67 @@ class GeolocationService {
|
|||
}
|
||||
}
|
||||
|
||||
static Future<void> onLocation(bg.Location location) async {
|
||||
if (_shouldDelete(location)) {
|
||||
await bg.BackgroundGeolocation.destroyLocation(location.uuid);
|
||||
} else {
|
||||
LocationCache.set(location);
|
||||
try {
|
||||
await bg.BackgroundGeolocation.sync();
|
||||
} catch (error) {
|
||||
developer.log('Failed to send location', error: error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static Future<void> onHeartbeat(bg.HeartbeatEvent event) async {
|
||||
await bg.BackgroundGeolocation.getCurrentPosition(samples: 1, persist: true, extras: {'heartbeat': true});
|
||||
}
|
||||
|
||||
static bool _shouldDelete(bg.Location location) {
|
||||
if (!location.isMoving) return false;
|
||||
if (location.extras?.isNotEmpty == true) return false;
|
||||
|
||||
final lastLocation = LocationCache.get();
|
||||
if (lastLocation == null) return false;
|
||||
|
||||
final duration = DateTime.parse(location.timestamp).difference(DateTime.parse(lastLocation.timestamp)).inSeconds;
|
||||
|
||||
final fastestInterval = Preferences.instance.getInt(Preferences.fastestInterval);
|
||||
if (fastestInterval != null && duration < fastestInterval) return true;
|
||||
|
||||
final distance = _distance(lastLocation, location);
|
||||
|
||||
final distanceFilter = Preferences.instance.getInt(Preferences.distance) ?? 0;
|
||||
if (distanceFilter > 0 && distance >= distanceFilter) return false;
|
||||
|
||||
final isHighestAccuracy = Preferences.instance.getString(Preferences.accuracy) == 'highest';
|
||||
|
||||
if (distanceFilter == 0 || isHighestAccuracy) {
|
||||
final intervalFilter = Preferences.instance.getInt(Preferences.interval) ?? 0;
|
||||
if (intervalFilter > 0 && duration >= intervalFilter) return false;
|
||||
}
|
||||
|
||||
if (isHighestAccuracy && lastLocation.heading >= 0 && location.coords.heading > 0) {
|
||||
final angle = (location.coords.heading - lastLocation.heading).abs();
|
||||
final angleFilter = Preferences.instance.getInt(Preferences.angle) ?? 0;
|
||||
if (angleFilter > 0 && angle >= angleFilter) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static double _distance(Location from, bg.Location to) {
|
||||
const earthRadius = 6371000; // meters
|
||||
final dLat = _degToRad(to.coords.latitude - from.latitude);
|
||||
final dLon = _degToRad(to.coords.longitude - from.longitude);
|
||||
final a = sin(dLat / 2) * sin(dLat / 2) +
|
||||
cos(_degToRad(from.latitude)) * cos(_degToRad(to.coords.latitude)) * sin(dLon / 2) * sin(dLon / 2);
|
||||
final c = 2 * atan2(sqrt(a), sqrt(1 - a));
|
||||
return earthRadius * c;
|
||||
}
|
||||
|
||||
static double _degToRad(double degree) => degree * pi / 180.0;
|
||||
}
|
||||
|
||||
@pragma('vm:entry-point')
|
||||
|
|
@ -49,6 +112,9 @@ void headlessTask(bg.HeadlessEvent headlessEvent) async {
|
|||
case bg.Event.MOTIONCHANGE:
|
||||
await GeolocationService.onMotionChange(headlessEvent.event);
|
||||
break;
|
||||
case bg.Event.LOCATION:
|
||||
await GeolocationService.onLocation(headlessEvent.event);
|
||||
break;
|
||||
case bg.Event.HEARTBEAT:
|
||||
await GeolocationService.onHeartbeat(headlessEvent.event);
|
||||
break;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue