diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index 8cbe2e9..a2874b0 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -4,11 +4,13 @@
+
+
-
-
@@ -44,7 +37,5 @@
-
-
diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties
index 296b146..da44bc1 100644
--- a/android/gradle/wrapper/gradle-wrapper.properties
+++ b/android/gradle/wrapper/gradle-wrapper.properties
@@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-6.3-all.zip
diff --git a/assets/offline_layers/oaci_vfr/.gitkeep b/assets/offline_layers/oaci_vfr/.gitkeep
deleted file mode 100644
index e69de29..0000000
diff --git a/bin/download_oaci_vfr.dart b/bin/download_oaci_vfr.dart
index cd23575..a86bc9a 100644
--- a/bin/download_oaci_vfr.dart
+++ b/bin/download_oaci_vfr.dart
@@ -27,7 +27,7 @@ Future downloadTile(http.Client client, int x, int y, int zoom) async {
String url =
'https://wxs.ign.fr/an7nvfzojv5wa96dsga5nk8w/geoportail/wmts?layer=GEOGRAPHICALGRIDSYSTEMS.MAPS.SCAN-OACI&style=normal&tilematrixset=PM&Service=WMTS&Request=GetTile&Version=1.0.0&Format=image/jpeg&TileMatrix=$zoom&TileCol=$y&TileRow=$x';
- var response = await client.get(url);
+ var response = await client.get(Uri.parse(url));
if (response.statusCode == 200) {
print('Downloaded $zoom/$x-$y.');
diff --git a/lib/flight_recorder.dart b/lib/flight_recorder.dart
index f11994e..b901577 100644
--- a/lib/flight_recorder.dart
+++ b/lib/flight_recorder.dart
@@ -1,15 +1,14 @@
import 'dart:io';
-import 'package:latlong/latlong.dart';
+import 'package:latlong2/latlong.dart';
import 'package:vfr_light/instruments_data_source.dart';
class FlightRecorder {
IOSink _outputSink;
- LatLng _lastPosition;
+ LatLng? _lastPosition;
- FlightRecorder(File outputFile) {
- _outputSink = outputFile.openWrite();
+ FlightRecorder(File outputFile) : _outputSink = outputFile.openWrite() {
_outputSink.writeln(
'longitude,latitude,altitudeInM,heightInM,speedInKmH,datetime');
}
@@ -18,7 +17,7 @@ class FlightRecorder {
if (_lastPosition == null || _lastPosition != data.position) {
_lastPosition = data.position;
_outputSink.writeln(
- '${data.position.longitude},${data.position.latitude},${data.altitudeInM.round()},${data.heightInM.round()},${data.speedInKmH.round()},${data.time.toIso8601String()}');
+ '${data.position.longitude},${data.position.latitude},${data.altitudeInM?.round() ?? ''},${data.heightInM?.round() ?? ''},${data.speedInKmH.round()},${data.time.toIso8601String()}');
}
}
diff --git a/lib/instruments.dart b/lib/instruments.dart
index 969945d..58b5029 100644
--- a/lib/instruments.dart
+++ b/lib/instruments.dart
@@ -9,7 +9,7 @@ class Instruments extends StatelessWidget {
final InstrumentsData data;
- const Instruments({Key key, @required this.data}) : super(key: key);
+ const Instruments({Key? key, required this.data}) : super(key: key);
@override
Widget build(BuildContext context) {
@@ -25,17 +25,14 @@ class Instruments extends StatelessWidget {
style: Theme.of(context).textTheme.subtitle2),
Text(
data.heightInM != null
- ? StandardAtmosphere.feetFromMeters(data.heightInM)
+ ? StandardAtmosphere.feetFromMeters(data.heightInM!)
.round()
.toString()
: '???',
style: commonStyle),
Text('Height (m)',
style: Theme.of(context).textTheme.subtitle2),
- Text(
- data.heightInM != null
- ? data.heightInM.round().toString()
- : '???',
+ Text(data.heightInM?.round().toString() ?? '???',
style: commonStyle),
],
),
@@ -46,17 +43,15 @@ class Instruments extends StatelessWidget {
style: Theme.of(context).textTheme.subtitle2),
Text(
data.altitudeInM != null
- ? StandardAtmosphere.feetFromMeters(data.altitudeInM)
+ ? StandardAtmosphere.feetFromMeters(data.altitudeInM!)
.round()
.toString()
: '???',
style: commonStyle),
Text('Altitude (m)',
style: Theme.of(context).textTheme.subtitle2),
- Text(
- data.altitudeInM != null
- ? data.altitudeInM.round().toString()
- : '???',
+ Text(data.altitudeInM?.round().toString() ?? '???',
+ // FIXME only one ?.?
style: commonStyle),
],
),
@@ -65,18 +60,10 @@ class Instruments extends StatelessWidget {
children: [
Text('Heading (°)',
style: Theme.of(context).textTheme.subtitle2),
- Text(
- data.headingInDeg != null
- ? data.headingInDeg.round().toString()
- : '???',
- style: commonStyle),
+ Text(data.headingInDeg.round().toString(), style: commonStyle),
Text('Speed (km/h)',
style: Theme.of(context).textTheme.subtitle2),
- Text(
- data.speedInKmH != null
- ? data.speedInKmH.round().toString()
- : '???',
- style: commonStyle),
+ Text(data.speedInKmH.round().toString(), style: commonStyle),
],
),
],
diff --git a/lib/instruments_data_source.dart b/lib/instruments_data_source.dart
index 30dfc6f..db3825f 100644
--- a/lib/instruments_data_source.dart
+++ b/lib/instruments_data_source.dart
@@ -1,26 +1,25 @@
import 'dart:async';
-import 'package:enviro_sensors/enviro_sensors.dart';
+import 'package:environment_sensors/environment_sensors.dart';
import 'package:geolocator/geolocator.dart';
-import 'package:meta/meta.dart';
import 'standard_atmosphere.dart';
-import 'package:latlong/latlong.dart';
+import 'package:latlong2/latlong.dart';
class InstrumentsData {
final LatLng position;
- final double speedInKmH;
- final double altitudeInM;
- final double heightInM;
final double headingInDeg;
final DateTime time;
+ final double speedInKmH;
+ final double? altitudeInM;
+ final double? heightInM;
InstrumentsData(
- {@required this.position,
- @required this.speedInKmH,
- @required this.altitudeInM,
- @required this.heightInM,
- @required this.headingInDeg,
- @required this.time});
+ {required this.position,
+ required this.headingInDeg,
+ required this.time,
+ required this.speedInKmH,
+ required this.altitudeInM,
+ required this.heightInM});
}
class InstrumentsDataSource {
@@ -31,23 +30,25 @@ class InstrumentsDataSource {
final StreamController _instrumentsDataStream =
StreamController.broadcast();
- StreamSubscription _pressureSubscription;
- StreamSubscription _positionSubscription;
+ late StreamSubscription _pressureSubscription;
+ late StreamSubscription _positionSubscription;
- LatLng _lastPosition;
- double _lastSpeedInKmH;
- double _lastAltitudeInM;
- double _lastHeightInM;
- double _lastHeadingInDeg;
+ LatLng? _lastPosition;
+ double? _lastSpeedInKmH;
+ double? _lastAltitudeInM;
+ double? _lastHeightInM;
+ double? _lastHeadingInDeg;
+ double? _lastPressure;
- InstrumentsDataSource(
- {@required this.qnh, @required this.surfaceAltitudeInM}) {
+ InstrumentsDataSource({required this.qnh, required this.surfaceAltitudeInM}) {
_positionSubscription =
- getPositionStream(desiredAccuracy: LocationAccuracy.high)
+ Geolocator.getPositionStream(desiredAccuracy: LocationAccuracy.high)
.listen(_onNewPosition);
- _pressureSubscription =
- barometerEvents.asBroadcastStream().listen(_onNewPressure);
+ _pressureSubscription = EnvironmentSensors()
+ .pressure
+ .asBroadcastStream()
+ .listen(_onNewPressure);
}
void dispose() {
@@ -55,42 +56,48 @@ class InstrumentsDataSource {
_positionSubscription.cancel();
}
- Future recalibrateAtSfc({@required double surfaceAltitudeInM}) async {
+ Future recalibrateAtSfc({required double surfaceAltitudeInM}) async {
this.surfaceAltitudeInM = surfaceAltitudeInM;
- qnh = StandardAtmosphere.qnh(
- pressure: (await barometerEvents.asBroadcastStream().first).reading,
- altitude: surfaceAltitudeInM);
+ if (_lastPressure != null) {
+ qnh = StandardAtmosphere.qnh(
+ pressure: _lastPressure!, altitude: surfaceAltitudeInM);
+ }
}
Stream get data => _instrumentsDataStream.stream;
- LatLng get lastPosition => _lastPosition;
+ LatLng? get lastPosition => _lastPosition;
void _sendData() {
_instrumentsDataStream.add(InstrumentsData(
- position: _lastPosition,
- speedInKmH: _lastSpeedInKmH,
+ position: _lastPosition!,
+ speedInKmH: _lastSpeedInKmH!,
+ headingInDeg: _lastHeadingInDeg!,
+ time: DateTime.now(),
altitudeInM: _lastAltitudeInM,
- heightInM: _lastHeightInM,
- headingInDeg: _lastHeadingInDeg,
- time: DateTime.now()));
+ heightInM: _lastHeightInM));
}
void _onNewPosition(Position position) {
- this._lastPosition = LatLng(position.latitude, position.longitude);
+ _lastPosition = LatLng(position.latitude, position.longitude);
_lastSpeedInKmH = position.speed * 3.6;
_lastHeadingInDeg = position.heading;
_sendData();
}
- void _onNewPressure(BarometerEvent event) {
+ void _onNewPressure(double pressure) {
_lastAltitudeInM =
- StandardAtmosphere.altitude(qnh: qnh, pressure: event.reading);
+ StandardAtmosphere.altitude(qnh: qnh, pressure: pressure);
- _lastHeightInM = _lastAltitudeInM - surfaceAltitudeInM;
+ _lastHeightInM = _lastAltitudeInM! - surfaceAltitudeInM;
+ _lastPressure = pressure;
- _sendData();
+ if (_lastPosition != null &&
+ _lastSpeedInKmH != null &&
+ _lastHeadingInDeg != null) {
+ _sendData();
+ }
}
}
diff --git a/lib/map/flight_map.dart b/lib/map/flight_map.dart
index b79a6df..2e8ee6d 100644
--- a/lib/map/flight_map.dart
+++ b/lib/map/flight_map.dart
@@ -1,11 +1,10 @@
import 'dart:async';
-import 'dart:math';
import 'package:flutter/material.dart';
import 'package:flutter_map/flutter_map.dart';
import 'package:vfr_light/instruments_data_source.dart';
-import 'package:latlong/latlong.dart';
+import 'package:latlong2/latlong.dart';
import '../preset_layers.dart';
class FlightMap extends StatefulWidget {
@@ -14,10 +13,10 @@ class FlightMap extends StatefulWidget {
final LongPressCallback onLongPress;
const FlightMap(
- {Key key,
- @required this.dataStream,
- @required this.onLongPress,
- this.route})
+ {Key? key,
+ required this.dataStream,
+ required this.onLongPress,
+ required this.route})
: super(key: key);
@override
@@ -27,10 +26,10 @@ class FlightMap extends StatefulWidget {
class _FlightMapState extends State {
bool _centerOnPosition = false;
- Marker _planeMarker;
+ Marker? _planeMarker;
MapController _mapController = MapController();
- StreamSubscription _dataSubscription;
- Polyline _headingPolyline;
+ late StreamSubscription _dataSubscription;
+ Polyline? _headingPolyline;
@override
void initState() {
@@ -41,7 +40,7 @@ class _FlightMapState extends State {
@override
void dispose() {
- _dataSubscription?.cancel();
+ _dataSubscription.cancel();
super.dispose();
}
@@ -57,13 +56,16 @@ class _FlightMapState extends State {
zoom: 10.0,
swPanBoundary: LatLng(41.327326, -5.734863),
nePanBoundary: LatLng(51.138001, 9.382324),
- onLongPress: widget.onLongPress),
+ onLongPress: widget.onLongPress,
+ interactiveFlags: InteractiveFlag.drag |
+ InteractiveFlag.pinchZoom |
+ InteractiveFlag.pinchMove),
layers: [
TileLayerOptions(
urlTemplate:
"https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",
subdomains: ['a', 'b', 'c']),
- // PresetLayers.oaciVfrFrance,
+ // PresetLayers.oaciVfrFrance,
TileLayerOptions(
opacity: 0.5,
tileProvider: AssetTileProvider(),
@@ -71,11 +73,11 @@ class _FlightMapState extends State {
minNativeZoom: 8,
maxNativeZoom: 11),
PolylineLayerOptions(polylines: [
- if (_headingPolyline != null) _headingPolyline,
- if (widget.route != null) widget.route
+ if (_headingPolyline != null) _headingPolyline!,
+ widget.route
]),
MarkerLayerOptions(markers: [
- if (_planeMarker != null) _planeMarker,
+ if (_planeMarker != null) _planeMarker!,
...widget.route.points
.asMap()
.entries
@@ -126,19 +128,17 @@ class _FlightMapState extends State {
_mapController.move(data.position, _mapController.zoom);
}
- if (data.headingInDeg != null) {
- _headingPolyline = _headingLine(data.position, data.headingInDeg);
+ _headingPolyline = _headingLine(data.position, data.headingInDeg);
- _planeMarker = Marker(
- point: data.position,
- builder: (context) {
- return Transform.rotate(
- angle: data.headingInDeg * 2 * pi / 360,
- child: Icon(Icons.airplanemode_active,
- color: Colors.purpleAccent));
- });
+ _planeMarker = Marker(
+ point: data.position,
+ builder: (context) {
+ return Transform.rotate(
+ angle: data.headingInDeg * 2 * pi / 360,
+ child:
+ Icon(Icons.airplanemode_active, color: Colors.purpleAccent));
+ });
- setState(() {});
- }
+ setState(() {});
}
}
diff --git a/lib/map/map_screen.dart b/lib/map/map_screen.dart
index 9b0a321..d971737 100644
--- a/lib/map/map_screen.dart
+++ b/lib/map/map_screen.dart
@@ -2,9 +2,10 @@ import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
+import 'package:flutter_background/flutter_background.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
-import 'package:latlong/latlong.dart';
+import 'package:latlong2/latlong.dart';
import 'package:wakelock/wakelock.dart';
import '../record_button.dart';
@@ -23,12 +24,10 @@ class MapScreen extends StatefulWidget {
}
class _MapScreenState extends State {
- InstrumentsDataSource _instrumentsDataSource;
- RouteManager _routeManager;
-
- NavigationDataSource _navigationDataSource;
-
- StreamSubscription _destinationStreamSubscription;
+ late InstrumentsDataSource _instrumentsDataSource;
+ late RouteManager _routeManager;
+ NavigationDataSource? _navigationDataSource;
+ late StreamSubscription _destinationStreamSubscription;
@override
void initState() {
@@ -49,6 +48,14 @@ class _MapScreenState extends State {
destination: event, stream: _instrumentsDataSource.data);
setState(() {});
});
+
+ final androidConfig = FlutterBackgroundAndroidConfig(
+ notificationTitle: "VFR Light location service",
+ notificationText:
+ "Enables recording of GPS data while app is in the background.",
+ );
+ Future success =
+ FlutterBackground.initialize(androidConfig: androidConfig);
}
@override
@@ -113,7 +120,7 @@ class _MapScreenState extends State {
},
),
SizedBox(height: 8),
- RaisedButton(
+ ElevatedButton(
child: Text('Submit'),
onPressed: () {
print(double.parse(val));
@@ -163,13 +170,12 @@ class _MapScreenState extends State {
),
if (_navigationDataSource != null)
StreamBuilder(
- stream: _navigationDataSource.data,
+ stream: _navigationDataSource!.data,
builder:
(BuildContext context, AsyncSnapshot snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.active:
return NavigationInfo(data: snapshot.data);
- break;
case ConnectionState.none:
case ConnectionState.waiting:
@@ -181,7 +187,6 @@ class _MapScreenState extends State {
style: Theme.of(context).textTheme.headline6,
),
);
- break;
}
}),
Expanded(
@@ -196,7 +201,6 @@ class _MapScreenState extends State {
switch (snapshot.connectionState) {
case ConnectionState.active:
return Instruments(data: snapshot.data);
- break;
case ConnectionState.none:
case ConnectionState.waiting:
@@ -208,7 +212,6 @@ class _MapScreenState extends State {
style: Theme.of(context).textTheme.headline6,
),
);
- break;
}
}),
],
diff --git a/lib/navigation_data_source.dart b/lib/navigation_data_source.dart
index b245d5b..6e2b696 100644
--- a/lib/navigation_data_source.dart
+++ b/lib/navigation_data_source.dart
@@ -1,30 +1,27 @@
import 'dart:async';
-import 'package:meta/meta.dart';
import 'instruments_data_source.dart';
-import 'package:latlong/latlong.dart';
+import 'package:latlong2/latlong.dart';
class NavigationData {
- final double distanceInM;
- final Duration duration;
- final DateTime eta;
+ final double? distanceInM;
+ final Duration? duration;
+ final DateTime? eta;
NavigationData(
- {@required this.distanceInM,
- @required this.duration,
- @required this.eta});
+ {required this.distanceInM, required this.duration, required this.eta});
}
class NavigationDataSource {
final StreamController _navigationDataStream =
StreamController.broadcast();
- StreamSubscription _subscription;
+ late StreamSubscription _subscription;
LatLng destination;
NavigationDataSource(
- {@required this.destination, @required Stream stream}) {
+ {required this.destination, required Stream stream}) {
_subscription = stream.listen(_onNewData);
}
@@ -35,20 +32,18 @@ class NavigationDataSource {
Stream get data => _navigationDataStream.stream;
void _onNewData(InstrumentsData data) {
- double distanceInM;
- Duration duration;
- DateTime eta;
+ double? distanceInM;
+ Duration? duration;
+ DateTime? eta;
- if (data.position != null) {
- Distance d = Distance();
- distanceInM = d.distance(data.position, destination);
+ Distance d = Distance();
+ distanceInM = d.distance(data.position, destination).toDouble();
- if (data.speedInKmH != null && data.speedInKmH > 5) {
- duration = Duration(
- minutes: (distanceInM / 1000 / data.speedInKmH * 60).round());
+ if (data.speedInKmH > 5) {
+ duration = Duration(
+ minutes: (distanceInM / 1000 / data.speedInKmH * 60).round());
- eta = DateTime.now().add(duration);
- }
+ eta = DateTime.now().add(duration);
}
_navigationDataStream.add(
diff --git a/lib/navigation_info.dart b/lib/navigation_info.dart
index 0677bb5..2d17786 100644
--- a/lib/navigation_info.dart
+++ b/lib/navigation_info.dart
@@ -8,7 +8,7 @@ class NavigationInfo extends StatelessWidget {
final NavigationData data;
- const NavigationInfo({Key key, @required this.data}) : super(key: key);
+ const NavigationInfo({Key? key, required this.data}) : super(key: key);
@override
Widget build(BuildContext context) {
@@ -24,7 +24,7 @@ class NavigationInfo extends StatelessWidget {
style: Theme.of(context).textTheme.subtitle2),
Text(
data.distanceInM != null
- ? (data.distanceInM / 1000).toStringAsFixed(1)
+ ? (data.distanceInM! / 1000).toStringAsFixed(1)
: '???',
style: commonStyle),
],
@@ -35,7 +35,7 @@ class NavigationInfo extends StatelessWidget {
Text('Duration', style: Theme.of(context).textTheme.subtitle2),
Text(
data.duration != null
- ? '${data.duration.inHours}h${data.duration.inMinutes % 60}'
+ ? '${data.duration!.inHours}h${data.duration!.inMinutes % 60}'
: '???',
style: commonStyle),
],
@@ -46,7 +46,7 @@ class NavigationInfo extends StatelessWidget {
Text('ETA', style: Theme.of(context).textTheme.subtitle2),
Text(
data.eta != null
- ? '${data.eta.hour}:${data.eta.minute}'
+ ? '${data.eta!.hour}:${data.eta!.minute}'
: '???',
style: commonStyle),
],
diff --git a/lib/preset_layers.dart b/lib/preset_layers.dart
index 49b2db7..2c4dc37 100644
--- a/lib/preset_layers.dart
+++ b/lib/preset_layers.dart
@@ -5,28 +5,27 @@ import 'package:path_provider/path_provider.dart';
import 'package:flutter_cache_manager/flutter_cache_manager.dart';
import 'package:path/path.dart' as p;
-class LongTermCacheManager extends BaseCacheManager {
- static const key = 'libCachedImageDataLongTerm';
-
- static LongTermCacheManager _instance;
-
- factory LongTermCacheManager() {
- _instance ??= LongTermCacheManager._();
- return _instance;
- }
-
- LongTermCacheManager._() : super(key);
-
- @override
- Future getFilePath() async {
- var directory = (await getExternalCacheDirectories())[0];
- return p.join(directory.path, key);
- }
-}
+//
+// class LongTermCacheManager extends BaseCacheManager {
+// static const key = 'libCachedImageDataLongTerm';
+//
+// static LongTermCacheManager _instance;
+//
+// factory LongTermCacheManager() {
+// _instance ??= LongTermCacheManager._();
+// return _instance;
+// }
+//
+// LongTermCacheManager._() : super(key, maxNrOfCacheObjects: 10000);
+//
+// @override
+// Future getFilePath() async {
+// var directory = (await getExternalCacheDirectories())[0];
+// return p.join(directory.path, key);
+// }
+// }
class PresetLayers {
-
-
static TileLayerOptions oaciVfrFrance = TileLayerOptions(
opacity: 0.5,
urlTemplate:
diff --git a/lib/record_button.dart b/lib/record_button.dart
index 0841fe9..ec60f95 100644
--- a/lib/record_button.dart
+++ b/lib/record_button.dart
@@ -2,7 +2,7 @@ import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
-import 'package:flutter_foreground_plugin/flutter_foreground_plugin.dart';
+import 'package:flutter_background/flutter_background.dart';
import 'package:path_provider/path_provider.dart';
import 'flight_recorder.dart';
@@ -11,7 +11,7 @@ import 'instruments_data_source.dart';
class RecordButton extends StatefulWidget {
final InstrumentsDataSource dataSource;
- const RecordButton({Key key, @required this.dataSource}) : super(key: key);
+ const RecordButton({Key? key, required this.dataSource}) : super(key: key);
@override
_RecordButtonState createState() => _RecordButtonState();
@@ -19,8 +19,8 @@ class RecordButton extends StatefulWidget {
class _RecordButtonState extends State {
bool _isRecording = false;
- StreamSubscription _recorderSubscription;
- FlightRecorder _flightRecorder;
+ StreamSubscription? _recorderSubscription;
+ FlightRecorder? _flightRecorder;
@override
void dispose() {
@@ -50,42 +50,41 @@ class _RecordButtonState extends State {
setState(() {
_isRecording = false;
});
- _recorderSubscription.cancel();
+ _recorderSubscription?.cancel();
_recorderSubscription = null;
- _flightRecorder.dispose();
+ _flightRecorder?.dispose();
_flightRecorder = null;
- FlutterForegroundPlugin.stopForegroundService();
+ FlutterBackground.disableBackgroundExecution();
} else {
getExternalStorageDirectory().then((value) {
- DateTime now = DateTime.now();
- String path =
- '${value.path}/${now.year}-${now.month}-${now.day}_${now.hour}-${now.minute}.csv';
-
- File outputFile = File(path);
- print('Saving trace to $path');
-
- if (!outputFile.existsSync()) {
- _flightRecorder = FlightRecorder(outputFile);
-
- setState(() {
- _isRecording = true;
- });
-
- _recorderSubscription = widget.dataSource.data.listen((event) {
- _flightRecorder.appendData(event);
- });
- } else {
- print('File already exists!');
+ if (value != null) {
+ DateTime now = DateTime.now();
+ String path =
+ '${value.path}/${now.year}-${now.month}-${now.day}_${now.hour}-${now.minute}.csv';
+
+ File outputFile = File(path);
+ print('Saving trace to $path');
+
+ if (!outputFile.existsSync()) {
+ _flightRecorder = FlightRecorder(outputFile);
+
+ setState(() {
+ _isRecording = true;
+ });
+
+ _recorderSubscription = widget.dataSource.data.listen((event) {
+ _flightRecorder?.appendData(event);
+ });
+ } else {
+ print('File already exists!');
+ }
+
+ // Start a foreground service to keep receiving location updates when
+ // the app is in the background.
+ // Turns out I don't need any special background location library :-)
+ FlutterBackground.enableBackgroundExecution();
}
-
- // Start a foreground service to keep receiving location updates when
- // the app is in the background.
- // Turns out I don't need any special background location library :-)
- FlutterForegroundPlugin.startForegroundService(
- title: "No Fuss PPG location service",
- iconName: "ic_launcher",
- );
});
}
}
diff --git a/lib/route_editor.dart b/lib/route_editor.dart
index 633fd12..10af99a 100644
--- a/lib/route_editor.dart
+++ b/lib/route_editor.dart
@@ -1,10 +1,10 @@
import 'package:flutter/material.dart';
-import 'package:latlong/latlong.dart';
+import 'package:latlong2/latlong.dart';
class RouteEditor extends StatefulWidget {
final List waypoints;
- const RouteEditor({Key key, this.waypoints}) : super(key: key);
+ const RouteEditor({Key? key, required this.waypoints}) : super(key: key);
@override
_RouteEditorState createState() => _RouteEditorState();
@@ -30,12 +30,12 @@ class _RouteEditorState extends State {
double _tripLengthInM() {
double length = 0;
- LatLng from;
+ LatLng? from;
Distance d = Distance();
widget.waypoints.forEach((waypoint) {
if (from != null) {
- length += d.distance(from, waypoint);
+ length += d.distance(from!, waypoint);
}
from = waypoint;
@@ -46,12 +46,12 @@ class _RouteEditorState extends State {
List _legDistancesInM() {
List distances = [0];
- LatLng from;
+ LatLng? from;
Distance d = Distance();
widget.waypoints.forEach((waypoint) {
if (from != null) {
- distances.add(d.distance(from, waypoint));
+ distances.add(d.distance(from!, waypoint).toDouble());
}
from = waypoint;
diff --git a/lib/route_manager.dart b/lib/route_manager.dart
index 1fb4412..b1c0713 100644
--- a/lib/route_manager.dart
+++ b/lib/route_manager.dart
@@ -1,19 +1,18 @@
import 'dart:async';
-import 'package:meta/meta.dart';
import 'package:flutter_map/flutter_map.dart';
-import 'package:latlong/latlong.dart';
+import 'package:latlong2/latlong.dart';
import 'package:vfr_light/instruments_data_source.dart';
class RouteManager {
List waypoints = [];
StreamController _destinationStream = StreamController.broadcast();
final InstrumentsDataSource instrumentsDataSource;
- StreamSubscription _instrumentsDataSubscription;
+ late StreamSubscription _instrumentsDataSubscription;
int _destinationIndex = 0;
bool _navigationStarted = false;
- RouteManager({@required this.instrumentsDataSource}) {
+ RouteManager({required this.instrumentsDataSource}) {
_instrumentsDataSubscription =
instrumentsDataSource.data.listen(_onInstrumentsData);
}
@@ -28,7 +27,7 @@ class RouteManager {
Polyline routeRepresentation() {
if (instrumentsDataSource.lastPosition != null) {
return Polyline(
- points: [instrumentsDataSource.lastPosition] + waypoints,
+ points: [instrumentsDataSource.lastPosition!] + waypoints,
strokeWidth: 3);
} else {
return Polyline(points: waypoints, strokeWidth: 3);
@@ -50,10 +49,10 @@ class RouteManager {
}
void _onInstrumentsData(InstrumentsData data) {
- if (_navigationStarted && waypoints.isNotEmpty && data.position != null) {
+ if (_navigationStarted && waypoints.isNotEmpty) {
Distance d = Distance();
double distanceInM =
- d.distance(data.position, waypoints[_destinationIndex]);
+ d.distance(data.position, waypoints[_destinationIndex]).toDouble();
if (distanceInM < 20 && waypoints.length > _destinationIndex + 1) {
_destinationStream.add(waypoints[++_destinationIndex]);
diff --git a/lib/standard_atmosphere.dart b/lib/standard_atmosphere.dart
index adddb2f..c090a0e 100644
--- a/lib/standard_atmosphere.dart
+++ b/lib/standard_atmosphere.dart
@@ -1,16 +1,16 @@
import 'dart:math';
-import 'package:meta/meta.dart';
-
// https://fr.wikipedia.org/wiki/Atmosph%C3%A8re_normalis%C3%A9e
+// Pressures in millibar/hPA
+
class StandardAtmosphere {
- static double altitude({@required double pressure, @required double qnh}) {
- return (1 - pow((pressure / qnh), 1 / 5.255)) * 288.15 / 0.0065;
+ static double altitude({required double pressure, required double qnh}) {
+ return (1 - pow(pressure / qnh, 1 / 5.255)) * 288.15 / 0.0065;
}
- static double qnh({@required double pressure, @required double altitude}) {
- return pressure / pow((1 - 0.0065 * altitude / 288.15), 5.255);
+ static double qnh({required double pressure, required double altitude}) {
+ return pressure / pow(1 - 0.0065 * altitude / 288.15, 5.255);
}
static double feetFromMeters(double meters) {
diff --git a/lib/user_agent_tile_provider.dart b/lib/user_agent_tile_provider.dart
index a839a53..6ab9c9f 100644
--- a/lib/user_agent_tile_provider.dart
+++ b/lib/user_agent_tile_provider.dart
@@ -3,16 +3,13 @@ import 'package:flutter_map/flutter_map.dart';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:vfr_light/preset_layers.dart';
-export 'package:flutter_map/src/layer/tile_provider/mbtiles_image_provider.dart';
-
class UserAgentTileProvider extends TileProvider {
@override
ImageProvider