Navigációs térkép és útvoanlrögzítés hibáinak javítása

This commit is contained in:
2026-07-15 04:21:30 +02:00
parent 204d848ba4
commit 4660873350
4 changed files with 276 additions and 48 deletions
@@ -9,7 +9,10 @@ import 'package:terepi_seged/models/source_point.dart';
import 'package:terepi_seged/models/vechicle_position_log.dart';
import 'package:terepi_seged/services/app_database.dart';
import 'package:terepi_seged/services/coord_converter_service.dart';
import 'package:terepi_seged/services/gnss/gnss_connection.dart';
import 'package:terepi_seged/services/gnss/gnss_device_service.dart';
import 'package:terepi_seged/services/gnss/gnss_service.dart';
import 'package:terepi_seged/services/layer_import_service.dart';
import 'package:terepi_seged/services/project_service.dart';
import 'package:terepi_seged/services/sps_import_service.dart';
import 'package:terepi_seged/services/vechicle_identity_service.dart';
@@ -27,50 +30,80 @@ class VibroNavView extends GetView<VibroNavController> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Vibrátor navigáció'),
actions: [
IconButton(
icon: const Icon(Icons.upload_file),
tooltip: 'Forráspontok importja (SPS S-fájl)',
onPressed: _importSourcePoints,
),
IconButton(
icon: const Icon(Icons.local_shipping_outlined),
tooltip: 'Jármű kiválasztása',
onPressed: _pickVehicle,
),
],
),
body: Stack(
children: [
_buildMap(),
Obx(() {
final target =
controller.hasPosition.value && Get.isRegistered<GnssService>()
appBar: AppBar(
title: const Text('Navigáció'),
actions: [
IconButton(
icon: const Icon(Icons.bluetooth_connected),
tooltip: "Gyors újracsatlakozás a GNSS vevőhöz",
onPressed: _quickReconnectGnss,
),
IconButton(
icon: const Icon(Icons.layers_outlined),
tooltip: 'Réteg importja (GeoJSON/KML/KMZ)',
onPressed: _importLayer,
),
IconButton(
icon: const Icon(Icons.upload_file),
tooltip: 'Forráspontok importja (SPS S-fájl)',
onPressed: _importSourcePoints,
),
IconButton(
icon: const Icon(Icons.local_shipping_outlined),
tooltip: 'Jármű kiválasztása',
onPressed: _pickVehicle,
),
],
),
body: Obx(() {
if (!controller.mapReady.value) {
return const Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
CircularProgressIndicator(),
SizedBox(height: 12),
Text('Pozíció lekérése…'),
],
),
);
}
return Stack(
children: [
_buildMap(),
Builder(builder: (context) {
final target = controller.hasPosition.value &&
Get.isRegistered<GnssService>()
? LatLng(GnssService.to.latitude.value,
GnssService.to.longitude.value)
: null;
return AnimatedMapFollow(
mapController: controller.mapController,
target: target,
heading: controller.travelHeading.value);
}),
Positioned(
left: 8,
right: 8,
top: 8,
child: _VehicleBadge(),
),
Positioned(
left: 8,
right: 8,
bottom: 8,
child: _NavPanel(controller: controller),
),
],
),
);
return AnimatedMapFollow(
mapController: controller.mapController,
target: target,
heading: controller.travelHeading.value,
);
}),
Positioned(
left: 8,
right: 8,
top: 8,
child: Row(
children: [
Expanded(child: _VehicleBadge()),
const SizedBox(width: 8),
const _GnssStatusBadge(),
],
),
),
Positioned(
left: 8,
right: 8,
bottom: 8,
child: _NavPanel(controller: controller),
),
],
);
}));
}
Widget _buildMap() {
@@ -78,10 +111,17 @@ class VibroNavView extends GetView<VibroNavController> {
final points = controller.sourcePoints;
final nearest = controller.nearestPoint.value;
final gnssPos =
Get.isRegistered<GnssService>() && GnssService.to.latitude.value != 0
? LatLng(
GnssService.to.latitude.value, GnssService.to.longitude.value)
: null;
final center = gnssPos ?? const LatLng(47.5, 19.05);
return FlutterMap(
mapController: controller.mapController,
options: const MapOptions(
initialCenter: LatLng(47.5, 19.05),
options: MapOptions(
initialCenter: center,
initialZoom: 15,
),
children: [
@@ -147,6 +187,38 @@ class VibroNavView extends GetView<VibroNavController> {
}
}
Future<void> _quickReconnectGnss() async {
final device = GnssDeviceService.to.selectedDevice.value;
if (device == null) {
Get.snackbar(
'Nincs korábbi GNSS-eszköz',
'Előbb válassz ki egyet a Kitűzés/Mérés beállításaiban.',
snackPosition: SnackPosition.BOTTOM,
);
return;
}
Get.snackbar(
'Újracsatlakozás',
'${device.name}" (${device.typeLabel}) — folyamatban…',
snackPosition: SnackPosition.BOTTOM,
duration: const Duration(seconds: 2),
);
await GnssService.to.reconnect();
}
Future<void> _importLayer() async {
try {
final layer = await LayerImportService.to.importFile();
if (layer != null) {
Get.snackbar('Réteg importálva', layer.name,
snackPosition: SnackPosition.BOTTOM);
}
} catch (e) {
Get.snackbar('Import hiba', e.toString(),
snackPosition: SnackPosition.BOTTOM);
}
}
// ── SPS S-fájl (forráspont) import — kompakt, egyetlen dialógus ────
Future<void> _importSourcePoints() async {
@@ -419,3 +491,59 @@ class _VehicleMarker extends StatelessWidget {
);
}
}
class _GnssStatusBadge extends StatelessWidget {
const _GnssStatusBadge();
@override
Widget build(BuildContext context) {
if (!Get.isRegistered<GnssService>()) return const SizedBox.shrink();
return Obx(() {
final gnss = GnssService.to;
final state = gnss.connectionState.value;
final quality = gnss.gpsQuality.value;
Color color;
IconData icon;
String label;
if (state == GnssConnectionState.connected && quality > 0) {
color = Colors.green;
icon = Icons.gps_fixed;
label = quality >= 4 ? 'RTK fix' : (quality == 2 ? 'RTK float' : 'GPS');
} else if (state == GnssConnectionState.connected) {
color = Colors.orange;
icon = Icons.gps_not_fixed;
label = 'Nincs fix';
} else if (state == GnssConnectionState.connecting) {
color = Colors.orange;
icon = Icons.gps_not_fixed;
label = 'Csatlakozás…';
} else {
color = Colors.red;
icon = Icons.gps_off;
label = 'Nincs GNSS';
}
return Container(
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
decoration: BoxDecoration(
color: color.withOpacity(0.15),
borderRadius: BorderRadius.circular(6),
border: Border.all(color: color, width: 1),
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(icon, size: 14, color: color),
const SizedBox(width: 4),
Text(label,
style: TextStyle(
fontSize: 11, fontWeight: FontWeight.w600, color: color)),
],
),
);
});
}
}