From 1a714bcdebb0b64938ada15b664fe8d5ae699983 Mon Sep 17 00:00:00 2001 From: jusax23 Date: Thu, 21 Sep 2023 16:05:34 +0200 Subject: [PATCH] avaibility, compass big box --- lib/boxes/compass.dart | 182 ++++++++++++++++--------- lib/boxes/maps.dart | 292 +++++++++++++++++++++++------------------ lib/main.dart | 2 +- 3 files changed, 284 insertions(+), 192 deletions(-) diff --git a/lib/boxes/compass.dart b/lib/boxes/compass.dart index 2189363..27d0376 100644 --- a/lib/boxes/compass.dart +++ b/lib/boxes/compass.dart @@ -27,35 +27,50 @@ base class GnssLocData extends Struct { // end c-structs class Compass extends JuBox { - const Compass({super.key}); + final bool small; + const Compass(this.small, {super.key}); @override - State createState() => _CompassState(); + // ignore: no_logic_in_create_state + State createState() => _CompassState(small); } class _CompassState extends State { + final bool small; + + _CompassState(this.small) : super(); + USerial serial = getSerial(); - late Timer timer; + Timer? timer; int _magX = 0, _magY = 0, _magZ = 0, _magAngle = 0; + bool available = true; @override void initState() { super.initState(); SensorReader.listen(serialListen); - timer = Timer.periodic(const Duration(milliseconds: 500), (_) async { - serial.sprintln("2200", system: true); - }); + if (small) { + timer = Timer.periodic(const Duration(milliseconds: 500), (_) async { + if (available) serial.sprintln("2200", system: true); + }); + } } @override void dispose() { SensorReader.removeListen(serialListen); - timer.cancel(); + timer?.cancel(); super.dispose(); } void serialListen(int type, int command, Pointer ptr) { + if (type == 0x22 && command == 0xff) { + setState(() { + available = false; + }); + return; + } if (type != 0x22 || command != 0x00) return; var loc = ptr as Pointer; setState(() { @@ -70,64 +85,101 @@ class _CompassState extends State { } @override - Widget build(BuildContext context) => Stack( - children: [ - SvgPicture.asset('assets/compass.svg'), - AnimatedRotation( - turns: _magAngle / 360.0, - duration: const Duration(milliseconds: 500), - alignment: Alignment.center, // Rotate around the center - child: SvgPicture.asset('assets/needle.svg')), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "x: ${(_magX * 8.0 / 32768.0 * 100.0).toStringAsFixed(2)}µT"), - Text( - "y: ${(_magY * 8.0 / 32768.0 * 100.0).toStringAsFixed(2)}µT"), - Text( - "z: ${(_magZ * 8.0 / 32768.0 * 100.0).toStringAsFixed(2)}µT"), - Expanded( - child: Align( - alignment: Alignment.bottomLeft, - child: FilledButton( - child: const Icon(Icons.calculate), - onPressed: () { - showDialog( - context: context, - builder: (BuildContext context) => AlertDialog( - title: const Text('Callibrate Compass'), - content: const Text( - 'When clicking okay the compass will be calibrated, \ncompletely blocking all radio communication for 10 sec. \nWhile calibrating rotate the sensor in ever direction.'), - actions: [ - TextButton( - onPressed: () => Navigator.pop(context, 'Cancel'), - child: const Text('Cancel'), - ), - TextButton( - onPressed: () { - serial.sprintln("2201", - system: true); - Navigator.pop(context, 'OK'); - }, - child: const Text('OK'), - ), - ], - ), - ); - // - }, - ), - ), + Widget build(BuildContext context) => small + ? GestureDetector( + onTap: () { + if (available) { + Navigator.push( + context, + MaterialPageRoute(builder: (context) => const Compass(false)), + ); + } else { + available = true; + } + }, + child: buildLoc(context)) + : Scaffold( + appBar: AppBar( + backgroundColor: Theme.of(context).colorScheme.inversePrimary, + title: const Text( + "Compass", + style: TextStyle( + fontSize: 16, ), - ], + ), + toolbarHeight: 40, ), - Expanded( - child: Align( - alignment: Alignment.topRight, - child: Text( - "t: ${(sqrt(_magX * _magX + _magY * _magY + _magZ * _magZ) * 8.0 / 32768.0 * 100.0).toStringAsFixed(2)}µT"), - )) - ], - ); + body: Container( + padding: const EdgeInsets.all(0.3 * 2 * 20), + child: buildLoc(context)), + ); + + Widget buildLoc(BuildContext context) => !available + ? const Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [Text("Compass is not available!"), Icon(Icons.block)])) + : Stack( + children: [ + Center(child: SvgPicture.asset('assets/compass.svg')), + Center( + child: AnimatedRotation( + turns: _magAngle / 360.0, + duration: const Duration(milliseconds: 500), + alignment: Alignment.center, // Rotate around the center + child: SvgPicture.asset('assets/needle.svg'))), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "x: ${(_magX * 8.0 / 32768.0 * 100.0).toStringAsFixed(2)}µT"), + Text( + "y: ${(_magY * 8.0 / 32768.0 * 100.0).toStringAsFixed(2)}µT"), + Text( + "z: ${(_magZ * 8.0 / 32768.0 * 100.0).toStringAsFixed(2)}µT"), + if (!small) + Expanded( + child: Align( + alignment: Alignment.bottomLeft, + child: FilledButton( + child: const Icon(Icons.calculate), + onPressed: () { + showDialog( + context: context, + builder: (BuildContext context) => AlertDialog( + title: const Text('Callibrate Compass'), + content: const Text( + 'When clicking okay the compass will be calibrated, \ncompletely blocking all radio communication for 10 sec. \nWhile calibrating rotate the sensor in ever direction.'), + actions: [ + TextButton( + onPressed: () => + Navigator.pop(context, 'Cancel'), + child: const Text('Cancel'), + ), + TextButton( + onPressed: () { + serial.sprintln("2201", + system: true); + Navigator.pop(context, 'OK'); + }, + child: const Text('OK'), + ), + ], + ), + ); + // + }, + ), + ), + ), + ], + ), + Align( + alignment: Alignment.topRight, + child: Text( + "t: ${(sqrt(_magX * _magX + _magY * _magY + _magZ * _magZ) * 8.0 / 32768.0 * 100.0).toStringAsFixed(2)}µT"), + ) + ], + ); } diff --git a/lib/boxes/maps.dart b/lib/boxes/maps.dart index 217e323..7e18c90 100644 --- a/lib/boxes/maps.dart +++ b/lib/boxes/maps.dart @@ -108,13 +108,14 @@ class _MapsState extends State with TickerProviderStateMixin { int _state = 0; bool _wasVaild = false; final _mapController = MapController(); + bool available = true; @override void initState() { super.initState(); SensorReader.listen(serialListen); timer = Timer.periodic(const Duration(seconds: 1), (_) async { - serial.sprintln("2300", system: true); + if (available) serial.sprintln("2300", system: true); }); } @@ -126,6 +127,12 @@ class _MapsState extends State with TickerProviderStateMixin { } void serialListen(int type, int command, Pointer ptr) { + if (type == 0x23 && command == 0xff) { + setState(() { + available = false; + }); + return; + } if (type != 0x23 || command != 0x00) return; var loc = ptr as Pointer; setState(() { @@ -140,46 +147,61 @@ class _MapsState extends State with TickerProviderStateMixin { } @override - Widget build(BuildContext context) => FlutterMap( - options: MapOptions( - center: LatLng(_lat, _long), - zoom: _wasVaild ? 17 : 6, - maxZoom: _wasVaild ? 17 : 6, - minZoom: _wasVaild ? 17 : 6, - interactiveFlags: InteractiveFlag.none, - onTap: (TapPosition pos, LatLng ll) { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => const SerialDetailPage()), - ); - }), - mapController: _mapController, - children: [ - TileLayer( - urlTemplate: 'https://tile.openstreetmap.de/{z}/{x}/{y}.png', - userAgentPackageName: 'de.jusax.ju_rc_app', - ), - MarkerLayer( - markers: [ - Marker( - point: LatLng(_lat, _long), - width: 100, - height: 100, - builder: (context) => Icon( - switch (_state) { - 3 => Icons.location_on, - 2 => Icons.location_off, - 1 => Icons.location_on_outlined, - int() => Icons.location_off_outlined, - }, - color: Theme.of(context).colorScheme.primary, + Widget build(BuildContext context) => !available + ? GestureDetector( + onTap: () { + if (!available) { + available = true; + } + }, + child: const Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Text("GNSS is not available!"), + Icon(Icons.block) + ]))) + : FlutterMap( + options: MapOptions( + center: LatLng(_lat, _long), + zoom: _wasVaild ? 17 : 6, + maxZoom: _wasVaild ? 17 : 6, + minZoom: _wasVaild ? 17 : 6, + interactiveFlags: InteractiveFlag.none, + onTap: (TapPosition pos, LatLng ll) { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => const SerialDetailPage()), + ); + }), + mapController: _mapController, + children: [ + TileLayer( + urlTemplate: 'https://tile.openstreetmap.de/{z}/{x}/{y}.png', + userAgentPackageName: 'de.jusax.ju_rc_app', + ), + MarkerLayer( + markers: [ + Marker( + point: LatLng(_lat, _long), + width: 100, + height: 100, + builder: (context) => Icon( + switch (_state) { + 3 => Icons.location_on, + 2 => Icons.location_off, + 1 => Icons.location_on_outlined, + int() => Icons.location_off_outlined, + }, + color: Theme.of(context).colorScheme.primary, + ), ), - ), - ], - ), - ], - ); + ], + ), + ], + ); } class SerialDetailPage extends StatefulWidget { @@ -206,11 +228,13 @@ class _SerialDetailPageState extends State _hdopState = false; int _satN = -1; bool _follow = true; + bool available = true; @override void initState() { super.initState(); timer = Timer.periodic(const Duration(seconds: 2), (_) async { + if(!available) return; serial.sprintln("2303", system: true); sleep(const Duration(milliseconds: 200)); serial.sprintln("2304", system: true); @@ -233,6 +257,7 @@ class _SerialDetailPageState extends State void serialListen(int type, int command, Pointer ptr) { if (type != 0x23) return; + command = 0xff; switch (command) { case 0: { @@ -295,7 +320,11 @@ class _SerialDetailPageState extends State } break; case 0xff: - {} + { + setState(() { + available = false; + }); + } break; } } @@ -327,91 +356,102 @@ class _SerialDetailPageState extends State }, child: Icon(_follow ? Icons.near_me : Icons.near_me_outlined), ), - body: Column(children: [ - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - "Speed: ${_mps.toStringAsPrecision(3)}m/s", - style: TextStyle( - backgroundColor: - _mpsState ? Colors.green[shade()] : Colors.red[shade()]), - ), - const VerticalDivider(width: 5), - Text("Course: ${_course.toStringAsFixed(0)}°", - style: TextStyle( - backgroundColor: _courseState - ? Colors.green[shade()] - : Colors.red[shade()])), - const VerticalDivider(width: 5), - Text("Alt: ${_alt.toStringAsPrecision(4)}m", - style: TextStyle( - backgroundColor: _altState - ? Colors.green[shade()] - : Colors.red[shade()])), - const VerticalDivider(width: 5), - Text("Sats: $_satN", - style: TextStyle( - backgroundColor: _satNState - ? Colors.green[shade()] - : Colors.red[shade()])), - const VerticalDivider(width: 5), - Text("Hdop: ${_hdop.toStringAsPrecision(2)}", - style: TextStyle( - backgroundColor: _hdopState - ? Colors.green[shade()] - : Colors.red[shade()])), - ], - ), - Expanded( - child: FlutterMap( - mapController: _mapController, - options: MapOptions( - center: const LatLng(51.1667, 10.4500), - zoom: 6, - maxZoom: 18, - interactiveFlags: InteractiveFlag.drag | - InteractiveFlag.flingAnimation | - InteractiveFlag.pinchMove | - InteractiveFlag.pinchZoom | - InteractiveFlag.doubleTapZoom, - onPositionChanged: (MapPosition pos, bool user) { - if (user) { - setState(() { - _follow = false; - }); - } - }), - children: [ - TileLayer( - urlTemplate: 'https://tile.openstreetmap.de/{z}/{x}/{y}.png', - //urlTemplate: 'https://sgx.geodatenzentrum.de/wmts_basemapde/tile/1.0.0/de_basemapde_web_raster_farbe/default/GLOBAL_WEBMERCATOR/{z}/{y}/{x}.png', - userAgentPackageName: 'de.jusax.ju_rc_app', - ), - MarkerLayer( - markers: [ - Marker( - point: LatLng(_lat, _long), - width: 100, - height: 100, - builder: (context) => Transform.rotate( - angle: _course * - (pi / 180), // Convert degrees to radians - child: Icon( - switch (_state) { - 3 => Icons.navigation, - 2 => Icons.location_off, - 1 => Icons.navigation_outlined, - int() => Icons.location_off_outlined, - }, - color: Theme.of(context).colorScheme.primary, - ), - )), - ], - ), - ], - )) - ])); + body: !available + ? const Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Text("GNSS is not available!"), + Icon(Icons.block) + ])) + : Column(children: [ + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + "Speed: ${_mps.toStringAsPrecision(3)}m/s", + style: TextStyle( + backgroundColor: _mpsState + ? Colors.green[shade()] + : Colors.red[shade()]), + ), + const VerticalDivider(width: 5), + Text("Course: ${_course.toStringAsFixed(0)}°", + style: TextStyle( + backgroundColor: _courseState + ? Colors.green[shade()] + : Colors.red[shade()])), + const VerticalDivider(width: 5), + Text("Alt: ${_alt.toStringAsPrecision(4)}m", + style: TextStyle( + backgroundColor: _altState + ? Colors.green[shade()] + : Colors.red[shade()])), + const VerticalDivider(width: 5), + Text("Sats: $_satN", + style: TextStyle( + backgroundColor: _satNState + ? Colors.green[shade()] + : Colors.red[shade()])), + const VerticalDivider(width: 5), + Text("Hdop: ${_hdop.toStringAsPrecision(2)}", + style: TextStyle( + backgroundColor: _hdopState + ? Colors.green[shade()] + : Colors.red[shade()])), + ], + ), + Expanded( + child: FlutterMap( + mapController: _mapController, + options: MapOptions( + center: const LatLng(51.1667, 10.4500), + zoom: 6, + maxZoom: 18, + interactiveFlags: InteractiveFlag.drag | + InteractiveFlag.flingAnimation | + InteractiveFlag.pinchMove | + InteractiveFlag.pinchZoom | + InteractiveFlag.doubleTapZoom, + onPositionChanged: (MapPosition pos, bool user) { + if (user) { + setState(() { + _follow = false; + }); + } + }), + children: [ + TileLayer( + urlTemplate: + 'https://tile.openstreetmap.de/{z}/{x}/{y}.png', + //urlTemplate: 'https://sgx.geodatenzentrum.de/wmts_basemapde/tile/1.0.0/de_basemapde_web_raster_farbe/default/GLOBAL_WEBMERCATOR/{z}/{y}/{x}.png', + userAgentPackageName: 'de.jusax.ju_rc_app', + ), + MarkerLayer( + markers: [ + Marker( + point: LatLng(_lat, _long), + width: 100, + height: 100, + builder: (context) => Transform.rotate( + angle: _course * + (pi / 180), // Convert degrees to radians + child: Icon( + switch (_state) { + 3 => Icons.navigation, + 2 => Icons.location_off, + 1 => Icons.navigation_outlined, + int() => Icons.location_off_outlined, + }, + color: Theme.of(context).colorScheme.primary, + ), + )), + ], + ), + ], + )) + ])); } // animated Map from Map lib provider diff --git a/lib/main.dart b/lib/main.dart index 270dcde..8b8b9ef 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -49,8 +49,8 @@ class _MyHomePageState extends State { static List boxes = [ const ControllerState(), + const Compass(true), const Maps(), - const Compass(), const SerialBox(), ];