A Flutter app that runs next to DJI Fly without the DJI SDK. It receives the aircraft's Remote ID (Bluetooth, BT5, Wi-Fi NaN and Beacon) in a foreground service, streams the paired aircraft to the hub over /ws/device, and turns take-off to landing into a logbook entry filed through /api/flights, queued when offline. Covers phases A0-A3 of the Fly Agent plan; needs no server change. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
51 lines
1.5 KiB
Dart
51 lines
1.5 KiB
Dart
import 'dart:async';
|
|
|
|
import 'package:flutter/foundation.dart';
|
|
import 'package:geolocator/geolocator.dart';
|
|
|
|
/// The phone's own GPS fix: where the pilot stands. Used for the briefing
|
|
/// weather, the distance to the aircraft, and as the pilot position on the
|
|
/// live uplink (the Web App also falls back on it when the drone has no fix).
|
|
class PilotLocation extends ChangeNotifier {
|
|
Position? position;
|
|
String? problem;
|
|
StreamSubscription<Position>? _sub;
|
|
|
|
Future<void> start() async {
|
|
if (_sub != null) return;
|
|
try {
|
|
if (!await Geolocator.isLocationServiceEnabled()) {
|
|
problem = 'Location is off';
|
|
notifyListeners();
|
|
return;
|
|
}
|
|
LocationPermission p = await Geolocator.checkPermission();
|
|
if (p == LocationPermission.denied) p = await Geolocator.requestPermission();
|
|
if (p == LocationPermission.denied || p == LocationPermission.deniedForever) {
|
|
problem = 'Location permission refused';
|
|
notifyListeners();
|
|
return;
|
|
}
|
|
problem = null;
|
|
_sub = Geolocator.getPositionStream(
|
|
locationSettings: const LocationSettings(accuracy: LocationAccuracy.high, distanceFilter: 2),
|
|
).listen((Position pos) {
|
|
position = pos;
|
|
notifyListeners();
|
|
}, onError: (Object e) {
|
|
problem = e.toString();
|
|
notifyListeners();
|
|
});
|
|
} catch (e) {
|
|
problem = e.toString();
|
|
notifyListeners();
|
|
}
|
|
}
|
|
|
|
@override
|
|
void dispose() {
|
|
_sub?.cancel();
|
|
super.dispose();
|
|
}
|
|
}
|