diff --git a/lib/pages/home/presentation/views/home_view.dart b/lib/pages/home/presentation/views/home_view.dart index 7b748ca..5222d4e 100644 --- a/lib/pages/home/presentation/views/home_view.dart +++ b/lib/pages/home/presentation/views/home_view.dart @@ -60,11 +60,18 @@ class HomeView extends GetView { child: Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ + // BigButtonWidget( + // iconData: Icons.flag, + // label: "Kitűzés", + // onPressed: () async { + // Get.toNamed('/map'); + // }, + // ), BigButtonWidget( iconData: Icons.flag, - label: "Kitűzés", + label: "Bemérés", onPressed: () async { - Get.toNamed('/map'); + Get.toNamed('/map_survey'); }, ), BigButtonWidget( diff --git a/lib/pages/map_survey/bindings/map_survey_bindings.dart b/lib/pages/map_survey/bindings/map_survey_bindings.dart new file mode 100644 index 0000000..8e24443 --- /dev/null +++ b/lib/pages/map_survey/bindings/map_survey_bindings.dart @@ -0,0 +1,9 @@ +import 'package:get/get.dart'; +import 'package:terepi_seged/pages/map_survey/presentations/controllers/map_survey_controller.dart'; + +class MapSurveyBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut(() => MapSurveyController()); + } +} diff --git a/lib/pages/map_survey/presentations/controllers/map_survey_controller.dart b/lib/pages/map_survey/presentations/controllers/map_survey_controller.dart new file mode 100644 index 0000000..5b17809 --- /dev/null +++ b/lib/pages/map_survey/presentations/controllers/map_survey_controller.dart @@ -0,0 +1,846 @@ +import 'dart:async'; +import 'dart:convert'; +import 'dart:io'; +import 'dart:math'; + +import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:file_picker/file_picker.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_bluetooth_serial/flutter_bluetooth_serial.dart'; +import 'package:flutter_map/flutter_map.dart'; +import 'package:flutter_map_geojson/flutter_map_geojson.dart'; +import 'package:flutter_map_polywidget/flutter_map_polywidget.dart'; +import 'package:get/get.dart'; +import 'package:intl/intl.dart'; +import 'package:location/location.dart'; +import 'package:latlong2/latlong.dart'; +import 'package:nmea/nmea.dart'; +import 'package:path_provider/path_provider.dart'; +import 'package:permission_handler/permission_handler.dart' + as permission_handler; +import 'package:supabase_flutter/supabase_flutter.dart'; +import 'package:terepi_seged/eov/convert_coordinate.dart'; +import 'package:terepi_seged/eov/eov.dart'; +import 'package:terepi_seged/gnss_sentences/gngga.dart'; +import 'package:terepi_seged/gnss_sentences/gngst.dart'; +import 'package:terepi_seged/gnss_sentences/gnrmc.dart'; +import 'package:terepi_seged/models/point_to_measure.dart'; +import 'package:terepi_seged/models/point_with_description_model.dart'; +import 'package:proj4dart/proj4dart.dart' as proj4; +import 'package:shared_preferences/shared_preferences.dart'; + +class MapSurveyController extends GetxController { + // String gpsAddress = "E8:31:CD:14:8B:B2"; + // String gpsAddress = "98:CD:AC:62:FF:4E"; + RxString gpsAddress = "98:CD:AC:62:FF:36".obs; + RxString gpsName = "TiGNSS Rover-FF4E".obs; + // String gpsName = "TiGNSS Rover-8BB2"; + static const double maxZoomValue = 25.0; + Rx gpsIsConnected = false.obs; + RxBool ntripIsConnected = false.obs; + RxInt ntripDataPacketNumbers = 0.obs; + RxInt ggaSenDataPacketNumber = 0.obs; + RxString ggaSendLastTimeStr = "".obs; + String _messageBuffer = ""; + late BluetoothConnection connection; + late Socket socket; + late StreamSubscription socketStreamSubscription; + RxInt gpsReceivedData = 0.obs; + RxBool hasGpsValidData = false.obs; + RxBool isMapMoveToCenter = true.obs; + DateTime lastGpsRefreshTime = DateTime.now(); + String utcOfPositionFix = ""; + String utcDateOfPositionFix = ""; + RxInt ntripReceivedData = 0.obs; + final NmeaDecoder nmeaDecoder = NmeaDecoder(); + String lastGgaMessage = ''; + DateTime lastSendTimeGgaMessage = + DateTime.now().add(const Duration(seconds: -30)); + + NumberFormat formatEov = NumberFormat("##0,000.0", "hu-HU"); + NumberFormat formatEovForFile = NumberFormat("#####0.0", "hu-HU"); + NumberFormat formatWgs84Sec = NumberFormat('00.000', 'hu-HU'); + + RxDouble gpsLatitude = 0.0.obs; + RxString gpsLatitudeDirection = "".obs; + RxDouble gpsLongitude = 0.0.obs; + RxString gpsLongitudeDirection = "".obs; + RxDouble gpsAltitude = 0.0.obs; + RxDouble gpsGeoidSeparation = 0.0.obs; + RxInt gpsQuality = 0.obs; + RxDouble gpsLatitudeError = 0.0.obs; + RxDouble gpsLongitudeError = 0.0.obs; + RxDouble gpsAltitudeError = 0.0.obs; + Rx gpsDateTime = DateTime(2000).obs; + Rx eov = Eov(0, 0).obs; + RxInt latDegree = 0.obs; + RxInt latMin = 0.obs; + RxDouble latSec = 0.0.obs; + RxInt longDegree = 0.obs; + RxInt longMin = 0.obs; + RxDouble longSec = 0.0.obs; + + RxDouble currentLongitude = 0.0.obs; + RxDouble currentLatitude = 0.0.obs; + RxDouble currentZoom = 12.0.obs; + late final MapController mapController; + final currentLocationMarker = []; + final pointNotesMarker = []; + + List pointsToMeasure = []; + final pointsToMeasureMarker = []; + final pointsToMeasureLabel = []; + + TextEditingController pointIdController = TextEditingController(); + TextEditingController pointDescriptionController = TextEditingController(); + TextEditingController gpsHeightController = TextEditingController(); + TextEditingController pointPrefixController = TextEditingController(); + TextEditingController pointPostfixController = TextEditingController(); + TextEditingController ntripUsernameController = TextEditingController(); + TextEditingController ntripPasswordController = TextEditingController(); + + int pointId = 1; + String pointIdPrefix = ""; + String pointIdPostfix = ""; + RxString ntripUserName = "".obs; + RxString ntripPassword = "".obs; + + Rx pointMeasuringDirectionForward = true.obs; + + Rx isShowPassword = true.obs; + + List pointWithDescriptionList = []; + late Directory? directory; + late File dataFile; + + late proj4.Projection eovProj, wgsProj; + RxBool mapIsInitialized = false.obs; + + GeoJsonParser parser = + GeoJsonParser(defaultMarkerColor: const Color.fromARGB(255, 85, 34, 49)); + + final CollectionReference _measuredPoints = + FirebaseFirestore.instance.collection('measuredPoints'); + + // late SMIBool gpsTrigger; + // late StateMachineController riveGpsIconController; + + late SharedPreferences prefs; + + late AuthResponse authResponse; + late Session? session; + late User? user; + + @override + void onInit() async { + super.onInit(); + final bytes = (await rootBundle.load('assets/Grids/etrs2eov_notowgs.gsb')) + .buffer + .asUint8List(); + proj4.Projection.nadgrid('Etrs2Eov', bytes); + // var def = + // '+proj=somerc +lat_0=47.14439372222222 +lon_0=19.04857177777778 +k_0=0.99993 +x_0=650000 +y_0=200000 +ellps=GRS67 +towgs84=52.17,-71.82,-14.9,0,0,0,0 +units=m +nadgrids=@ignorable,Etrs2Eov,null +no_defs'; + var def = + '+proj=somerc +lat_0=47.14439372222222 +lon_0=19.04857177777778 +k_0=0.99993 +x_0=650000 +y_0=200000 +ellps=GRS67 +towgs84=52.17,-71.82,-14.9,0,0,0,0 +units=m +nadgrids=Etrs2Eov +no_defs'; + +// Named Projection signature, later find it from anywhere via Projection.get('EPSG:23700') + eovProj = proj4.Projection.add('EPSG:23700', def); + wgsProj = proj4.Projection.WGS84; + //Loading, Success, Error handle with 1 line of code + nmeaDecoder + ..registerTalkerSentence("GGA", (line) => Gngga(raw: line)) + ..registerTalkerSentence("RMC", (line) => Gnrmc(raw: line)) + ..registerTalkerSentence("GST", (line) => Gngst(raw: line)); + + prefs = await SharedPreferences.getInstance(); + + authResponse = await Supabase.instance.client.auth + .signInWithPassword(email: 'test.elek.1@email.hu', password: 'demo'); + session = authResponse.session; + user = authResponse.user; + + Supabase.instance.client + .channel('public:TerepiSeged_Receiver') + .onPostgresChanges( + event: PostgresChangeEvent.update, + schema: 'public', + table: 'TerepiSeged_Receiver', + callback: (playload) { + var id = playload.newRecord['pointNumber'] as int; + print('Change received: ${id}'); + updatePointStatus(id); + }) + .subscribe(); + + mapController = MapController(); + + // riveGpsIconController = RiveUtils.getRiveController(Artboard(), + // stateMachineName: "gps_Interactivity"); + // gpsTrigger = riveGpsIconController.findSMI("active"); + + mapIsInitialized.value = true; + } + + @override + void onClose() async { + super.onClose(); + FlutterBluetoothSerial.instance.setPairingRequestHandler(null); + if (gpsIsConnected.value) { + connection.close(); + // connection = null; + print("BluetoothTestController dispose ...."); + } + pointDescriptionController.dispose(); + pointIdController.dispose(); + gpsHeightController.dispose(); + pointPrefixController.dispose(); + pointPostfixController.dispose(); + ntripUsernameController.dispose(); + ntripPasswordController.dispose(); + + await Supabase.instance.client + .channel('public:TerepiSeged_Receiver') + .unsubscribe(); + } + + @override + void onReady() async { + super.onReady(); + + _getInitialLocation(); + + // String data = await rootBundle.loadString('assets/Files/transzekt.geojson'); + // parser.parseGeoJsonAsString(data); + + if (await permission_handler.Permission.storage.isGranted) { + print("Storage permission is ok ..."); + } else { + var result = await permission_handler.Permission.storage.request(); + if (result == permission_handler.PermissionStatus.granted) { + print("Storage permission request is ok ...."); + } else { + print("No storage permission"); + } + } + if (await permission_handler.Permission.manageExternalStorage.isGranted) { + print("External storage permission is ok ..."); + } else { + var result = + await permission_handler.Permission.manageExternalStorage.request(); + if (result == permission_handler.PermissionStatus.granted) { + print("External storage permission request is ok ...."); + } else { + print("No external storage permission"); + } + if (prefs.containsKey('gpsAddress')) { + var address = prefs.getString('gpsAddress'); + if (address != null) { + gpsAddress.value = address; + } + } + if (prefs.containsKey('gpsName')) { + var name = prefs.getString('gpsName'); + if (name != null) { + gpsName.value = name; + } + } + if (prefs.containsKey('ntripUserName')) { + var userName = prefs.getString('ntripUserName'); + if (userName != null) { + ntripUserName.value = userName; + } + } + if (prefs.containsKey('ntripPassword')) { + var password = prefs.getString('ntripPassword'); + if (password != null) { + ntripPassword.value = password; + } + } + } + + directory = await getExternalStorageDirectory(); + print(directory!.path); + // String newPath = ''; + // List folders = directory!.path.split("/"); + // for (int i = 1; i < folders.length; i++) { + // String folder = folders[i]; + // if (folder != "Android") { + // newPath += "/" + folder; + // } else { + // break; + // } + // } + // newPath = newPath + "/TerepisSegedApp"; + // directory = Directory(newPath); + if (!await directory!.exists()) { + await directory!.create(recursive: true); + } + dataFile = File("${directory!.path}/data.txt"); + + if (await directory!.exists()) { + if (!await dataFile.exists()) { + dataFile.writeAsString( + "Id;DateTime;Description;EovX;EovY;Latitude;Longitude;Altitude;Hor.Err;Vert.Err\r\n"); + } + } + + gpsHeightController.text = '1.8'; + } + + void _getInitialLocation() async { + bool servicedEnabled; + PermissionStatus permissionGranted; + LocationData locationData; + Location location = Location(); + + servicedEnabled = await location.serviceEnabled(); + if (!servicedEnabled) { + servicedEnabled = await location.requestService(); + if (!servicedEnabled) { + return; + } + } + + permissionGranted = await location.hasPermission(); + if (permissionGranted == PermissionStatus.denied) { + permissionGranted = await location.requestPermission(); + if (permissionGranted != PermissionStatus.granted) { + return; + } + } + + locationData = await location.getLocation(); + currentLatitude.value = locationData.latitude ?? 0.0; + currentLongitude.value = locationData.longitude ?? 0.0; + print("Current location initialized -> $currentLatitude $currentLongitude"); + mapController.move(LatLng(currentLatitude.value, currentLongitude.value), + currentZoom.value); + _updateCurrentLocationMarker(); + } + + void connectToGps() { + if (gpsIsConnected == false) { + BluetoothConnection.toAddress(gpsAddress.value).then((value) { + connection = value; + gpsIsConnected.value = true; + print("GPS is connected ..."); + + connection.input!.listen(_onDataReceived); + }); + } + } + + void disconnectFromGps() { + if (gpsIsConnected.value) { + connection.close(); + gpsIsConnected.value = false; + print("GPS is disconnected ...."); + } + if (ntripIsConnected.value) { + disconnectFromNtripServer(); + } + } + + void connectToNtripServer() async { + // socket = await Socket.connect(InternetAddress('3.23.52.207'), 2101, + // timeout: const Duration(seconds: 5)); + socket = await Socket.connect(InternetAddress('84.206.45.44'), 2101, + timeout: const Duration(seconds: 5)); + socket.asBroadcastStream; + ntripIsConnected.value = true; + + socket.encoding = ascii; + print("Connected to ntrip server ...."); + + // String header = "GET /KOVARIK HTTP/1.1\r\n"; + String header = "GET /SGO_RTK3.2 HTTP/1.1\r\n"; + + header += "User-Agent: SharpGps iter.dk\r\n"; + header += "Accept: */*\r\nConnection: close\r\n"; + // header += "Authorization: Basic ${_toBase64("info@mail.app-dev.hu:")}\r\n"; + //header += "Authorization: Basic ${_toBase64("elgi08:Laszl0stef1")}\r\n"; + header += + "Authorization: Basic ${_toBase64("${ntripUserName.value}:${ntripPassword.value}")}\r\n"; + // header += "Host:rtk2go.com:2101\r\n"; + header += "Host:gnssnet.hu:2101\r\n"; + header += "Ntrip-Vesrsion:Ntrip/2.0\r\n"; + header += "\r\n"; + + // listen for responses from the server + socketStreamSubscription = socket.listen( + // handle data from the server + (Uint8List data) { + // "ICY 200 OK" - first response + final serverResponse = String.fromCharCodes(data); + ntripReceivedData.value = data.length; + ntripDataPacketNumbers.value++; + if (gpsIsConnected.value) { + if (data.length > 14) { + connection.output.add(data); + } + } + print('Server: $ntripReceivedData'); + }, + + // handle errors + onError: (error) { + print(error); + socket.destroy(); + }, + + // handle server ending connection + onDone: () async { + print('Server left.'); + socketStreamSubscription.cancel(); + await socket.flush(); + ntripIsConnected.value = false; + ntripReceivedData.value = 0; + socket.destroy(); + }, + ); + + socket.add(_convertStringToUint8List(header)); + + // sendGgaMessage(lastGgaMessage); + } + + void disconnectFromNtripServer() async { + socketStreamSubscription.cancel(); + await socket.flush(); + socket.close(); + socket.destroy(); + ntripReceivedData.value = 0; + ntripIsConnected.value = false; + print("Disconnect from ntrip server...."); + } + + void _onDataReceived(Uint8List data) { + String sentence = ""; + + print("Bluetooth received -> ${data.length} byte(s)"); + String dataString = String.fromCharCodes(data); + int index = data.indexOf(13); + + if (~index != 0) { + sentence = _messageBuffer + dataString.substring(0, index); + _messageBuffer = dataString.substring(index); + } else { + _messageBuffer = _messageBuffer + dataString; + } + + // print("Message ($count): $sentence"); + _processGnssMessage(sentence); + } + + String _toBase64(String str) { + final bytes = ascii.encode(str); + final base64Str = base64.encode(bytes); + + return base64Str; + } + + Uint8List _convertStringToUint8List(String str) { + final List codeUnits = str.codeUnits; + final Uint8List unit8List = Uint8List.fromList(codeUnits); + return unit8List; + } + + void _processGnssMessage(String message) { + LineSplitter lineSplitter = const LineSplitter(); + List lines = lineSplitter.convert(message); + + if (lines.isEmpty) { + return; + } + + for (String line in lines) { + if (line.trim().isEmpty) { + continue; + } + if (line.startsWith("\$GNGGA")) { + final sentence = nmeaDecoder.decode(line); + if (sentence!.valid && sentence is Gngga) { + hasGpsValidData.value = sentence.gpsQualityIndicator > 0; + if (hasGpsValidData.value) { + if (DateTime.now().difference(lastGpsRefreshTime).inSeconds >= 0) { + lastGpsRefreshTime = DateTime.now(); + utcOfPositionFix = sentence.utcOfPositionFix; + gpsLatitude.value = sentence.latitude; + gpsLatitudeDirection.value = sentence.latitudeDirection; + gpsLongitude.value = sentence.longitude; + gpsLongitudeDirection.value = sentence.longitudeDirection; + gpsAltitude.value = sentence.altitudeAboveMeanSeaLevel; + gpsGeoidSeparation.value = sentence.geoidSeparation; + gpsQuality.value = sentence.gpsQualityIndicator; + eov.value = ConvertCoordinate.ConvertWgsToEov( + gpsLatitude.value, gpsLongitude.value); + + latDegree.value = ConvertCoordinate.toDegree(gpsLatitude.value); + latMin.value = ConvertCoordinate.toMinute(gpsLatitude.value); + latSec.value = ConvertCoordinate.toSecond(gpsLatitude.value); + longDegree.value = ConvertCoordinate.toDegree(gpsLongitude.value); + longMin.value = ConvertCoordinate.toMinute(gpsLongitude.value); + longSec.value = ConvertCoordinate.toSecond(gpsLongitude.value); + currentLatitude.value = gpsLatitude.value; + currentLongitude.value = gpsLongitude.value; + _updateCurrentLocationMarker(); + lastGgaMessage = line; + if (ntripIsConnected.value && + (DateTime.now() + .difference(lastSendTimeGgaMessage) + .inSeconds >= + 5)) { + sendGgaMessage(lastGgaMessage); + print("Send GGA message: $lastGgaMessage"); + ggaSenDataPacketNumber.value++; + ggaSendLastTimeStr.value = utcOfPositionFix; + lastSendTimeGgaMessage = DateTime.now(); + } + } + } + } + } + if (line.startsWith("\$GNGST") && hasGpsValidData.value) { + final sentence = nmeaDecoder.decode(line); + if (sentence!.valid && sentence is Gngst) { + gpsLatitudeError.value = sentence.latitudeError; + gpsLongitudeError.value = sentence.longitudeError; + gpsAltitudeError.value = sentence.heightError; + } + } + if (line.startsWith("\$GNRMC") && hasGpsValidData.value) { + final sentence = nmeaDecoder.decode(line); + if (sentence!.valid && sentence is Gnrmc) { + utcDateOfPositionFix = sentence.date; + if (utcDateOfPositionFix.isNotEmpty && utcOfPositionFix.isNotEmpty) { + gpsDateTime.value = DateTime( + 2000 + + int.parse( + "${utcDateOfPositionFix[4]}${utcDateOfPositionFix[5]}"), + int.parse( + "${utcDateOfPositionFix[2]}${utcDateOfPositionFix[3]}"), + int.parse( + "${utcDateOfPositionFix[0]}${utcDateOfPositionFix[1]}"), + int.parse("${utcOfPositionFix[0]}${utcOfPositionFix[1]}"), + int.parse("${utcOfPositionFix[2]}${utcOfPositionFix[3]}"), + int.parse("${utcOfPositionFix[4]}${utcOfPositionFix[5]}")); + } + } + } + } + } + + String getGpsQualityIndicator({required int quality}) { + String qualityStr = "Invalid"; + switch (quality) { + case 0: + { + qualityStr = "Invalid"; + } + break; + case 1: + { + qualityStr = "Standard GPS (2D/3D)"; + } + break; + case 2: + { + qualityStr = "Differential GPS"; + } + break; + case 4: + { + qualityStr = "RTK Fix"; + } + break; + case 5: + { + qualityStr = "RTK Float"; + } + break; + case 6: + { + qualityStr = "Estimated (DR) Fix"; + } + break; + default: + { + qualityStr = "Invalid (-1)"; + } + } + return qualityStr; + } + + void mapZoomOut() { + double cLat, cLong; + if (currentZoom.value > 0) { + currentZoom.value = currentZoom.value - 1; + cLat = isMapMoveToCenter.value + ? currentLatitude.value + : mapController.camera.center.latitude; + cLong = isMapMoveToCenter.value + ? currentLongitude.value + : mapController.camera.center.longitude; + mapController.move(LatLng(cLat, cLong), currentZoom.value); + } + } + + void mapZoomIn() { + double cLat, cLong; + if (currentZoom.value < maxZoomValue) { + currentZoom.value++; + cLat = isMapMoveToCenter.value + ? currentLatitude.value + : mapController.camera.center.latitude; + cLong = isMapMoveToCenter.value + ? currentLongitude.value + : mapController.camera.center.longitude; + mapController.move(LatLng(cLat, cLong), currentZoom.value); + } + } + + void _updateCurrentLocationMarker() { + currentLocationMarker.clear(); + currentLocationMarker.add(Marker( + point: LatLng(currentLatitude.value, currentLongitude.value), + width: 15.0, + height: 15.0, + child: Container( + width: 15.0, + height: 15.0, + decoration: BoxDecoration( + color: getCurrentLocationMarkerColor(quality: gpsQuality.value), + shape: BoxShape.circle, + border: Border.all(width: 1.5, color: Colors.white)), + ))); + if (isMapMoveToCenter.value) { + mapController.move(LatLng(currentLatitude.value, currentLongitude.value), + currentZoom.value); + } + } + + Color getCurrentLocationMarkerColor({required int quality}) { + Color qualityStr = Colors.black; + switch (quality) { + case 0: + { + qualityStr = Colors.black; + } + break; + case 1: + { + qualityStr = Colors.red; + } + break; + case 2: + { + qualityStr = Colors.blue; + } + break; + case 4: + { + qualityStr = Colors.green; + } + break; + case 5: + { + qualityStr = Colors.orange; + } + break; + case 6: + { + qualityStr = Colors.yellow; + } + break; + default: + { + qualityStr = Colors.white; + } + } + return qualityStr; + } + + void onBottomNavigationBarTap(int index) async { + bool noMorePoint = false; + print("OnBottomNavTap -> $index"); + if (index == 0) { + pointIdController.text = pointId.toString(); + pointDescriptionController.text = ""; + Get.dialog( + AlertDialog( + title: const Text("Pont rögzítése"), + content: Column( + mainAxisSize: MainAxisSize.min, + children: [ + TextField( + controller: pointIdController, + autofocus: true, + keyboardType: TextInputType.number, + decoration: const InputDecoration( + border: OutlineInputBorder(), labelText: 'Azonosító'), + ), + const SizedBox( + height: 20.0, + ), + TextField( + controller: pointDescriptionController, + decoration: const InputDecoration( + border: OutlineInputBorder(), labelText: 'Leírás'), + ), + const SizedBox( + height: 20, + ), + TextField( + controller: gpsHeightController, + autofocus: true, + keyboardType: TextInputType.number, + decoration: const InputDecoration( + border: OutlineInputBorder(), labelText: 'GPS magasság'), + ), + ], + ), + actions: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + OutlinedButton( + style: OutlinedButton.styleFrom( + minimumSize: const Size(120.0, 40.0)), + child: const Text( + "Mégsem", + style: TextStyle(color: Colors.red), + ), + onPressed: () { + Get.back(); + }, + ), + OutlinedButton( + style: OutlinedButton.styleFrom( + minimumSize: const Size(120.0, 40.0)), + child: const Text( + "Ment", + style: TextStyle( + color: Colors.green, fontWeight: FontWeight.bold), + ), + onPressed: () async { + pointId = int.parse(pointIdController.text); + pointWithDescriptionList.add(PointWithDescription( + pointId, + gpsDateTime.value, + pointDescriptionController.text, + eov.value.Y, + eov.value.X, + gpsLatitude.value, + gpsLongitude.value, + max(gpsLatitudeError.value, gpsLongitudeError.value), + gpsAltitudeError.value)); + print( + "pointWithDescriptionList -> ${pointWithDescriptionList.length}"); + + pointNotesMarker.add(Marker( + point: LatLng(gpsLatitude.value, gpsLongitude.value), + width: 15.0, + height: 15.0, + child: Container( + width: 15.0, + height: 15.0, + decoration: BoxDecoration( + color: Colors.amber[700], + shape: BoxShape.circle, + border: + Border.all(width: 1.0, color: Colors.black)), + ))); + await dataFile.writeAsString( + "$pointId;$gpsDateTime;${pointDescriptionController.text};${formatEovForFile.format(eov.value.Y)};${formatEovForFile.format(eov.value.X)};$gpsLatitude;$gpsLongitude;$gpsAltitude;${max(gpsLatitudeError.value, gpsLongitudeError.value)};$gpsAltitudeError;${gpsHeightController.text}\r\n", + mode: FileMode.append); + + _measuredPoints.add({ + "id": pointId, + "dateAndTime": gpsDateTime.value, + "latitude": gpsLatitude.value, + "longitude": gpsLongitude.value, + "altitude": gpsAltitude.value, + "eovY": formatEovForFile.format(eov.value.Y), + "eovX": formatEovForFile.format(eov.value.X), + "description": pointDescriptionController.text, + "horizontalError": + max(gpsLatitudeError.value, gpsLongitudeError.value), + "verticalError": gpsAltitudeError.value, + "gpsHeight": gpsHeightController.text + }); + + await Supabase.instance.client + .from('TerepiSeged_MeasuredPoints') + .insert({ + 'pointNumber': pointId, + 'gnssNumber': gpsName.value, + 'latitude': gpsLatitude.value, + 'longitude': gpsLongitude.value, + 'altitude': gpsAltitude.value, + 'heightOfGeoid': gpsGeoidSeparation.value, + 'eovX': eov.value.X, + 'eovY': eov.value.Y, + 'poleHeight': double.tryParse(gpsHeightController.text), + 'horizontalError': + max(gpsLatitudeError.value, gpsLongitudeError.value), + 'verticalError': gpsAltitudeError.value, + 'description': pointDescriptionController.text + }); + + await Supabase.instance.client + .from('TerepiSeged_Receiver') + .update({'isMeasured': true}).eq( + 'pointNumber', pointId); + + pointId++; + + Get.back(); + }, + ), + ], + ) + ], + ), + barrierDismissible: false, + ); + } + } + + void sendGgaMessage(String ggaMessage) { + if (ntripIsConnected.value && ggaMessage.isNotEmpty) { + socket.add(_convertStringToUint8List("$ggaMessage\r\n")); + } + } + + void setIsMapMoveToCenter() { + isMapMoveToCenter.value = !isMapMoveToCenter.value; + // onBottomNavigationBarTap(0); + } + + void addMeasuredPoint() { + _measuredPoints.add({"id": 4001, "latitude": 46.3455, "longitude": 19.652}); + } + + void showAddPointDialog() { + onBottomNavigationBarTap(0); + } + + void saveGpsAddress(String address) { + prefs.setString('gpsAddress', address); + } + + void saveGpsName(String name) { + prefs.setString('gpsName', name); + } + + void saveNtripUserName(String username) { + prefs.setString('ntripUserName', username); + } + + void saveNtripPassword(String password) { + prefs.setString('ntripPassword', password); + } + + void updatePointStatus(int pointId) {} +} diff --git a/lib/pages/map_survey/presentations/views/map_add_point_dialog.dart b/lib/pages/map_survey/presentations/views/map_add_point_dialog.dart new file mode 100644 index 0000000..11cae13 --- /dev/null +++ b/lib/pages/map_survey/presentations/views/map_add_point_dialog.dart @@ -0,0 +1,97 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:terepi_seged/pages/map_survey/presentations/controllers/map_survey_controller.dart'; + +class MapAddPointDialog extends GetView { + const MapAddPointDialog({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Scaffold( + body: SafeArea( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + TextField( + controller: controller.pointIdController, + autofocus: true, + keyboardType: TextInputType.number, + decoration: const InputDecoration( + border: OutlineInputBorder(), labelText: 'Azonosító'), + ), + const SizedBox( + height: 20.0, + ), + TextField( + controller: controller.pointDescriptionController, + decoration: const InputDecoration( + border: OutlineInputBorder(), labelText: 'Leírás'), + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + OutlinedButton( + style: OutlinedButton.styleFrom( + minimumSize: const Size(120.0, 40.0)), + child: const Text( + "Mégsem", + style: TextStyle(color: Colors.red), + ), + onPressed: () { + Get.back(); + }, + ), + OutlinedButton( + style: OutlinedButton.styleFrom( + minimumSize: const Size(120.0, 40.0)), + child: const Text( + "Ment", + style: TextStyle( + color: Colors.green, fontWeight: FontWeight.bold), + ), + onPressed: () async { + // pointId = int.parse(pointIdController.text); + // pointWithDescriptionList.add(PointWithDescription( + // pointId, + // gpsDateTime.value, + // pointDescriptionController.text, + // eov.value.Y, + // eov.value.X, + // gpsLatitude.value, + // gpsLongitude.value, + // max(gpsLatitudeError.value, gpsLongitudeError.value), + // gpsAltitudeError.value)); + // print( + // "pointWithDescriptionList -> ${pointWithDescriptionList.length}"); + // pointNotesMarker.add(Marker( + // point: LatLng(gpsLatitude.value, gpsLongitude.value), + // width: 15.0, + // height: 15.0, + // builder: (ctx) => Container( + // width: 15.0, + // height: 15.0, + // decoration: BoxDecoration( + // color: Colors.purple, + // shape: BoxShape.circle, + // border: Border.all( + // width: 1.0, color: Colors.black)), + // ))); + // await dataFile.writeAsString( + // "$pointId;$gpsDateTime;${pointDescriptionController.text};${formatEovForFile.format(eov.value.Y)};${formatEovForFile.format(eov.value.X)};$gpsLatitude;$gpsLongitude;$gpsAltitude;${max(gpsLatitudeError.value, gpsLongitudeError.value)};$gpsAltitudeError\r\n", + // mode: FileMode.append); + + // pointId++; + + Get.back(); + }, + ), + ], + ) + ], + ), + )), + ); + } +} diff --git a/lib/pages/map_survey/presentations/views/mapsurvey_view.dart b/lib/pages/map_survey/presentations/views/mapsurvey_view.dart new file mode 100644 index 0000000..06ff303 --- /dev/null +++ b/lib/pages/map_survey/presentations/views/mapsurvey_view.dart @@ -0,0 +1,430 @@ +import 'dart:io'; +import 'dart:math'; + +import 'package:file_picker/file_picker.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_map_polywidget/flutter_map_polywidget.dart'; +import 'package:get/get.dart'; +import 'package:flutter_map/flutter_map.dart'; +import 'package:latlong2/latlong.dart'; +import 'package:rive/rive.dart'; +import 'package:terepi_seged/pages/map_survey/presentations/controllers/map_survey_controller.dart'; +import 'package:terepi_seged/pages/map_survey/presentations/views/settings_dialog.dart'; +import 'package:terepi_seged/utils/rive_utils.dart'; + +import 'map_add_point_dialog.dart'; + +class MapSurveyView extends GetView { + const MapSurveyView({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + late SMIBool gpsTrigger; + + return Scaffold( + resizeToAvoidBottomInset: false, + extendBody: true, + appBar: AppBar( + title: const Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text('Térkép'), + Text( + "", + style: TextStyle(fontSize: 12.0), + ) + ], + ), + actions: [ + Padding( + padding: const EdgeInsets.only(right: 20.0), + child: Obx( + () => GestureDetector( + onTap: () { + if (controller.gpsIsConnected.value) { + controller.disconnectFromGps(); + } else { + controller.connectToGps(); + } + }, + child: Icon(Icons.gps_fixed, + size: 26.0, + color: controller.gpsIsConnected.value + ? Colors.green + : Colors.red), + ), + ), + ), + Padding( + padding: const EdgeInsets.only(right: 20.0), + child: Obx( + () => GestureDetector( + onTap: () { + if (controller.ntripIsConnected.value) { + controller.disconnectFromNtripServer(); + } else { + controller.connectToNtripServer(); + } + }, + child: Icon( + Icons.assistant, + size: 26.0, + color: controller.ntripIsConnected.value + ? Colors.green + : Colors.red, + ), + ), + ), + ), + Padding( + padding: const EdgeInsets.only(right: 20.0), + child: GestureDetector( + onTap: () { + if (controller.ntripUserName.value.isNotEmpty) { + controller.ntripUsernameController.text = + controller.ntripUserName.value; + } + if (controller.ntripPassword.value.isNotEmpty) { + controller.ntripPasswordController.text = + controller.ntripPassword.value; + } + Get.to(() => SettingsDialog(), transition: Transition.downToUp); + }, + child: const Icon( + Icons.more_vert, + size: 26.0, + ), + ), + ) + ], + ), + body: Column( + children: [ + Obx( + () => controller.gpsIsConnected.value + ? Padding( + padding: const EdgeInsets.all(4.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + width: 170.0, + // height: 160.0, + decoration: BoxDecoration( + border: Border.all( + width: 2.0, + color: const Color.fromARGB( + 130, 255, 255, 255)), + color: + const Color.fromARGB(130, 255, 255, 255)), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "${controller.gpsDateTime} (UTC)", + style: const TextStyle(fontSize: 10.0), + ), + const Divider( + height: 5.0, + color: Colors.black, + ), + Text( + "EovX: ${controller.formatEov.format(controller.eov.value.Y)}"), + Text( + "EovY: ${controller.formatEov.format(controller.eov.value.X)}"), + Text("Alt: ${controller.gpsAltitude} (m)"), + const Divider( + height: 5.0, + color: Colors.black, + ), + Text( + "Hor. error: ${max(controller.gpsLatitudeError.value, controller.gpsLongitudeError.value)} (m)", + style: const TextStyle(fontSize: 14.0), + ), + Text( + "Vert. error: ${controller.gpsAltitudeError} (m)", + style: const TextStyle(fontSize: 14.0), + ), + const Divider( + height: 5.0, + color: Colors.black, + ), + Text( + "GPS quality -> ${controller.getGpsQualityIndicator(quality: controller.gpsQuality.value)} ", + style: const TextStyle(fontSize: 8.0), + ), + controller.ntripIsConnected.value + ? Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + const Divider( + height: 5.0, + color: Colors.black, + ), + Text( + "Ntrip ${controller.ntripReceivedData} byte(s) (${controller.ntripDataPacketNumbers})", + style: + const TextStyle(fontSize: 10.0), + ), + Text( + "GGA last send: ${controller.ggaSendLastTimeStr} (${controller.ggaSenDataPacketNumber})", + style: + const TextStyle(fontSize: 10.0), + ), + ], + ) + : const SizedBox( + width: 0.0, + height: 0.0, + ) + ], + )), + ], + ), + ) + : const SizedBox(), + ), + Expanded( + child: Stack( + children: [ + Obx( + () => controller.mapIsInitialized.value + ? FlutterMap( + mapController: controller.mapController, + options: MapOptions( + initialCenter: LatLng( + controller.currentLatitude.value, + controller.currentLongitude.value), + maxZoom: 25, + initialZoom: controller.currentZoom.value, + ), + children: [ + TileLayer( + urlTemplate: + 'http://{s}.google.com/vt/lyrs=s,h&x={x}&y={y}&z={z}', + subdomains: const ['mt0', 'mt1', 'mt2', 'mt3'], + maxNativeZoom: 18, + // urlTemplate: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png', + // userAgentPackageName: 'hu.app_dev.terepi_seged', + ), + MarkerLayer( + markers: controller.pointNotesMarker, + ), + MarkerLayer( + markers: controller.currentLocationMarker), + MarkerLayer(markers: controller.parser.markers), + MarkerLayer( + markers: controller.pointsToMeasureMarker), + // PolylineLayer( + // polylines: controller.parser.polylines), + PolyWidgetLayer( + polyWidgets: controller.pointsToMeasureLabel) + ], + ) + : const Center(child: CircularProgressIndicator()), + ), + // Obx( + // () => controller.gpsIsConnected.value + // ? Positioned( + // left: 4.0, + // top: 4.0, + // child: Container( + // width: 170.0, + // // height: 160.0, + // decoration: BoxDecoration( + // border: Border.all( + // width: 2.0, + // color: const Color.fromARGB( + // 130, 255, 255, 255)), + // color: + // const Color.fromARGB(130, 255, 255, 255)), + // child: Column( + // mainAxisAlignment: MainAxisAlignment.start, + // crossAxisAlignment: CrossAxisAlignment.start, + // children: [ + // Text( + // "${controller.gpsDateTime} (UTC)", + // style: const TextStyle(fontSize: 10.0), + // ), + // const Divider( + // height: 5.0, + // color: Colors.black, + // ), + // Text( + // "EovX: ${controller.formatEov.format(controller.eov.value.Y)}"), + // Text( + // "EovY: ${controller.formatEov.format(controller.eov.value.X)}"), + // Text("Alt: ${controller.gpsAltitude} (m)"), + // const Divider( + // height: 5.0, + // color: Colors.black, + // ), + // Text( + // "Hor. error: ${max(controller.gpsLatitudeError.value, controller.gpsLongitudeError.value)} (m)", + // style: const TextStyle(fontSize: 14.0), + // ), + // Text( + // "Vert. error: ${controller.gpsAltitudeError} (m)", + // style: const TextStyle(fontSize: 14.0), + // ), + // const Divider( + // height: 5.0, + // color: Colors.black, + // ), + // Text( + // "GPS quality -> ${controller.getGpsQualityIndicator(quality: controller.gpsQuality.value)} ", + // style: const TextStyle(fontSize: 8.0), + // ), + // controller.ntripIsConnected.value + // ? Column( + // crossAxisAlignment: + // CrossAxisAlignment.start, + // children: [ + // const Divider( + // height: 5.0, + // color: Colors.black, + // ), + // Text( + // "Ntrip ${controller.ntripReceivedData} byte(s) (${controller.ntripDataPacketNumbers})", + // style: const TextStyle( + // fontSize: 10.0), + // ), + // Text( + // "GGA last send: ${controller.ggaSendLastTimeStr} (${controller.ggaSenDataPacketNumber})", + // style: const TextStyle( + // fontSize: 10.0), + // ), + // ], + // ) + // : const SizedBox( + // width: 0.0, + // height: 0.0, + // ) + // ], + // )), + // ) + // : const Positioned( + // child: SizedBox( + // width: 0.0, + // height: 0.0, + // )), + // ) + ], + ), + ), + ], + ), + // bottomNavigationBar: Container( + // padding: const EdgeInsets.all(12), + // margin: const EdgeInsets.symmetric(horizontal: 24), + // decoration: BoxDecoration( + // color: Colors.black.withOpacity(0.5), + // borderRadius: const BorderRadius.all(Radius.circular(24))), + // child: Row( + // children: [ + // GestureDetector( + // onTap: () { + // gpsTrigger.change(true); + // Future.delayed(const Duration(seconds: 1), () { + // gpsTrigger.change(false); + // }); + // // controller.onBottomNavigationBarTap(0); + // Get.to(() => const MapAddPointDialog(), + // fullscreenDialog: true, + // transition: Transition.downToUp, + // duration: const Duration(milliseconds: 600)); + // }, + // child: SizedBox( + // height: 36, + // width: 36, + // child: RiveAnimation.asset( + // "assets/RiveAssets/travel_icons_pack.riv", + // artboard: "GPS", onInit: (artboard) { + // StateMachineController controllerRive = + // RiveUtils.getRiveController(artboard, + // stateMachineName: "gps_interactivity"); + // gpsTrigger = controllerRive.findSMI("active") as SMIBool; + // }), + // ), + // ) + // ], + // ), + // ), + floatingActionButtonLocation: FloatingActionButtonLocation.startFloat, + floatingActionButton: Wrap( + direction: Axis.horizontal, + children: [ + FloatingActionButton( + onPressed: () { + controller.mapZoomOut(); + }, + heroTag: 'ZoomOut', + tooltip: 'Zoom out', + child: const Icon(Icons.remove_circle_outline_rounded), + ), + const SizedBox( + width: 15, + ), + FloatingActionButton( + onPressed: () { + controller.mapZoomIn(); + }, + heroTag: 'ZoomIn', + tooltip: 'Zoom in', + child: const Icon(Icons.add_circle_outline_rounded), + ), + const SizedBox(width: 15.0), + FloatingActionButton( + onPressed: () { + // controller.isMapMoveToCenter(); + controller.setIsMapMoveToCenter(); + }, + heroTag: 'Center map', + tooltip: 'Center map', + child: Obx( + () => Icon(Icons.center_focus_strong, + color: controller.isMapMoveToCenter.value + ? Colors.green + : Colors.red), + ), + ), + const SizedBox( + width: 15.0, + ), + FloatingActionButton( + onPressed: () { + // controller.addMeasuredPoint(); + // controller.onBottomNavigationBarTap(0); + controller.showAddPointDialog(); + }, + heroTag: 'Pont bemérése', + tooltip: 'Pont bemérése', + child: const Icon(Icons.flag_sharp), + ), + const SizedBox( + width: 15.0, + ), + FloatingActionButton( + onPressed: () { + // controller.isMapMoveToCenter(); + // controller.addMeasuredPoint(); + ScaffoldMessenger.of(context).showSnackBar(const SnackBar( + content: Text( + "Fejlesztlés alatt", + style: TextStyle(fontWeight: FontWeight.bold), + ), + backgroundColor: Colors.black54, + )); + }, + heroTag: 'Database test', + tooltip: 'Pont bemérése', + child: const Icon(Icons.dataset), + ), + ], + ), + ); + } +} diff --git a/lib/pages/map_survey/presentations/views/settings_dialog.dart b/lib/pages/map_survey/presentations/views/settings_dialog.dart new file mode 100644 index 0000000..c461eb3 --- /dev/null +++ b/lib/pages/map_survey/presentations/views/settings_dialog.dart @@ -0,0 +1,362 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:terepi_seged/pages/map_survey/presentations/controllers/map_survey_controller.dart'; + +class SettingsDialog extends StatelessWidget { + final controller = Get.find(); + SettingsDialog({super.key}); + + Widget build(BuildContext context) { + return Scaffold( + body: ListView( + children: [ + Padding( + padding: const EdgeInsets.all(8.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + IconButton( + onPressed: () { + if (controller.ntripUsernameController.text.isNotEmpty) { + controller.ntripUserName.value = + controller.ntripUsernameController.text; + controller.saveNtripUserName( + controller.ntripUsernameController.text); + if (controller + .ntripPasswordController.text.isNotEmpty) { + controller.ntripPassword.value = + controller.ntripPasswordController.text; + controller.saveNtripPassword( + controller.ntripPasswordController.text); + } + } + Get.back(); + }, + icon: const Icon(Icons.close)), + TextButton( + style: ButtonStyle( + overlayColor: + MaterialStateProperty.all(Colors.transparent)), + onPressed: () { + if (controller.ntripUsernameController.text.isNotEmpty) { + controller.ntripUserName.value = + controller.ntripUsernameController.text; + controller.saveNtripUserName( + controller.ntripUsernameController.text); + if (controller + .ntripPasswordController.text.isNotEmpty) { + controller.ntripPassword.value = + controller.ntripPasswordController.text; + controller.saveNtripPassword( + controller.ntripPasswordController.text); + } + } + Get.back(); + }, + child: const Text( + 'Bezár', + style: TextStyle(color: Colors.blue, fontSize: 14.0), + )) + ], + ), + ), + const Padding( + padding: EdgeInsets.symmetric(horizontal: 40.0), + child: Text( + 'Beállítások', + style: TextStyle(fontSize: 20.0, fontWeight: FontWeight.bold), + ), + ), + const Padding( + padding: EdgeInsets.symmetric(horizontal: 40.0), + child: Text( + 'GPS vevő', + style: TextStyle(fontSize: 14.0, fontWeight: FontWeight.w500), + ), + ), + Obx(() => Column(children: [ + RadioListTile( + title: Text('TiGNSS Rover-BE6A'), + value: '10:06:1C:97:BE:6A', + groupValue: controller.gpsAddress.value, + onChanged: (value) { + controller.gpsAddress.value = value!; + controller.gpsName.value = 'TiGNSS Rover-BE6A'; + controller.saveGpsAddress(value); + controller.saveGpsName('TiGNSS Rover-BE6A'); + }), + RadioListTile( + title: Text('TiGNSS Rover-1DC6'), + value: 'E8:31:CD:16:1D:C6', + groupValue: controller.gpsAddress.value, + onChanged: (value) { + controller.gpsAddress.value = value!; + controller.gpsName.value = 'TiGNSS Rover-1DC6'; + controller.saveGpsAddress(value); + controller.saveGpsName('TiGNSS Rover-1DC6'); + }), + RadioListTile( + title: Text('TiGNSS Rover-9C3A'), + value: '08:3A:8D:14:9C:3A', + groupValue: controller.gpsAddress.value, + onChanged: (value) { + controller.gpsAddress.value = value!; + controller.gpsName.value = 'TiGNSS Rover-9C3A'; + controller.saveGpsAddress(value); + controller.saveGpsName('TiGNSS Rover-9C3A'); + }), + RadioListTile( + title: Text('TiGNSS Rover-72C2'), + value: '10:06:1C:97:72:C2', + groupValue: controller.gpsAddress.value, + onChanged: (value) { + controller.gpsAddress.value = value!; + controller.gpsName.value = 'TiGNSS Rover-72C2'; + controller.saveGpsAddress(value); + controller.saveGpsName('TiGNSS Rover-72C2'); + }), + RadioListTile( + title: Text('TiGNSS Rover-FE16'), + value: '10:06:1C:9F:FE:16', + groupValue: controller.gpsAddress.value, + onChanged: (value) { + controller.gpsAddress.value = value!; + controller.gpsName.value = 'TiGNSS Rover-FE16'; + controller.saveGpsAddress(value); + controller.saveGpsName('TiGNSS Rover-FE16'); + }), + RadioListTile( + title: Text('TiGNSS Rover-3B0A'), + value: '10:C6:1C:9E:3B:0A', + groupValue: controller.gpsAddress.value, + onChanged: (value) { + controller.gpsAddress.value = value!; + controller.gpsName.value = 'TiGNSS Rover-3B0A'; + controller.saveGpsAddress(value); + controller.saveGpsName('TiGNSS Rover-3B0A'); + }), + RadioListTile( + title: Text('TiGNSS Rover-7FEA'), + value: '10:06:1C:9C:7F:EA', + groupValue: controller.gpsAddress.value, + onChanged: (value) { + controller.gpsAddress.value = value!; + controller.gpsName.value = 'TiGNSS Rover-7FEA'; + controller.saveGpsAddress(value); + controller.saveGpsName('TiGNSS Rover-7FEA'); + }), + RadioListTile( + title: Text('TiGNSS Rover-A39E'), + value: '10:06:1C:97:A3:9E', + groupValue: controller.gpsAddress.value, + onChanged: (value) { + controller.gpsAddress.value = value!; + controller.gpsName.value = 'TiGNSS Rover-A39E'; + controller.saveGpsAddress(value); + controller.saveGpsName('TiGNSS Rover-A39E'); + }), + RadioListTile( + title: Text('TiGNSS Rover-FF4E'), + value: '98:CD:AC:62:FF:4E', + groupValue: controller.gpsAddress.value, + onChanged: (value) { + controller.gpsAddress.value = value!; + controller.gpsName.value = 'TiGNSS Rover-FF4E'; + controller.saveGpsAddress(value); + controller.saveGpsName('TiGNSS Rover-FF4E'); + }), + RadioListTile( + title: Text('TiGNSS Rover-8BB2'), + value: 'E8:31:CD:14:8B:B2', + groupValue: controller.gpsAddress.value, + onChanged: (value) { + controller.gpsAddress.value = value!; + controller.gpsName.value = 'TiGNSS Rover-8BB2'; + controller.saveGpsAddress(value); + controller.saveGpsName('TiGNSS Rover-8BB2'); + }), + RadioListTile( + title: Text('TiGNSS Rover-FF36'), + value: '98:CD:AC:62:FF:36', + groupValue: controller.gpsAddress.value, + onChanged: (value) { + controller.gpsAddress.value = value!; + controller.gpsName.value = 'TiGNSS Rover-FF36'; + controller.saveGpsAddress(value); + controller.saveGpsName('TiGNSS Rover-FF36'); + }) + ])), + const Padding( + padding: EdgeInsets.symmetric(horizontal: 20), + child: Divider( + height: 5, + ), + ), + // const SizedBox(height: 5), + // const Padding( + // padding: EdgeInsets.symmetric(horizontal: 40.0), + // child: Text( + // 'Bemért pont azonosítója:', + // style: TextStyle(fontSize: 14.0, fontWeight: FontWeight.w500), + // ), + // ), + // const SizedBox(height: 4), + // Padding( + // padding: const EdgeInsets.symmetric(horizontal: 40), + // child: Row( + // children: [ + // Flexible( + // child: TextField( + // controller: controller.pointPrefixController, + // decoration: const InputDecoration( + // border: OutlineInputBorder(), labelText: 'Előtag'), + // ), + // ), + // const Padding( + // padding: EdgeInsets.symmetric(horizontal: 10.0), + // child: Text( + // 'Eredeti azonosító', + // style: TextStyle(fontSize: 12.0), + // ), + // ), + // Flexible( + // child: TextField( + // controller: controller.pointPostfixController, + // decoration: const InputDecoration( + // border: OutlineInputBorder(), labelText: 'Utótag'), + // ), + // ), + // ], + // ), + // ), + const SizedBox(height: 5), + const Padding( + padding: EdgeInsets.symmetric(horizontal: 20.0), + child: Text( + 'Mérés iránya:', + style: TextStyle(fontSize: 14.0, fontWeight: FontWeight.w500), + ), + ), + Obx( + () => Column(children: [ + RadioListTile( + title: Text('Növekvő'), + value: true, + groupValue: controller.pointMeasuringDirectionForward.value, + onChanged: (value) { + controller.pointMeasuringDirectionForward.value = value!; + }), + RadioListTile( + title: Text('Csökkenő'), + value: false, + groupValue: controller.pointMeasuringDirectionForward.value, + onChanged: (value) { + controller.pointMeasuringDirectionForward.value = value!; + }) + ]), + ), + const Padding( + padding: EdgeInsets.symmetric(horizontal: 20), + child: Divider( + height: 5, + ), + ), + const SizedBox(height: 5), + const Padding( + padding: EdgeInsets.symmetric(horizontal: 20.0), + child: Text( + 'Kitűzött pont azonostója:', + style: TextStyle(fontSize: 14.0, fontWeight: FontWeight.w500), + ), + ), + const SizedBox(height: 4), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 20), + child: SizedBox( + height: 32, + width: double.infinity, + child: Row( + children: [ + Flexible( + child: TextField( + controller: controller.pointPrefixController, + decoration: const InputDecoration( + border: OutlineInputBorder(), labelText: 'Előtag'), + ), + ), + const Padding( + padding: EdgeInsets.symmetric(horizontal: 10.0), + child: Text( + 'Eredeti azonosító', + style: TextStyle(fontSize: 12.0), + ), + ), + Flexible( + child: TextField( + controller: controller.pointPostfixController, + decoration: const InputDecoration( + border: OutlineInputBorder(), labelText: 'Utótag'), + ), + ), + ], + ), + ), + ), + const Padding( + padding: EdgeInsets.only(left: 20, top: 8), + child: Text( + 'Például: előtag: 6, utótag: -bp, eredeti azonositó: 1002 -> 61002-bp', + style: TextStyle(fontSize: 10, fontWeight: FontWeight.w400))), + const SizedBox(height: 15), + const Padding( + padding: EdgeInsets.symmetric(horizontal: 20), + child: Divider( + height: 5, + ), + ), + const SizedBox(height: 5), + const Padding( + padding: EdgeInsets.symmetric(horizontal: 20.0), + child: Text( + 'Ntrip szolgáltatás:', + style: TextStyle(fontSize: 14.0, fontWeight: FontWeight.w500), + ), + ), + const SizedBox(height: 5), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 20.0), + child: Column(children: [ + SizedBox( + height: 40, + child: TextField( + controller: controller.ntripUsernameController, + decoration: const InputDecoration( + border: OutlineInputBorder(), + labelText: 'Felhasználónév', + icon: Icon(Icons.account_circle_rounded)), + ), + ), + const SizedBox(height: 10), + SizedBox( + height: 40, + child: TextField( + obscureText: true, + enableSuggestions: false, + autocorrect: false, + controller: controller.ntripPasswordController, + decoration: const InputDecoration( + border: OutlineInputBorder(), + labelText: 'Jelszó', + icon: Icon( + Icons.lock, + )), + ), + ), + const SizedBox(height: 20) + ]), + ), + ], + ), + ); + } +} diff --git a/lib/pages/navigation/presentation/controllers/navigation_controller.dart b/lib/pages/navigation/presentation/controllers/navigation_controller.dart index b5a5e9b..7e90165 100644 --- a/lib/pages/navigation/presentation/controllers/navigation_controller.dart +++ b/lib/pages/navigation/presentation/controllers/navigation_controller.dart @@ -124,7 +124,7 @@ class NavigationViewController extends GetxController { RxInt vehicleNumber = 5.obs; late Location internalGpsLogger; Location internalGpsLocation = Location(); - late StreamSubscription internalGpsLocationSubscription; + late StreamSubscription? internalGpsLocationSubscription; late List> pathLayer = []; @@ -193,7 +193,7 @@ class NavigationViewController extends GetxController { // internalGpsLogTimer.cancel(); // } - internalGpsLocationSubscription.cancel(); + internalGpsLocationSubscription!.cancel(); } @override diff --git a/lib/routes/app_pages.dart b/lib/routes/app_pages.dart index f676cb2..8951a83 100644 --- a/lib/routes/app_pages.dart +++ b/lib/routes/app_pages.dart @@ -6,6 +6,8 @@ import 'package:terepi_seged/pages/home/presentation/views/home_view.dart'; import 'package:terepi_seged/pages/map/bindings/map_bindings.dart'; import 'package:terepi_seged/pages/map/presentation/views/map_add_point_dialog.dart'; import 'package:terepi_seged/pages/map/presentation/views/map_view.dart'; +import 'package:terepi_seged/pages/map_survey/bindings/map_survey_bindings.dart'; +import 'package:terepi_seged/pages/map_survey/presentations/views/mapsurvey_view.dart'; import 'package:terepi_seged/pages/measured_data/bindings/measured_data_bindings.dart'; import 'package:terepi_seged/pages/measured_data/presentation/views/measured_data_view.dart'; import 'package:terepi_seged/pages/navigation/bindings/navigation_bindings.dart'; @@ -73,6 +75,10 @@ class AppPages { GetPage( name: Routes.MEASUREDDATA, binding: MeasuredDataBinding(), - page: () => const MeasuredDataView()) + page: () => const MeasuredDataView()), + GetPage( + name: Routes.MAPSURVEY, + binding: MapSurveyBinding(), + page: () => const MapSurveyView()) ]; } diff --git a/lib/routes/app_routes.dart b/lib/routes/app_routes.dart index 71e17e0..32b0f0e 100644 --- a/lib/routes/app_routes.dart +++ b/lib/routes/app_routes.dart @@ -14,6 +14,7 @@ abstract class Routes { static const MAPTEST = '/map_test'; static const PROPERTYLIST = '/property_list'; static const MEASUREDDATA = '/measured_data'; + static const MAPSURVEY = '/map_survey'; static const MAPADDPOINTDIALOG = "/map_add_point_dialog"; }