Copy old project - initial state

This commit is contained in:
2025-01-07 15:19:59 +01:00
parent cae841f0e5
commit afad23ca20
202 changed files with 17563 additions and 0 deletions
@@ -0,0 +1,9 @@
import 'package:get/get.dart';
import 'package:terepi_seged/pages/bleutooth/presentation/controllers/bluetooth_controller.dart';
class BluetoothTestBinding extends Bindings {
@override
void dependencies() {
Get.lazyPut(() => BluetoothTestViewController());
}
}
@@ -0,0 +1,180 @@
import 'dart:async';
import 'dart:convert';
import 'dart:typed_data';
import 'package:flutter_bluetooth_serial/flutter_bluetooth_serial.dart';
import 'package:get/get.dart';
import 'package:nmea/nmea.dart';
import 'package:terepi_seged/gnss_sentences/gngga.dart';
class BluetoothTestViewController extends GetxController {
Rx<BluetoothState> bluetoothState = BluetoothState.UNKNOWN.obs;
RxList<BluetoothDevice> devices = RxList<BluetoothDevice>([]);
Rx<BluetoothDevice>? selectedDevice;
final NmeaDecoder nmeaDecoder = NmeaDecoder();
BluetoothConnection? connection;
StreamSubscription<BluetoothDiscoveryResult>? _bluetoothDiscoveryStream;
RxList<BluetoothDiscoveryResult> bluetoothDiscoveryResults =
RxList<BluetoothDiscoveryResult>.empty(growable: true);
// bool get isConnected => connection != null && connection!.isConnected;
bool isConnected = false;
int count = 0;
String _messageBuffer = '';
bool hasGpsData = false;
DateTime lastGpsRefreshTime = DateTime.now();
RxString utcOfPositionFix = "".obs;
@override
void onInit() {
super.onInit();
print("Call BluetoothTestController.OnInit");
FlutterBluetoothSerial.instance.state.then((state) {
bluetoothState.value = state;
if (bluetoothState.value.isEnabled) {
//_listBoundedDevices();
_startDiscovery();
}
});
nmeaDecoder.registerTalkerSentence("GGA", (line) => Gngga(raw: line));
//Loading, Success, Error handle with 1 line of code
}
@override
void onClose() {
super.onClose();
FlutterBluetoothSerial.instance.setPairingRequestHandler(null);
if (isConnected) {
connection?.close();
// connection = null;
print("BluetoothTestController dispose ....");
}
}
_listBoundedDevices() {
FlutterBluetoothSerial.instance
.getBondedDevices()
.then((List<BluetoothDevice> boundedDevices) {
devices.value = boundedDevices;
devices.refresh();
});
}
void setSelectedDevice(BluetoothDevice device) {
selectedDevice = Rx<BluetoothDevice>(device);
if (!isConnected) {
BluetoothConnection.toAddress(selectedDevice?.value.address)
.then((value) {
connection = value;
isConnected = true;
print("Bleutooth device connected .... ${connection!.isConnected}");
connection!.input!.listen(_onDataReceived);
});
// connection!.input!.listen((data) {
// print("Data -> $data");
// });
}
}
void _startDiscovery() {
_bluetoothDiscoveryStream =
FlutterBluetoothSerial.instance.startDiscovery().listen((event) {
final existingIndex = bluetoothDiscoveryResults.indexWhere(
(element) => element.device.address == event.device.address);
if (existingIndex > 0) {
bluetoothDiscoveryResults[existingIndex] = event;
update();
} else {
bluetoothDiscoveryResults.add(event);
update();
}
});
_bluetoothDiscoveryStream!.onDone(() {});
}
void _onDataReceived(Uint8List data) {
// Allocate buffer for parsed data
int backspacesCounter = 0;
String sentence = '';
// print("Data: $data");
for (var byte in data) {
if (byte == 8 || byte == 127) {
backspacesCounter++;
}
}
Uint8List buffer = Uint8List(data.length - backspacesCounter);
int bufferIndex = buffer.length;
// Apply backspace control character
backspacesCounter = 0;
for (int i = data.length - 1; i >= 0; i--) {
if (data[i] == 8 || data[i] == 127) {
backspacesCounter++;
} else {
if (backspacesCounter > 0) {
backspacesCounter--;
} else {
buffer[--bufferIndex] = data[i];
}
}
}
// Create message if there is new line character
String dataString = String.fromCharCodes(buffer);
int index = buffer.indexOf(13);
if (~index != 0) {
sentence = backspacesCounter > 0
? _messageBuffer.substring(
0, _messageBuffer.length - backspacesCounter)
: _messageBuffer + dataString.substring(0, index);
_messageBuffer = dataString.substring(index);
} else {
_messageBuffer = (backspacesCounter > 0
? _messageBuffer.substring(
0, _messageBuffer.length - backspacesCounter)
: _messageBuffer + dataString);
}
count++;
// print("Message ($count): $sentence");
_processGnssMessage(sentence);
}
void _processGnssMessage(String message) {
LineSplitter lineSplitter = const LineSplitter();
List<String> 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) {
hasGpsData = sentence.gpsQualityIndicator > 0;
if (hasGpsData) {
if (DateTime.now().difference(lastGpsRefreshTime).inSeconds >= 4) {
lastGpsRefreshTime = DateTime.now();
utcOfPositionFix.value = sentence.utcOfPositionFix;
}
print("Last update: $utcOfPositionFix");
}
}
}
}
}
}
@@ -0,0 +1,70 @@
import 'package:flutter/material.dart';
import 'package:flutter_bluetooth_serial/flutter_bluetooth_serial.dart';
import 'package:get/get.dart';
import 'package:terepi_seged/models/bluetooth_device_list_entry.dart';
import 'package:terepi_seged/pages/bleutooth/presentation/controllers/bluetooth_controller.dart';
class BluetoothTestView extends GetView<BluetoothTestViewController> {
const BluetoothTestView({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
color: Colors.white,
child: Scaffold(
extendBody: true,
backgroundColor: Colors.black.withOpacity(0.05),
appBar: AppBar(
elevation: 0.0,
title: const Text('BluetoothTest'),
leading: IconButton(
icon: const Icon(Icons.arrow_back_ios),
color: Colors.white,
onPressed: () {
Get.back();
},
),
),
body: Column(children: [
const Center(
child: Text("BluetoothTestView"),
),
ListTile(
title: const Text(
'Bluetooth status',
),
subtitle: Obx(() => Text("${controller.bluetoothState}")),
trailing: ElevatedButton(
child: const Text('Settings'),
onPressed: () {
FlutterBluetoothSerial.instance.openSettings();
},
),
),
Obx(() => Text(
"${controller.bluetoothState}",
style: TextStyle(
color: controller.bluetoothState.value.isEnabled
? Colors.green
: Colors.red),
)),
Obx(() => Text("Last update: ${controller.utcOfPositionFix}",
style: const TextStyle(
color: Colors.blue, fontWeight: FontWeight.bold))),
Expanded(
child: Obx(
() => ListView(
children: controller.bluetoothDiscoveryResults
.map((device) => BluetoothDeviceListEntry(
device: device.device,
enabled: true,
onTap: () {
print("Device: ${device.device.address}");
controller.setSelectedDevice(device.device);
},
))
.toList()),
))
])));
}
}
@@ -0,0 +1,10 @@
import 'package:get/get.dart';
import '../presentation/controllers/home_controller.dart';
class HomeBinding extends Bindings {
@override
void dependencies() {
Get.lazyPut(() => HomeViewController());
}
}
@@ -0,0 +1,25 @@
import 'package:get/get.dart';
import 'package:package_info_plus/package_info_plus.dart';
class HomeViewController extends GetxController {
Rx<PackageInfo> packageInfo = PackageInfo(
appName: 'Unknown',
packageName: 'Unknown',
version: 'Unknown',
buildNumber: 'Unknown',
buildSignature: 'Unknown',
installerStore: 'Unknown',
).obs;
@override
void onInit() {
_initPackageInfo();
super.onInit();
//Loading, Success, Error handle with 1 line of code
}
Future<void> _initPackageInfo() async {
final info = await PackageInfo.fromPlatform();
packageInfo.value = info;
}
}
@@ -0,0 +1,176 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:terepi_seged/pages/home/presentation/controllers/home_controller.dart';
import 'package:terepi_seged/pages/home/presentation/widgets/big_button_widget.dart';
class HomeView extends GetView<HomeViewController> {
const HomeView({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
color: Colors.white,
child: Scaffold(
extendBody: true,
backgroundColor: Colors.black.withOpacity(0.05),
appBar: AppBar(
elevation: 0.0,
title: const Text('Kezdőlap'),
leading: IconButton(
icon: const Icon(Icons.arrow_back_ios),
color: Colors.white,
onPressed: () {
Get.back();
},
),
),
body: Column(children: [
Column(
children: const [
Padding(
padding: EdgeInsets.only(top: 10.0),
child: Center(
child: Text("Kezdőlap"),
),
),
// TextButton(
// onPressed: () async {
// Get.toNamed('/map');
// },
// child: const Text('Map')),
// TextButton(
// onPressed: () async {
// Get.toNamed('/bluetooth_test');
// },
// child: const Text('Bluetooth test')),
// TextButton(
// onPressed: () async {
// Get.toNamed('/socket_test');
// },
// child: const Text('Socket teszt')),
// TextButton(
// onPressed: () async {
// Get.toNamed('/rtcm_test');
// },
// child: const Text('RTCM teszt'))
],
),
Padding(
padding: const EdgeInsets.only(top: 10.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
BigButtonWidget(
iconData: Icons.flag,
label: "Kitűzés",
onPressed: () async {
Get.toNamed('/map');
},
),
BigButtonWidget(
iconData: Icons.monitor_heart,
label: "Mérés",
onPressed: () async {
Get.toNamed("/measured_data");
// ScaffoldMessenger.of(context)
// .showSnackBar(const SnackBar(
// content: Text(
// "Fejlesztlés alatt",
// style: TextStyle(fontWeight: FontWeight.bold),
// ),
// backgroundColor: Colors.black54,
// ));
},
),
],
),
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 10.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
BigButtonWidget(
iconData: Icons.navigation,
label: "Navigáció",
onPressed: () async {
Get.toNamed('/navigation');
// ScaffoldMessenger.of(context)
// .showSnackBar(const SnackBar(
// content: Text(
// "Fejlesztlés alatt",
// style: TextStyle(fontWeight: FontWeight.bold),
// ),
// backgroundColor: Colors.black54,
// ));
},
),
BigButtonWidget(
iconData: Icons.message,
label: "Üzenetek",
onPressed: () async {
// Get.toNamed("/navigation");
ScaffoldMessenger.of(context)
.showSnackBar(const SnackBar(
content: Text(
"Fejlesztlés alatt",
style: TextStyle(fontWeight: FontWeight.bold),
),
backgroundColor: Colors.black54,
));
},
),
],
),
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 10.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
BigButtonWidget(
iconData: Icons.house,
label: "Ingatlanok",
onPressed: () async {
// Get.toNamed('/map_test');
ScaffoldMessenger.of(context)
.showSnackBar(const SnackBar(
content: Text(
"Fejlesztlés alatt",
style: TextStyle(fontWeight: FontWeight.bold),
),
backgroundColor: Colors.black54,
));
},
),
BigButtonWidget(
iconData: Icons.edit_road,
label: "Track",
onPressed: () async {
// Get.toNamed("/navigation");
ScaffoldMessenger.of(context)
.showSnackBar(const SnackBar(
content: Text(
"Fejlesztlés alatt",
style: TextStyle(fontWeight: FontWeight.bold),
),
backgroundColor: Colors.black54,
));
},
),
],
),
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Obx(
() => Text(
"Verzió: ${controller.packageInfo.value.version}+${controller.packageInfo.value.buildNumber}",
style: const TextStyle(fontSize: 12)),
)
],
)
])));
}
}
@@ -0,0 +1,43 @@
import 'package:flutter/material.dart';
class BigButtonWidget extends StatelessWidget {
const BigButtonWidget(
{Key? key, required this.iconData, required this.label, this.onPressed})
: super(key: key);
final IconData iconData;
final String label;
final Function()? onPressed;
@override
Widget build(BuildContext context) {
return OutlinedButton(
onPressed: onPressed,
style: ButtonStyle(
minimumSize: MaterialStateProperty.all(const Size(130, 140)),
maximumSize: MaterialStateProperty.all(const Size(130, 140)),
shape: MaterialStateProperty.all<RoundedRectangleBorder>(
const RoundedRectangleBorder(borderRadius: BorderRadius.zero))),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Padding(
padding: const EdgeInsets.fromLTRB(8.0, 10.0, 8.0, 4.0),
child: Icon(
iconData,
color: Colors.blueGrey,
size: 64,
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
label,
textAlign: TextAlign.center,
style: const TextStyle(
color: Colors.blueGrey, fontWeight: FontWeight.bold),
))
],
));
}
}
+9
View File
@@ -0,0 +1,9 @@
import 'package:get/get.dart';
import 'package:terepi_seged/pages/map/presentation/controllers/map_controller.dart';
class MapBinding extends Bindings {
@override
void dependencies() {
Get.lazyPut(() => MapViewController());
}
}
@@ -0,0 +1,890 @@
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: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;
class MapViewController 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;
String gpsName = "TiGNSS Rover-FF4E";
// String gpsName = "TiGNSS Rover-8BB2";
static const double maxZoomValue = 25.0;
Rx<bool> 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<DateTime> gpsDateTime = DateTime(2000).obs;
Rx<Eov> 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 = <Marker>[];
final pointNotesMarker = <Marker>[];
List<PointToMeasure> pointsToMeasure = <PointToMeasure>[];
final pointsToMeasureMarker = <Marker>[];
final pointsToMeasureLabel = <PolyWidget>[];
final pointsToMeasureDropDownMenuItem = <DropdownMenuItem<int>>[];
RxInt pointsToMeasureSelectedValue = (-1).obs;
RxDouble distance = 0.0.obs;
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 = "";
String ntripUserName = "";
String ntripPassword = "";
Rx<bool> pointMeasuringDirectionForward = true.obs;
List<PointWithDescription> pointWithDescriptionList = [];
late Directory? directory;
late File dataFile;
late proj4.Projection eovProj, wgsProj;
RxBool mapIsInitialized = false.obs;
GeoJsonParser parser = GeoJsonParser(defaultMarkerColor: Colors.yellow);
final CollectionReference _measuredPoints =
FirebaseFirestore.instance.collection('measuredPoints');
// 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';
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));
mapController = MapController();
// 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();
pointPrefixController.dispose();
pointPostfixController.dispose();
ntripUsernameController.dispose();
ntripPasswordController.dispose();
}
@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");
}
}
directory = await getExternalStorageDirectory();
print(directory!.path);
// String newPath = '';
// List<String> 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.7';
}
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 += "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<int> codeUnits = str.codeUnits;
final Uint8List unit8List = Uint8List.fromList(codeUnits);
return unit8List;
}
void _processGnssMessage(String message) {
LineSplitter lineSplitter = const LineSplitter();
List<String> 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]}"));
}
}
}
}
}
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 =
'${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: <Widget>[
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
});
if (pointMeasuringDirectionForward.isTrue) {
if (pointsToMeasureSelectedValue.value <
pointsToMeasure.length - 1) {
pointId++;
pointsToMeasureSelectedValue.value += 1;
noMorePoint = false;
} else {
noMorePoint = true;
// Get.snackbar("Információ", "Nincs több bemérendő pont.",
// colorText: Colors.white,
// backgroundColor: Colors.lightBlue);
ScaffoldMessenger.of(Get.context!).showSnackBar(
const SnackBar(
content: Text('Nincs több bemérendő pont.')));
}
} else {
if (pointsToMeasureSelectedValue.value > 0) {
pointId--;
pointsToMeasureSelectedValue.value -= 1;
noMorePoint = false;
} else {
noMorePoint = true;
ScaffoldMessenger.of(Get.context!).showSnackBar(
const SnackBar(
content: Text('Nincs több bemérendő pont.')));
}
}
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 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.purple,
shape: BoxShape.circle,
border: Border.all(width: 1.0, color: Colors.black)),
)));
pointsToMeasureLabel.add(PolyWidget(
center: LatLng(wgsCoord.y + 0.0000075, wgsCoord.x + 0.0000075),
widthInMeters: 3,
heightInMeters: 3,
// 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<int>(
value: index - 1,
child: Text('$id'),
));
}
}
}
pointsToMeasureSelectedValue.value = 0;
print('Converted points number -> ${pointsToMeasure.length}');
}
}
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 showAddPointDialog() {
onBottomNavigationBarTap(0);
}
}
@@ -0,0 +1,97 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:terepi_seged/pages/map/presentation/controllers/map_controller.dart';
class MapAddPointDialog extends GetView<MapViewController> {
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();
},
),
],
)
],
),
)),
);
}
}
@@ -0,0 +1,458 @@
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/presentation/controllers/map_controller.dart';
import 'package:terepi_seged/pages/map/presentation/views/settings_dialog.dart';
import 'package:terepi_seged/utils/rive_utils.dart';
import 'map_add_point_dialog.dart';
class MapView extends GetView<MapViewController> {
const MapView({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(
"Budapest",
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: () {
controller.ReadPointsFromFile();
},
child:
const Icon(Icons.file_open, size: 26.0, color: Colors.blue),
),
),
Padding(
padding: const EdgeInsets.only(right: 20.0),
child: GestureDetector(
onTap: () => 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,
)
],
)),
Padding(
padding: const EdgeInsets.only(left: 8.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
DropdownButton(
onChanged: (int? newValue) {
controller
.pointsToMeasureSelectedValueChanged(
newValue!);
},
items:
controller.pointsToMeasureDropDownMenuItem,
value: controller
.pointsToMeasureSelectedValue.value,
),
const SizedBox(height: 10),
FittedBox(
child: Text(
'Távolság: ${(controller.distance * 1000).toStringAsFixed(3)} m',
style: const TextStyle(
fontWeight: FontWeight.bold,
fontSize: 12.0),
),
)
],
),
)
],
),
)
: const SizedBox(),
),
Expanded(
child: Stack(
children: [
Obx(
() => controller.mapIsInitialized.value
? FlutterMap(
mapController: controller.mapController,
options: MapOptions(
center: LatLng(controller.currentLatitude.value,
controller.currentLongitude.value),
maxZoom: 25,
zoom: 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),
),
],
),
);
}
}
@@ -0,0 +1,247 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:terepi_seged/pages/map/presentation/controllers/map_controller.dart';
class SettingsDialog extends StatelessWidget {
final controller = Get.find<MapViewController>();
SettingsDialog({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
body: ListView(
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
IconButton(
onPressed: () {
Get.back();
},
icon: const Icon(Icons.close)),
TextButton(
style: ButtonStyle(
overlayColor:
MaterialStateProperty.all(Colors.transparent)),
onPressed: () {},
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-FF4E'),
value: '98:CD:AC:62:FF:4E',
groupValue: controller.gpsAddress.value,
onChanged: (value) {
controller.gpsAddress.value = value!;
}),
RadioListTile(
title: Text('TiGNSS Rover-8BB2'),
value: 'E8:31:CD:14:8B:B2',
groupValue: controller.gpsAddress.value,
onChanged: (value) {
controller.gpsAddress.value = value!;
;
}),
RadioListTile(
title: Text('TiGNSS Rover-FF36'),
value: '98:CD:AC:62:FF:36',
groupValue: controller.gpsAddress.value,
onChanged: (value) {
controller.gpsAddress.value = value!;
})
])),
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<bool>(
title: Text('Növekvő'),
value: true,
groupValue: controller.pointMeasuringDirectionForward.value,
onChanged: (value) {
controller.pointMeasuringDirectionForward.value = value!;
}),
RadioListTile<bool>(
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)
]),
),
],
),
);
}
}
@@ -0,0 +1,9 @@
import 'package:get/get.dart';
import 'package:terepi_seged/pages/map_test/presentation/controllers/map_test_controller.dart';
class MapTestBinding extends Bindings {
@override
void dependencies() {
Get.lazyPut(() => MapTestController());
}
}
@@ -0,0 +1,281 @@
import 'dart:async';
import 'dart:convert';
import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:get/get.dart';
import 'package:location/location.dart';
import 'package:syncfusion_flutter_maps/maps.dart';
class MapTestController extends GetxController {
late MapShapeSource mapSource;
late MapShapeSource kozigSource;
late MapZoomPanBehavior zoomPanBehavior;
late MapTileLayerController mapTileLayerController;
late List<MapLatLng> line1, line2, line3;
late List<List<MapLatLng>> lines1, lines2, lines3;
late List<MapModel> mapModel = [];
late StreamSubscription<LocationData> locationSubscription;
bool locationSubscriptionIsInitialized = false;
Location location = Location();
RxDouble currentLongitude = 18.122495576634044.obs;
RxDouble currentLatitude = 46.328746702592106.obs;
RxBool isInitialized = false.obs;
@override
void onInit() async {
mapTileLayerController = MapTileLayerController();
bool res = await loadMapData();
location.changeSettings(
accuracy: LocationAccuracy.high, interval: 500, distanceFilter: 1);
line1 = const <MapLatLng>[
MapLatLng(46.409474083913345, 18.196055479431202),
MapLatLng(46.40229074049568, 18.184834829804377),
MapLatLng(46.400881093344097, 18.183525800449701),
MapLatLng(46.392903944366708, 18.177253122976378),
MapLatLng(46.384773311328807, 18.170585406188426),
MapLatLng(46.382049391318191, 18.168012348371033),
MapLatLng(46.381677738114753, 18.167665852333496),
MapLatLng(46.381161940383038, 18.167149737333396),
MapLatLng(46.377534073316291, 18.164141681038203),
MapLatLng(46.374368645392636, 18.161698675385864),
MapLatLng(46.370683914933664, 18.158587091204133),
MapLatLng(46.3640763356468, 18.153155234991335),
MapLatLng(46.363576961214015, 18.152317669751312),
MapLatLng(46.35389201272092, 18.13590711186691),
MapLatLng(46.352978857192532, 18.133309083714881),
MapLatLng(46.35137058576526, 18.13098235253349),
MapLatLng(46.348440208996635, 18.126684238252697),
MapLatLng(46.347130535026032, 18.123117395006844),
MapLatLng(46.34706818966626, 18.122931136322965),
MapLatLng(46.346565571573841, 18.122161191477915),
MapLatLng(46.346370011622788, 18.121391157301662),
MapLatLng(46.342636923837361, 18.112691291995962),
MapLatLng(46.342389315173889, 18.111910189208963),
MapLatLng(46.333172947557394, 18.099415040392927),
MapLatLng(46.32863226668006, 18.087695666266029),
MapLatLng(46.325737435025978, 18.08355812652276),
// MapLatLng(46.322053106393668, 18.078583447909164),
// MapLatLng(46.318345777758296, 18.075366997618815),
// MapLatLng(46.317198167430817, 18.074782985031753),
// MapLatLng(46.316022015155262, 18.07310019901135),
// MapLatLng(46.314147548726261, 18.072144612154844),
// MapLatLng(46.312510626772578, 18.071178953163265),
// MapLatLng(46.310758970899364, 18.068863947464287),
// MapLatLng(46.308993975939856, 18.065995601793436),
// MapLatLng(46.302099673468611, 18.060496509299735),
// MapLatLng(46.299097775521432, 18.05627769200369),
// MapLatLng(46.295182331629846, 18.051900556314489),
// MapLatLng(46.292525209632785, 18.048285539930436),
// MapLatLng(46.290524900577878, 18.045515378447099)
];
line3 = const <MapLatLng>[
MapLatLng(46.325737435025978, 18.08355812652276),
MapLatLng(46.322053106393668, 18.078583447909164),
MapLatLng(46.318345777758296, 18.075366997618815),
MapLatLng(46.317198167430817, 18.074782985031753),
MapLatLng(46.316022015155262, 18.07310019901135),
MapLatLng(46.314147548726261, 18.072144612154844),
MapLatLng(46.312510626772578, 18.071178953163265),
MapLatLng(46.310758970899364, 18.068863947464287),
MapLatLng(46.308993975939856, 18.065995601793436),
MapLatLng(46.302099673468611, 18.060496509299735),
MapLatLng(46.299097775521432, 18.05627769200369),
MapLatLng(46.295182331629846, 18.051900556314489),
MapLatLng(46.292525209632785, 18.048285539930436),
MapLatLng(46.290524900577878, 18.045515378447099)
];
line2 = const <MapLatLng>[
// MapLatLng(46.260064352706863, 18.116797380886084),
MapLatLng(46.251888084511876, 18.116765702743511),
MapLatLng(46.276731538707907, 18.118312495916047),
MapLatLng(46.290630785869595, 18.121715933401102),
MapLatLng(46.291602112755918, 18.121615413423505),
MapLatLng(46.293861019929999, 18.121966080774971),
MapLatLng(46.306808758830037, 18.120536071329884),
MapLatLng(46.307565036417657, 18.120339010103002),
MapLatLng(46.313074623341073, 18.12005586208279),
MapLatLng(46.315292570695746, 18.120136355999676),
MapLatLng(46.317610563278862, 18.120225447918834),
MapLatLng(46.31852533235655, 18.120312832087762),
MapLatLng(46.324753378018201, 18.120473866804605),
MapLatLng(46.334486981796822, 18.117343038689867),
MapLatLng(46.335047155775996, 18.117367081901961),
MapLatLng(46.337466485256385, 18.116990955631348),
MapLatLng(46.340277266846968, 18.116562251592601),
MapLatLng(46.343322881556979, 18.116268008370902),
MapLatLng(46.347183527547493, 18.113215711471319),
MapLatLng(46.347908214739213, 18.112661806065514),
MapLatLng(46.348086908069178, 18.112669488541766),
MapLatLng(46.348833657599236, 18.113161876278717),
MapLatLng(46.35355966637772, 18.112136546361285),
MapLatLng(46.357138992408714, 18.111476412678716)
];
lines2 = [line2];
lines3 = [line3];
lines1 = [line1];
await _getInitialLocation();
mapSource = MapShapeSource.asset(
'assets/Files/erintett_telkek_0613.geojson',
shapeDataField: "id1",
dataCount: mapModel.length,
primaryValueMapper: (index) => mapModel[index].id!,
dataLabelMapper: (index) => mapModel[index].hrsz!,
shapeColorValueMapper: (index) => mapModel[index].color!,
);
kozigSource = const MapShapeSource.asset(
'assets/Files/kozig_hatar.geojson',
shapeDataField: "Telepules",
);
zoomPanBehavior = MapZoomPanBehavior(
minZoomLevel: 1,
maxZoomLevel: 25,
zoomLevel: 15,
// focalLatLng: const MapLatLng(46.328746702592106, 18.122495576634044));
focalLatLng: MapLatLng(currentLatitude.value, currentLongitude.value));
_listenLocation();
super.onInit();
isInitialized.value = true;
}
@override
void onClose() {
if (locationSubscriptionIsInitialized) {
locationSubscription.cancel();
}
super.onClose();
}
Future<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;
}
Future<void> _listenLocation() async {
locationSubscription =
location.onLocationChanged.handleError((dynamic err) {
locationSubscription.cancel();
}).listen((LocationData currentLocation) {
currentLatitude.value = currentLocation.latitude!;
currentLongitude.value = currentLocation.longitude!;
locationSubscriptionIsInitialized = true;
log('x: ${currentLatitude.value} - y: ${currentLongitude.value}');
// zoomPanBehavior.focalLatLng =
// MapLatLng(currentLatitude.value, currentLongitude.value);
mapTileLayerController.updateMarkers([0]);
});
}
Future<String> getJsonFromAssets() async {
return await rootBundle.loadString('assets/Files/telkek_0510.geojson');
}
Future<bool> loadMapData() async {
final String jsonString = await getJsonFromAssets();
final Map<String, dynamic> jsonResponse = jsonDecode(jsonString);
List<dynamic> feature = jsonResponse['features'];
for (int i = 0; i < feature.length; i++) {
mapModel.add(
MapModel.fromJson(feature[i]['properties'] as Map<String, dynamic>));
}
// _shapeSource = MapShapeSource.asset('assets/usa.json',
// shapeDataField: 'name',
// dataCount: _mapData.length,
// primaryValueMapper: (int index) => _mapData[index].name!,
// dataLabelMapper: (int index) => _mapData[index].name!,
// shapeColorValueMapper: (int index) => _mapData[index].color);
return true;
}
}
class MapModel {
// Data type
Color? color;
String? hrsz;
String? telepules;
String? id;
//constructor
MapModel({this.id, this.telepules, this.hrsz, this.color});
// Method that assigns values to respective datatype variables
factory MapModel.fromJson(Map<String, dynamic> json) {
Color modelColor = Colors.amber;
double opacity = 0.5;
/// While fetching the color codes as String from JSON. Use these codes to convert it as Color.
//String hexColor = json['COLOR'] as String;
// Color(int.parse(hexColor.substring(1, 7), radix: 16) + 0xFF000000);
// log("${json['id1']} - ${json['Telepules']} - ${json['Hrsz']}");
String telepules = json['Telepules'];
if (telepules == 'Jágónak') {
modelColor = Color.fromRGBO(55, 88, 187, opacity);
} else if (telepules == 'Baranyajenő') {
modelColor = Color.fromRGBO(159, 65, 214, opacity);
} else if (telepules == 'Kercseliget') {
modelColor = Color.fromRGBO(235, 209, 63, opacity);
} else if (telepules == 'Dombóvár') {
modelColor = Color.fromRGBO(99, 219, 169, opacity);
} else if (telepules == 'Kaposszekcső') {
modelColor = Color.fromRGBO(202, 122, 86, opacity);
} else if (telepules == 'Csikóstőttős') {
modelColor = Color.fromRGBO(145, 43, 43, opacity);
} else if (telepules == 'Baranyajenő') {
modelColor = Color.fromRGBO(159, 65, 214, opacity);
} else if (telepules == 'Vásárosdombó') {
modelColor = Color.fromRGBO(51, 238, 60, opacity);
} else if (telepules == 'Meződ') {
modelColor = Color.fromRGBO(99, 212, 216, opacity);
} else if (telepules == 'Tarrós') {
modelColor = Color.fromRGBO(224, 203, 236, opacity);
} else if (telepules == 'Vázsnok') {
modelColor = Color.fromRGBO(74, 155, 8, opacity);
} else if (telepules == 'Sásd') {
modelColor = Color.fromRGBO(143, 91, 112, opacity);
}
return MapModel(
id: json['id1'] as String,
telepules: json['Telepules'],
hrsz: json['Hrsz'],
color: modelColor);
}
}
@@ -0,0 +1,105 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:syncfusion_flutter_maps/maps.dart';
import 'package:terepi_seged/pages/map_test/presentation/controllers/map_test_controller.dart';
class MapTestView extends GetView<MapTestController> {
const MapTestView({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Obx(
() => controller.isInitialized.value
? SfMaps(
layers: [
MapTileLayer(
urlTemplate:
'http://mt1.google.com/vt/lyrs=s,h&x={x}&y={y}&z={z}',
zoomPanBehavior: controller.zoomPanBehavior,
controller: controller.mapTileLayerController,
initialMarkersCount: 1,
markerBuilder: (BuildContext context, int index) {
return MapMarker(
latitude: controller.currentLatitude.value,
longitude: controller.currentLongitude.value,
size: const Size(20, 20),
child: const Icon(
Icons.location_on,
color: Colors.yellow,
),
);
},
sublayers: [
// MapShapeSublayer(
// source: controller.kozigSource,
// showDataLabels: true,
// dataLabelSettings: const MapDataLabelSettings(
// textStyle: TextStyle(
// color: Colors.red,
// fontSize: 12,
// fontWeight: FontWeight.normal,
// fontFamily: 'Times')),
// color: Colors.transparent,
// strokeColor: Colors.red,
// strokeWidth: 2,
// ),
MapShapeSublayer(
source: controller.mapSource,
showDataLabels: true,
dataLabelSettings: const MapDataLabelSettings(
textStyle: TextStyle(
color: Colors.black,
fontSize: 10,
fontWeight: FontWeight.bold,
fontFamily: 'Times')),
// color: Colors.white38,
strokeColor: Colors.black,
strokeWidth: 2,
),
MapPolylineLayer(
polylines: List<MapPolyline>.generate(
controller.lines2.length, (index) {
return MapPolyline(
points: controller.lines2[index],
color: Colors.purple,
width: 3);
}).toSet()),
MapPolylineLayer(
polylines: List<MapPolyline>.generate(
controller.lines2.length, (index) {
return MapPolyline(
points: controller.lines3[index],
color: Colors.yellow,
width: 3);
}).toSet()),
MapPolylineLayer(
polylines: List<MapPolyline>.generate(
controller.lines1.length, (index) {
return MapPolyline(
points: controller.lines1[index],
color: Colors.yellow,
width: 3);
}).toSet()),
],
),
// MapShapeLayer(
// source: controller.mapSource,
// showDataLabels: true,
// dataLabelSettings: const MapDataLabelSettings(
// textStyle: TextStyle(
// color: Colors.black,
// fontSize: 10,
// fontWeight: FontWeight.bold,
// fontFamily: 'Times')),
// zoomPanBehavior: controller.zoomPanBehavior,
// )
],
)
: const Center(child: CircularProgressIndicator()),
),
),
);
}
}
@@ -0,0 +1,9 @@
import 'package:get/get.dart';
import 'package:terepi_seged/pages/measured_data/presentation/controllers/measured_data_controller.dart';
class MeasuredDataBinding extends Bindings {
@override
void dependencies() {
Get.lazyPut(() => MeasuredDataController());
}
}
@@ -0,0 +1,56 @@
import 'dart:typed_data';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_storage/firebase_storage.dart';
import 'package:get/get.dart';
import 'package:terepi_seged/models/seismic_records.dart';
import 'package:terepi_seged/pages/measured_data/presentation/views/seismogram_viewer_dialog.dart';
class MeasuredDataController extends GetxController {
final CollectionReference _seismicRecords =
FirebaseFirestore.instance.collection('seismicRecords');
// late Query<Map<String, dynamic>> records = _seismicRecords.orderBy('field');
late Stream<QuerySnapshot> seismicRecordSnapshot;
@override
void onReady() async {
super.onReady();
}
@override
void onInit() {
super.onInit();
seismicRecordSnapshot = _seismicRecords
// .orderBy('sourcePoint', descending: true)
.where('gpsDateTime', isGreaterThan: DateTime(2024, 2, 25, 0, 0, 0))
.orderBy('gpsDateTime', descending: true)
.snapshots();
}
@override
void onClose() async {
super.onClose();
// seismicRecordSnapshot.
}
void showSeismicImage(int ffid) async {
late Uint8List image;
Reference reference =
FirebaseStorage.instance.ref().child('bp-4/${ffid}.jpg');
await reference
.getData()
.then((value) => {image = value!})
.catchError((error) => {});
Get.to(
() => SeismogramViewerDialog(
imageUrl: '',
image: image,
),
transition: Transition.downToUp);
}
}
@@ -0,0 +1,83 @@
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'package:flutter/src/widgets/framework.dart';
import 'package:get/get.dart';
import 'package:terepi_seged/pages/measured_data/presentation/controllers/measured_data_controller.dart';
import 'package:terepi_seged/pages/measured_data/presentation/views/seismogram_viewer_dialog.dart';
class MeasuredDataView extends GetView<MeasuredDataController> {
const MeasuredDataView({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomInset: false,
extendBody: true,
appBar: AppBar(
title: const Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('Mérési adatok'),
Text(
"Budapest",
style: TextStyle(fontSize: 12.0),
)
],
),
actions: [
Padding(
padding: const EdgeInsets.only(right: 20.0),
child: GestureDetector(
onTap: () => Get.to(() => {}, transition: Transition.downToUp),
child: const Icon(
Icons.more_vert,
size: 26.0,
),
),
)
],
),
body: Column(children: [
Text("Mérési adatok"),
StreamBuilder<QuerySnapshot>(
stream: controller.seismicRecordSnapshot,
builder:
(BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (snapshot.hasError) {
return const Text('Hiba ...');
}
if (snapshot.connectionState == ConnectionState.waiting) {
return const Text('Adatbetöltés ...');
}
return Expanded(
child: ListView(
// shrinkWrap: true,
children: snapshot.data!.docs
.map((DocumentSnapshot document) {
Map<String, dynamic> data =
document.data()! as Map<String, dynamic>;
return ListTile(
title: Text(data['sourcePoint'].toString()),
subtitle: Text(
'${data['sourceLine'].toString()} - ${(data['gpsDateTime'] as Timestamp).toDate()}'),
trailing: Wrap(spacing: -16, children: [
IconButton(
onPressed: () {
controller.showSeismicImage(data['ffid']);
},
icon: const Icon(Icons.image_outlined)),
IconButton(
onPressed: () {},
icon:
const Icon(Icons.arrow_forward_ios_sharp))
]));
})
.toList()
.cast(),
),
);
},
)
]));
}
}
@@ -0,0 +1,68 @@
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:photo_view/photo_view.dart';
import 'package:terepi_seged/pages/measured_data/presentation/controllers/measured_data_controller.dart';
import 'package:widget_zoom/widget_zoom.dart';
class SeismogramViewerDialog extends StatelessWidget {
final controller = Get.find<MeasuredDataController>();
final String imageUrl;
final Uint8List image;
// final double sourcePoint;
SeismogramViewerDialog(
{required this.imageUrl, required this.image, super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
body: ListView(
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
IconButton(
onPressed: () {
Get.back();
},
icon: const Icon(Icons.close)),
TextButton(
style: ButtonStyle(
overlayColor:
MaterialStateProperty.all(Colors.transparent)),
onPressed: () {
Get.back();
},
child: const Text(
'Bezár',
style: TextStyle(color: Colors.blue, fontSize: 14.0),
))
],
),
),
const Padding(
padding: EdgeInsets.symmetric(horizontal: 15.0),
child: Text(
'Felvétel megtekintése ()',
style: TextStyle(fontSize: 20.0, fontWeight: FontWeight.bold),
),
),
Padding(
padding: const EdgeInsets.only(top: 10.0),
child: Center(
child: WidgetZoom(
zoomWidget: Image(image: MemoryImage(image)),
heroAnimationTag: 'tag',
maxScaleFullscreen: 8,
maxScaleEmbeddedView: 8,
),
),
)
],
),
);
}
}
@@ -0,0 +1,9 @@
import 'package:get/get.dart';
import 'package:terepi_seged/pages/navigation/presentation/controllers/navigation_controller.dart';
class NavigationViewBinding extends Bindings {
@override
void dependencies() {
Get.lazyPut(() => NavigationViewController());
}
}
@@ -0,0 +1,967 @@
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/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: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;
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;
String gpsName = "TiGNSS Rover-FF4E";
// String gpsName = "TiGNSS Rover-8BB2";
static const double maxZoomValue = 25.0;
Rx<bool> 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<DateTime> gpsDateTime = DateTime(2000).obs;
Rx<Eov> 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 = <Marker>[];
final pointNotesMarker = <Marker>[];
List<PointToMeasure> pointsToMeasure = <PointToMeasure>[];
final pointsToMeasureMarker = <Marker>[];
final pointsToMeasureLabel = <PolyWidget>[];
final pointsToMeasureDropDownMenuItem = <DropdownMenuItem<int>>[];
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<bool> pointMeasuringDirectionForward = true.obs;
List<PointWithDescription> 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);
int vehicleNumber = 2;
late Location internalGpsLogger;
Location internalGpsLocation = Location();
late StreamSubscription<LocationData> internalGpsLocationSubscription;
// 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();
// riveGpsIconController = RiveUtils.getRiveController(Artboard(),
// stateMachineName: "gps_Interactivity");
// gpsTrigger = riveGpsIconController.findSMI("active");
mapIsInitialized.value = true;
vehicleNumberController.text = vehicleNumber.toString();
}
@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");
}
}
directory = await getExternalStorageDirectory();
print(directory!.path);
// String newPath = '';
// List<String> 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,
"gpsDateTime": time,
"latitude": latitude,
"longitude": longitude,
"altitude": altitude,
"horizontalError": accuracy,
"speed": speed,
"createdAt": DateTime.timestamp()
});
});
// 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<int> codeUnits = str.codeUnits;
final Uint8List unit8List = Uint8List.fromList(codeUnits);
return unit8List;
}
void _processGnssMessage(String message) {
LineSplitter lineSplitter = const LineSplitter();
List<String> 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,
"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()
});
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: <Widget>[
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.purple,
shape: BoxShape.circle,
border: Border.all(width: 1.0, color: Colors.black)),
)));
pointsToMeasureLabel.add(PolyWidget(
center: LatLng(wgsCoord.y + 0.0000075, wgsCoord.x + 0.0000075),
widthInMeters: 3,
heightInMeters: 3,
// 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<int>(
value: index - 1,
child: Text('$id'),
));
}
}
}
pointsToMeasureSelectedValue.value = 0;
print('Converted points number -> ${pointsToMeasure.length}');
}
}
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});
}
}
@@ -0,0 +1,427 @@
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/navigation/presentation/controllers/navigation_controller.dart';
import 'package:terepi_seged/pages/navigation/presentation/views/settings_dialog.dart';
import 'package:terepi_seged/utils/rive_utils.dart';
class NavigationView extends GetView<NavigationViewController> {
const NavigationView({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('Navigáció'),
Text(
"Mérés: Budapest-4",
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: () {
controller.ReadPointsFromFile();
},
child:
const Icon(Icons.file_open, size: 26.0, color: Colors.blue),
),
),
Padding(
padding: const EdgeInsets.only(right: 20.0),
child: GestureDetector(
onTap: () => 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,
)
],
)),
Padding(
padding: const EdgeInsets.only(left: 8.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
DropdownButton(
onChanged: (int? newValue) {
controller
.pointsToMeasureSelectedValueChanged(
newValue!);
},
items:
controller.pointsToMeasureDropDownMenuItem,
value: controller
.pointsToMeasureSelectedValue.value,
),
const SizedBox(height: 10),
FittedBox(
child: Text(
'Távolság: ${(controller.distance * 1000).toStringAsFixed(3)} m',
style: const TextStyle(
fontWeight: FontWeight.bold,
fontSize: 12.0),
),
)
],
),
)
],
),
)
: const SizedBox(),
),
Expanded(
child: Stack(
children: [
Obx(
() => controller.mapIsInitialized.value
? FlutterMap(
mapController: controller.mapController,
options: MapOptions(
center: LatLng(controller.currentLatitude.value,
controller.currentLongitude.value),
maxZoom: 25,
zoom: 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.centerFloat,
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,
),
],
),
);
}
}
@@ -0,0 +1,229 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:get/get.dart';
import 'package:terepi_seged/pages/navigation/presentation/controllers/navigation_controller.dart';
class SettingsDialog extends StatelessWidget {
final controller = Get.find<NavigationViewController>();
SettingsDialog({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
body: ListView(
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
IconButton(
onPressed: () {
controller.vehicleNumber =
int.parse(controller.vehicleNumberController.text);
Get.back();
},
icon: const Icon(Icons.close)),
TextButton(
style: ButtonStyle(
overlayColor:
MaterialStateProperty.all(Colors.transparent)),
onPressed: () {},
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-FF4E'),
value: '98:CD:AC:62:FF:4E',
groupValue: controller.gpsAddress.value,
onChanged: (value) {
controller.gpsAddress.value = value!;
}),
RadioListTile(
title: Text('TiGNSS Rover-8BB2'),
value: 'E8:31:CD:14:8B:B2',
groupValue: controller.gpsAddress.value,
onChanged: (value) {
controller.gpsAddress.value = value!;
;
}),
RadioListTile(
title: Text('TiGNSS Rover-FF36'),
value: '98:CD:AC:62:FF:36',
groupValue: controller.gpsAddress.value,
onChanged: (value) {
controller.gpsAddress.value = value!;
})
])),
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<bool>(
title: Text('Növekvő'),
value: true,
groupValue: controller.pointMeasuringDirectionForward.value,
onChanged: (value) {
controller.pointMeasuringDirectionForward.value = value!;
}),
RadioListTile<bool>(
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: 4),
const Padding(
padding: EdgeInsets.symmetric(horizontal: 20.0),
child: Text(
'Vibrátor:',
style: TextStyle(fontSize: 14.0, fontWeight: FontWeight.w500),
),
),
SizedBox(
height: 40,
child: TextField(
enableSuggestions: false,
autocorrect: false,
controller: controller.vehicleNumberController,
keyboardType: TextInputType.number,
inputFormatters: [FilteringTextInputFormatter.digitsOnly],
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: 'Járműszám:',
icon: Icon(
Icons.numbers,
)),
),
),
const SizedBox(height: 5),
const Padding(
padding: EdgeInsets.symmetric(horizontal: 20),
child: Divider(
height: 5,
),
),
const SizedBox(height: 4),
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)
]),
),
],
),
);
}
}
@@ -0,0 +1,9 @@
import 'package:get/get.dart';
import 'package:terepi_seged/pages/property_list/presentations/controllers/property_list_controller.dart';
class PropertyListBinding extends Bindings {
@override
void dependencies() {
Get.lazyPut(() => PropertyListController());
}
}
@@ -0,0 +1,3 @@
import 'package:get/get.dart';
class PropertyListController extends GetxController {}
@@ -0,0 +1,12 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:terepi_seged/pages/property_list/presentations/controllers/property_list_controller.dart';
class PropertyListView extends GetView<PropertyListController> {
const PropertyListView({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container();
}
}
@@ -0,0 +1,9 @@
import 'package:get/get.dart';
import 'package:terepi_seged/pages/rtcm_test/presentation/controllers/rtcm_test_controller.dart';
class RtcmTestBinding extends Bindings {
@override
void dependencies() {
Get.lazyPut(() => RtcmTestController());
}
}
@@ -0,0 +1,301 @@
import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'dart:typed_data';
import 'package:flutter_bluetooth_serial/flutter_bluetooth_serial.dart';
import 'package:get/get.dart';
import 'package:intl/intl.dart';
import 'package:nmea/nmea.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';
class RtcmTestController extends GetxController {
String gpsAddress = "E8:31:CD:14:8B:B2";
String gpsName = "TiGNSS Rover-8BB2";
Rx<bool> gpsIsConnected = false.obs;
RxBool ntripIsConnected = false.obs;
RxInt ntripDataPacketNumbers = 0.obs;
String _messageBuffer = "";
late BluetoothConnection connection;
late Socket socket;
late StreamSubscription socketStreamSubscription;
RxInt gpsReceivedData = 0.obs;
RxBool hasGpsValidData = false.obs;
DateTime lastGpsRefreshTime = DateTime.now();
String utcOfPositionFix = "";
String utcDateOfPositionFix = "";
RxInt ntripReceivedData = 0.obs;
final NmeaDecoder nmeaDecoder = NmeaDecoder();
NumberFormat formatEov = NumberFormat("##0,000.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<DateTime> gpsDateTime = DateTime(2000).obs;
Rx<Eov> 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;
@override
void onInit() {
super.onInit();
//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));
}
@override
void onClose() {
super.onClose();
FlutterBluetoothSerial.instance.setPairingRequestHandler(null);
if (gpsIsConnected.value) {
connection.close();
// connection = null;
print("BluetoothTestController dispose ....");
}
}
void connectToGps() {
if (gpsIsConnected == false) {
BluetoothConnection.toAddress(gpsAddress).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.asBroadcastStream;
ntripIsConnected.value = true;
socket.encoding = ascii;
print("Connected to ntrip server ....");
String header = "GET /KOVARIK 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 += "Host:rtk2go.com: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 > 12) {
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));
}
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<int> codeUnits = str.codeUnits;
final Uint8List unit8List = Uint8List.fromList(codeUnits);
return unit8List;
}
void _processGnssMessage(String message) {
LineSplitter lineSplitter = const LineSplitter();
List<String> 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 >= 2) {
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);
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);
}
}
}
}
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;
}
}
@@ -0,0 +1,120 @@
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:terepi_seged/pages/rtcm_test/presentation/controllers/rtcm_test_controller.dart';
class RtcmTestView extends GetView<RtcmTestController> {
const RtcmTestView({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
color: Colors.white,
child: Scaffold(
extendBody: true,
backgroundColor: Colors.black.withOpacity(0.05),
appBar: AppBar(
elevation: 0.0,
title: const Text('RtcmTest'),
leading: IconButton(
icon: const Icon(Icons.arrow_back_ios),
color: Colors.white,
onPressed: () {
Get.back();
},
),
),
body: Column(
children: [
const Center(
child: Text("RTCM teszt view"),
),
ListTile(
title: Text(controller.gpsName),
subtitle: Obx(() => controller.gpsIsConnected.value
? const Text("Connected",
style: TextStyle(color: Colors.green))
: const Text(
"Disconnected",
style: TextStyle(color: Colors.red),
)),
trailing: Obx(() => ElevatedButton(
child: Text(controller.gpsIsConnected.value
? "Disconnect"
: "Connect"),
onPressed: () {
if (controller.gpsIsConnected.value) {
controller.disconnectFromGps();
} else {
controller.connectToGps();
}
},
)),
),
ListTile(
title: const Text("NTRIP Server (KOVARIK)"),
subtitle: Obx(() => controller.ntripIsConnected.value
? const Text("Connected",
style: TextStyle(color: Colors.green))
: const Text(
"Disconnected",
style: TextStyle(color: Colors.red),
)),
trailing: Obx(() => ElevatedButton(
child: Text(controller.ntripIsConnected.value
? "Disconnect"
: "Connect"),
onPressed: () {
if (controller.ntripIsConnected.value) {
controller.disconnectFromNtripServer();
} else {
controller.connectToNtripServer();
}
},
)),
),
Padding(
padding: const EdgeInsets.only(top: 10),
child: Center(
child: Obx(() => Text(
"Received ${controller.gpsReceivedData} byte(s) from GNSS device")))),
Padding(
padding: const EdgeInsets.only(top: 10),
child: Center(
child: Obx(() => Text(
"Received ${controller.ntripReceivedData} byte(s) from ntrip server ${controller.ntripDataPacketNumbers}")))),
Padding(
padding: const EdgeInsets.only(top: 10),
child: Center(
child: Obx(() => Text(
"GPS quality -> ${controller.getGpsQualityIndicator(quality: controller.gpsQuality.value)} ")))),
Padding(
padding: const EdgeInsets.only(top: 10),
child: Center(
child: Obx(() => Text(
"GpsDateTime -> ${controller.gpsDateTime} (UTC)")))),
Padding(
padding: const EdgeInsets.only(top: 10),
child: Center(
child: Obx(() => Text(
'Lat: ${controller.latDegree.value}°${controller.latMin.value.toString().padLeft(2, '0')}\'${controller.formatWgs84Sec.format(controller.latSec.value)}" - Long: ${controller.longDegree.value}°${controller.longMin.value.toString().padLeft(2, '0')}\'${controller.formatWgs84Sec.format(controller.longSec.value)}"')))),
Padding(
padding: const EdgeInsets.only(top: 10),
child: Center(
child: Obx(() => Text(
"EovX: ${controller.formatEov.format(controller.eov.value.Y)} - EovY: ${controller.formatEov.format(controller.eov.value.X)}")))),
Padding(
padding: const EdgeInsets.only(top: 10),
child: Center(
child: Obx(() => Text(
"Altitude -> ${controller.gpsAltitude} (m)")))),
Padding(
padding: const EdgeInsets.only(top: 10),
child: Center(
child: Obx(() => Text(
"Hor. error: ${max(controller.gpsLatitudeError.value, controller.gpsLongitudeError.value)} (m) - Vert. error: ${controller.gpsAltitudeError} (m)"))))
],
)));
}
}
@@ -0,0 +1,9 @@
import 'package:get/get.dart';
import 'package:terepi_seged/pages/socket_test/presentation/controllers/socket_test_controller.dart';
class SocketTestBinding extends Bindings {
@override
void dependencies() {
Get.lazyPut(() => SocketTestController());
}
}
@@ -0,0 +1,129 @@
import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'dart:typed_data';
import 'package:get/get.dart';
import 'package:google_sign_in/google_sign_in.dart';
class SocketTestController extends GetxController {
Socket? socket;
StreamSubscription? socketStreamSubscription;
RxString message = ''.obs;
final GoogleSignIn googleSignIn =
GoogleSignIn(scopes: ['https://www.googleapis.com/auth/drive.appdata']);
late GoogleSignInAccount? googleSignInAccount;
@override
void onInit() {
super.onInit();
//Loading, Success, Error handle with 1 line of code
message.value += "OnInit finished ....\n\n";
}
@override
void onClose() {
super.onClose();
disconnect();
print("SocketTestController onClose ....");
}
void googleLogIn() async {
googleSignInAccount = await googleSignIn.signIn();
final GoogleSignInAuthentication googleSignInAuthentication =
await googleSignInAccount!.authentication;
print("AccessToken: ${googleSignInAuthentication.accessToken}");
print("IdToken: ${googleSignInAuthentication.idToken}");
}
void connect() 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;
// socket?.encoding = ascii;
print("Connect ....");
message.value += "Connecting to caster .... \n\n";
// message.value += _toBase64("info@mail.app-dev.hu:") + "\r\n";
message.value += "${_toBase64("elgi08:Laszl0stef1")}\r\n";
// 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);
int length = data.length;
print('Server: $length');
},
// handle errors
onError: (error) {
print(error);
socket?.destroy();
},
// handle server ending connection
onDone: () {
print('Server left.');
socket?.destroy();
socket = null;
},
);
socket?.add(_convertStringToUint8List(header));
}
void disconnect() async {
if (socket != null) {
// socket?.close();
socketStreamSubscription?.cancel();
await socket?.flush();
socket?.close();
socket?.destroy();
socket = null;
print("Disconnect ....");
}
}
String _toBase64(String str) {
final bytes = ascii.encode(str);
final base64Str = base64.encode(bytes);
return base64Str;
}
Uint8List _convertStringToUint8List(String str) {
final List<int> codeUnits = str.codeUnits;
print("_convertStringToUint8List -> $codeUnits");
print("length codeunits -> ${codeUnits.length}");
print(
"_convertStringToUint8List uint8list -> ${Uint8List.fromList(codeUnits)}");
print(
"_convertStringToUint8List uint8list length -> ${Uint8List.fromList(codeUnits).length}");
final Uint8List unit8List = Uint8List.fromList(codeUnits);
return unit8List;
}
String _convertUint8ListToString(Uint8List uint8list) {
return String.fromCharCodes(uint8list);
}
}
@@ -0,0 +1,58 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:terepi_seged/pages/socket_test/presentation/controllers/socket_test_controller.dart';
class SocketTestView extends GetView<SocketTestController> {
const SocketTestView({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
extendBody: true,
backgroundColor: Colors.black.withOpacity(0.05),
appBar: AppBar(
elevation: 0.0,
title: const Text('Socket test (Ntrip caster)'),
leading: IconButton(
icon: const Icon(Icons.arrow_back_ios),
color: Colors.white,
onPressed: () {
Get.back();
},
),
),
body: Column(children: [
Column(
children: [
const Center(
child: Text("SocketTestView"),
),
TextButton(
onPressed: () async {
controller.googleLogIn();
},
child: const Text('Google log in ...')),
TextButton(
onPressed: () async {
print("Pressed connect ....");
controller.connect();
},
child: const Text('Connect to NTRIP caster')),
TextButton(
onPressed: () async {
controller.disconnect();
},
child: const Text('Disconnect'))
],
),
Expanded(
flex: 1,
child: SingleChildScrollView(
scrollDirection: Axis.vertical,
child: Obx(() => Text(
controller.message.value,
style: const TextStyle(color: Colors.white),
))))
]));
}
}
@@ -0,0 +1,9 @@
import 'package:get/get.dart';
import 'package:terepi_seged/pages/start/presentation/controllers/start_page_controller.dart';
class StartPageBinding extends Bindings {
@override
void dependencies() {
Get.put<StartPageController>(StartPageController());
}
}
@@ -0,0 +1,103 @@
import 'dart:developer';
import 'dart:io';
import 'package:get/get.dart';
import 'package:intl/intl.dart';
import 'package:path_provider/path_provider.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:terepi_seged/routes/app_pages.dart';
class StartPageController extends GetxController {
late PermissionStatus bluetoothStatus;
late Directory? applicationDocumentDirectory;
late Directory? applicationSupportDirectory;
late List<Directory>? externalCacheDirectories;
late Directory? externalStorageDirectory;
late Directory? temporaryDirectory;
late List<Directory>? externalStorageDirectoriesDocuments;
@override
void onInit() async {
applicationDocumentDirectory = await getApplicationDocumentsDirectory();
applicationSupportDirectory = await getApplicationSupportDirectory();
externalCacheDirectories = await getExternalCacheDirectories();
externalStorageDirectory = await getExternalStorageDirectory();
temporaryDirectory = await getTemporaryDirectory();
externalStorageDirectoriesDocuments =
await getExternalStorageDirectories(type: StorageDirectory.documents);
if (applicationDocumentDirectory != null) {
log("ApplicationDocumentsDirectory: ${applicationDocumentDirectory?.path}");
String pointsPath = '${applicationDocumentDirectory!.path}/Points/';
bool pointsPathIsExits = await Directory(pointsPath).exists();
if (!pointsPathIsExits) {
await Directory(pointsPath).create(recursive: true);
}
File dataFile = File("$pointsPath/data.txt");
DateTime now = DateTime.now();
String contents =
"Start: ${DateFormat('kk:mm:ss \n EEE d MMM').format(now)} \r\n";
await dataFile.writeAsString(contents, mode: FileMode.append);
log(contents);
} else {
log("ApplicationDocumentsDirectory: ---- NO ----}");
}
if (applicationSupportDirectory != null) {
log("applicationSupportDirectory: ${applicationSupportDirectory?.path}");
} else {
log("applicationSupportDirectory: ---- NO ----}");
}
if (externalCacheDirectories!.isNotEmpty) {
log("externalCacheDirectories: ${externalCacheDirectories!.length}");
for (var externalCacheDirectory in externalCacheDirectories!) {
log(" - externalCacheDirectories: ${externalCacheDirectory.path}");
}
} else {
log("externalCacheDirectories: ---- NO ----}");
}
if (externalStorageDirectory != null) {
print("externalStorageDirectory: ${externalStorageDirectory?.path}");
String pointsPath = '${externalStorageDirectory!.path}/Points/';
bool pointsPathIsExits = await Directory(pointsPath).exists();
if (!pointsPathIsExits) {
await Directory(pointsPath).create(recursive: true);
}
File dataFile = File("$pointsPath/data.txt");
DateTime now = DateTime.now();
String contents =
"Start: ${DateFormat('kk:mm:ss \n EEE d MMM').format(now)} \r\n";
await dataFile.writeAsString(contents, mode: FileMode.append);
print(contents);
} else {
log("externalStorageDirectory: ---- NO ----}");
}
if (temporaryDirectory != null) {
log("temporaryDirectory: ${temporaryDirectory?.path}");
} else {
log("temporaryDirectory: ---- NO ----}");
}
if (externalStorageDirectoriesDocuments!.isNotEmpty) {
log("externalStorageDirectoriesDocuments: ${externalStorageDirectoriesDocuments!.length}");
for (var externalStorageDirectoryDocuments
in externalStorageDirectoriesDocuments!) {
log(" - externalCacheDirectories: ${externalStorageDirectoryDocuments.path}");
}
} else {
log("externalStorageDirectoriesDocuments: ---- NO ----}");
}
super.onInit();
}
@override
void onReady() async {
super.onReady();
bluetoothStatus = await Permission.bluetooth.status;
_departStartPage();
}
void _departStartPage() async {
await Future.delayed(const Duration(seconds: 5));
Get.offAllNamed(Routes.HOME);
}
}
@@ -0,0 +1,44 @@
import 'package:animated_text_kit/animated_text_kit.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:terepi_seged/pages/start/presentation/controllers/start_page_controller.dart';
class StartPage extends GetView<StartPageController> {
const StartPage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white54,
body: Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text('Terepi',
style: TextStyle(
color: Colors.white,
fontSize: 32.0,
fontWeight: FontWeight.normal,
letterSpacing: 1.15)),
const SizedBox(
width: 8.0,
),
DefaultTextStyle(
style: const TextStyle(
color: Colors.white,
fontSize: 32,
fontWeight: FontWeight.normal,
letterSpacing: 1.15),
child: AnimatedTextKit(
animatedTexts: [
TypewriterAnimatedText('Segéd',
speed: const Duration(milliseconds: 350), cursor: '')
],
isRepeatingAnimation: false,
))
],
),
),
);
}
}