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:get/get_connect/http/src/utils/utils.dart'; import 'package:intl/date_time_patterns.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 NavigationViewController 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; 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 = 18.0.obs; late final MapController mapController; final currentLocationMarker = []; final pointNotesMarker = []; List pointsToMeasure = []; final pointsToMeasureMarker = []; final pointsToMeasureLabel = []; final pointsToMeasureDropDownMenuItem = >[]; RxInt pointsToMeasureSelectedValue = (-1).obs; RxDouble distance = 0.0.obs; TextEditingController pointIdController = TextEditingController(); TextEditingController pointDescriptionController = TextEditingController(); TextEditingController gpsHeightController = TextEditingController(); TextEditingController ntripUsernameController = TextEditingController(); TextEditingController ntripPasswordController = TextEditingController(); TextEditingController vehicleNumberController = TextEditingController(); int pointId = 1; Rx pointMeasuringDirectionForward = true.obs; List pointWithDescriptionList = []; late Directory? directory; late File dataFile; late File gpsFile; late File internalGpsFile; late Timer internalGpsLogTimer; late proj4.Projection eovProj, wgsProj; RxBool mapIsInitialized = false.obs; GeoJsonParser parser = GeoJsonParser(defaultMarkerColor: Colors.yellow); final CollectionReference _vibratorTracker = FirebaseFirestore.instance.collection('vibratorTracker'); DateTime lastGpsDataSaveTime = DateTime(2000, 1, 1, 0, 0, 0); RxInt vehicleNumber = 5.obs; late Location internalGpsLogger; Location internalGpsLocation = Location(); late StreamSubscription internalGpsLocationSubscription; late List> pathLayer = []; RxString ntripUserName = "".obs; RxString ntripPassword = "".obs; late SharedPreferences prefs; late AuthResponse authResponse; late Session? session; late User? user; // late SMIBool gpsTrigger; // late StateMachineController riveGpsIconController; @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'; // 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)); mapController = MapController(); 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; // riveGpsIconController = RiveUtils.getRiveController(Artboard(), // stateMachineName: "gps_Interactivity"); // gpsTrigger = riveGpsIconController.findSMI("active"); mapIsInitialized.value = true; } @override void onClose() { super.onClose(); FlutterBluetoothSerial.instance.setPairingRequestHandler(null); if (gpsIsConnected.value) { connection.close(); // connection = null; print("BluetoothTestController dispose ...."); } pointDescriptionController.dispose(); pointIdController.dispose(); gpsHeightController.dispose(); ntripUsernameController.dispose(); ntripPasswordController.dispose(); vehicleNumberController.dispose(); // if (internalGpsLogTimer.isActive) { // internalGpsLogTimer.cancel(); // } internalGpsLocationSubscription.cancel(); } @override void onReady() async { super.onReady(); _getInitialLocation(); String data = await rootBundle.loadString('assets/Files/kozmuvek.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; } } if (prefs.containsKey('vehicleNumber')) { var vehicleNum = prefs.getInt('vehicleNumber'); if (vehicleNum != null) { vehicleNumber.value = vehicleNum; } } vehicleNumberController.text = vehicleNumber.toString(); } 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"); gpsFile = File("${directory!.path}/GpsData.txt"); internalGpsFile = File("${directory!.path}/internalGpsData.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"); } } if (await directory!.exists()) { if (!await internalGpsFile.exists()) { internalGpsFile.writeAsString( "Vehicle;DateTime;Latitude;Longitude;Altitude;Accuracy\r\n"); } } if (await directory!.exists()) { if (!await gpsFile.exists()) { gpsFile.writeAsString( "Vehicle;DateTime;Latitude;Longitude;Altitude;Accuracy\r\n"); } } gpsHeightController.text = '1.7'; internalGpsLogger = Location(); await internalGpsLocation.changeSettings(interval: 10000); internalGpsLocationSubscription = internalGpsLogger.onLocationChanged.listen((LocationData value) { double? longitude; double? latitude; double? accuracy; double? altitude; DateTime time; double? speed; latitude = value.latitude ?? 0.0; longitude = value.longitude ?? 0.0; accuracy = value.accuracy ?? 0.0; altitude = value.altitude ?? 0.0; double? timestamp = value.time ?? 0.0; time = DateTime.fromMillisecondsSinceEpoch(timestamp.toInt()); speed = value.speed ?? 0.0; print("internalGpsLogTimer -> getLocation $time"); internalGpsFile.writeAsString( "$vehicleNumber;$time;$latitude;$longitude;$altitude;$accuracy\r\n"); // _vibratorTracker.add({ // "gpsType": 0, // "vibratorNumber": vehicleNumber.value, // "gpsDateTime": time, // "latitude": latitude, // "longitude": longitude, // "altitude": altitude, // "horizontalError": accuracy, // "speed": speed, // "createdAt": DateTime.timestamp() // }); Supabase.instance.client.from('TerepiSeged_VibratorTracker').insert({ 'gpsType': 0, 'vibratorNumber': vehicleNumber.value, 'gpsDateTime': time.toIso8601String(), 'latitude': gpsLatitude.value, 'longitude': gpsLongitude.value, 'altitude': gpsAltitude.value, 'horizontalError': accuracy, 'speed': speed }); }); // internalGpsLogTimer = // Timer.periodic(const Duration(seconds: 10), (timer) async { // double? longitude; // double? latitude; // double? accuracy; // double? altitude; // DateTime time; // double? speed; // print("internalGpsLogTimer -> out"); // LocationData value = await internalGpsLocation.getLocation(); // latitude = value.latitude ?? 0.0; // longitude = value.longitude ?? 0.0; // accuracy = value.accuracy ?? 0.0; // altitude = value.altitude ?? 0.0; // double? timestamp = value.time ?? 0.0; // time = DateTime.fromMillisecondsSinceEpoch(timestamp.toInt()); // speed = value.speed ?? 0.0; // print("internalGpsLogTimer -> getLocation $time"); // internalGpsFile.writeAsString( // "$vehicleNumber;$time;$latitude;$longitude;$altitude;$accuracy\r\n"); // _vibratorTracker.add({ // "gpsType": 0, // "vibratorNumber": vehicleNumber, // "gpsDateTime": time, // "latitude": latitude, // "longitude": longitude, // "altitude": altitude, // "horizontalError": accuracy, // "speed": speed, // "createdAt": DateTime.timestamp() // }); // }); } 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.value == 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 += "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; gpsQuality.value = sentence.gpsQualityIndicator; eov.value = ConvertCoordinate.ConvertWgsToEov( gpsLatitude.value, gpsLongitude.value); if (pointsToMeasureSelectedValue.value >= 0) { double coordX = pointsToMeasure[pointsToMeasureSelectedValue.value].coordX; double coordY = pointsToMeasure[pointsToMeasureSelectedValue.value].coordY; var eovCoord = proj4.Point(x: coordX, y: coordY); var wgsCoord = eovProj.transform(wgsProj, eovCoord); distance.value = calculateDistance( LatLng(gpsLatitude.value, gpsLongitude.value), LatLng(wgsCoord.y, wgsCoord.x)); } 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 >= 30)) { 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]}")); } } } } if (DateTime.now().difference(lastGpsDataSaveTime).inSeconds >= 10 && gpsQuality.value > 0) { _savePositionToDatabase(); } } void _savePositionToDatabase() { _vibratorTracker.add({ "gpsType": 1, "vibratorNumber": vehicleNumber.value, "gpsQuality": gpsQuality.value, "gpsDateTime": gpsDateTime.value, "latitude": gpsLatitude.value, "longitude": gpsLongitude.value, "altitude": gpsAltitude.value, "eovY": eov.value.Y, "eovX": eov.value.X, "horizontalError": max(gpsLatitudeError.value, gpsLongitudeError.value), "verticalError": gpsAltitudeError.value, "antennaHeight": double.parse(gpsHeightController.text), "createdAt": DateTime.timestamp() }); final res = Supabase.instance.client.from('TerepiSeged_VibratorTracker').insert({ "gpsType": 1, "vibratorNumber": vehicleNumber.value, "gpsQuality": gpsQuality.value, "gpsDateTime": gpsDateTime.value.toIso8601String(), "latitude": gpsLatitude.value, "longitude": gpsLongitude.value, "altitude": gpsAltitude.value, "eovY": eov.value.Y, "eovX": eov.value.X, "horizontalError": max(gpsLatitudeError.value, gpsLongitudeError.value), "verticalError": gpsAltitudeError.value, "poleHeight": double.parse(gpsHeightController.text) }).select(); print(res); lastGpsDataSaveTime = DateTime.now(); } 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 { print("OnBottomNavTap -> $index"); if (index == 0) { pointIdController.text = '${pointsToMeasure[pointsToMeasureSelectedValue.value].id}'; 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.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;${gpsHeightController.text}\r\n", mode: FileMode.append); pointId--; pointsToMeasureSelectedValue.value -= 1; 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; isMapMoveToCenter.value = !isMapMoveToCenter.value; } void ReadPointsFromFile() async { File? file; FilePickerResult? result = await FilePicker.platform.pickFiles(); if (result != null) { file = File(result.files.single.path!); } else { print("No file selected"); } if (await file!.exists()) { pointsToMeasure.clear(); final content = await file.readAsLines(); print('Length: -> ${content.length}'); for (final (index, item) in content.indexed) { if (index == 0) { continue; } var items = item.split(";"); if (items.length >= 3) { var id = int.tryParse(items[0]); var coordX = double.tryParse(items[1].replaceAll(',', '.')); var coordY = double.tryParse(items[2].replaceAll(',', '.')); if (id != null && coordX != null && coordY != null) { pointsToMeasure .add(PointToMeasure(id: id, coordX: coordX, coordY: coordY)); var eovCoord = proj4.Point(x: coordX, y: coordY); var wgsCoord = eovProj.transform(wgsProj, eovCoord); print("Lat -> ${wgsCoord.x}, Long -> ${wgsCoord.y}"); pointsToMeasureMarker.add(Marker( point: LatLng(wgsCoord.y, wgsCoord.x), width: 15.0, height: 15.0, child: Container( width: 15.0, height: 15.0, decoration: BoxDecoration( color: Colors.yellow, shape: BoxShape.circle, border: Border.all(width: 1.0, color: Colors.black)), ))); pointsToMeasureLabel.add(PolyWidget( center: LatLng(wgsCoord.y + 0.0000275, wgsCoord.x + 0.0000275), widthInMeters: 28, heightInMeters: 28, // constraints: const BoxConstraints( // minWidth: 250, // maxWidth: 350, // ), child: FittedBox( child: Padding( padding: const EdgeInsets.all(4.0), child: Text( ' $id ', style: const TextStyle( fontWeight: FontWeight.bold, color: Colors.yellow, fontSize: 12.0), ), ), ))); pointsToMeasureDropDownMenuItem.add(DropdownMenuItem( value: index - 1, child: Text('$id'), )); } } } pointsToMeasureSelectedValue.value = 0; print('Converted points number -> ${pointsToMeasure.length}'); } } void ReadPathFromFile() async { File? file; FilePickerResult? result = await FilePicker.platform.pickFiles(); if (result != null) { file = File(result.files.single.path!); } else { print("No file selected"); } if (await file!.exists()) { String data = await file.readAsString(); parser.defaultPolylineColor = Colors.orangeAccent; parser.defaultPolylineStroke = 5.0; parser.parseGeoJsonAsString(data); pathLayer = parser.polylines; } } void pointsToMeasureSelectedValueChanged(int value) { pointsToMeasureSelectedValue.value = value; print('Selected point -> ${pointsToMeasureSelectedValue.value}'); } double calculateDistance(LatLng start, LatLng end) { const double earthRadius = 6371.0; // Radius of the Earth in kilometers // Convert coordinates to radians final double lat1 = start.latitude * (pi / 180.0); final double lon1 = start.longitude * (pi / 180.0); final double lat2 = end.latitude * (pi / 180.0); final double lon2 = end.longitude * (pi / 180.0); // Calculate the differences between the coordinates final double dLat = lat2 - lat1; final double dLon = lon2 - lon1; // Apply the Haversine formula final double a = sin(dLat / 2) * sin(dLat / 2) + cos(lat1) * cos(lat2) * sin(dLon / 2) * sin(dLon / 2); final double c = 2 * atan2(sqrt(a), sqrt(1 - a)); final double distance = earthRadius * c; return distance; // Distance in kilometers, add "*1000" to get meters } void addMeasuredPoint() { // _measuredPoints.add({"id": 4001, "latitude": 46.3455, "longitude": 19.652}); } 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 saveVehicleNumber(int vehicleNumber) { prefs.setInt('vehicleNumber', vehicleNumber); } }