GNSS minőség adatok kijelzése (pod-ok)
This commit is contained in:
parent
b85cdb2596
commit
8b4c25f475
@ -2,6 +2,7 @@ import 'dart:async';
|
|||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
import 'dart:math';
|
import 'dart:math';
|
||||||
|
import 'dart:math' as math;
|
||||||
|
|
||||||
import 'package:file_picker/file_picker.dart';
|
import 'package:file_picker/file_picker.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
@ -65,10 +66,16 @@ class MapSurveyController extends GetxController {
|
|||||||
Rx<DateTime> get gpsDateTime => _gnss.gpsDateTime;
|
Rx<DateTime> get gpsDateTime => _gnss.gpsDateTime;
|
||||||
bool get gpsIsConnected =>
|
bool get gpsIsConnected =>
|
||||||
_gnss.connectionState.value == GnssConnectionState.connected;
|
_gnss.connectionState.value == GnssConnectionState.connected;
|
||||||
|
double? get horizontalAccuracy => _gnss.horizontalAccuracy;
|
||||||
|
|
||||||
|
RxDouble get pdop => _gnss.pdop;
|
||||||
|
RxDouble get hdop => _gnss.hdop;
|
||||||
|
RxDouble get vdop => _gnss.vdop;
|
||||||
|
|
||||||
final wgs84CoordinateFormat = Wgs84CoordinateFormat.decimalDegrees.obs;
|
final wgs84CoordinateFormat = Wgs84CoordinateFormat.decimalDegrees.obs;
|
||||||
final showWgs84Card = true.obs;
|
final showWgs84Card = true.obs;
|
||||||
final showEovCard = true.obs;
|
final showEovCard = true.obs;
|
||||||
|
final showGnssQualityCard = true.obs;
|
||||||
|
|
||||||
// NTRIP állapot
|
// NTRIP állapot
|
||||||
RxBool get ntripIsConnected => _ntrip.isConnected;
|
RxBool get ntripIsConnected => _ntrip.isConnected;
|
||||||
@ -799,6 +806,10 @@ class MapSurveyController extends GetxController {
|
|||||||
showEovCard.value = !showEovCard.value;
|
showEovCard.value = !showEovCard.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void toggleShowGnssQualityCard() {
|
||||||
|
showGnssQualityCard.value = !showGnssQualityCard.value;
|
||||||
|
}
|
||||||
|
|
||||||
String get latitudeText {
|
String get latitudeText {
|
||||||
return Wgs84CoordinateFormatter.formatLatitude(
|
return Wgs84CoordinateFormatter.formatLatitude(
|
||||||
gpsLatitude.value, wgs84CoordinateFormat.value);
|
gpsLatitude.value, wgs84CoordinateFormat.value);
|
||||||
@ -808,4 +819,28 @@ class MapSurveyController extends GetxController {
|
|||||||
return Wgs84CoordinateFormatter.formatLongitude(
|
return Wgs84CoordinateFormatter.formatLongitude(
|
||||||
gpsLongitude.value, wgs84CoordinateFormat.value);
|
gpsLongitude.value, wgs84CoordinateFormat.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String formatDop(double? value) {
|
||||||
|
if (value == null || value.isNaN || value.isInfinite) {
|
||||||
|
return '-';
|
||||||
|
}
|
||||||
|
|
||||||
|
return value.toStringAsFixed(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
String formatMeterCompact(double? value) {
|
||||||
|
if (value == null || value.isNaN || value.isInfinite) {
|
||||||
|
return '-';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value < 1.0) {
|
||||||
|
return '${value.toStringAsFixed(3)}m';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value < 10.0) {
|
||||||
|
return '${value.toStringAsFixed(2)}m';
|
||||||
|
}
|
||||||
|
|
||||||
|
return '${value.toStringAsFixed(1)}m';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -39,7 +39,7 @@ class MapSurveyView extends GetView<MapSurveyController> {
|
|||||||
),
|
),
|
||||||
|
|
||||||
Positioned(
|
Positioned(
|
||||||
top: 300,
|
top: 390,
|
||||||
right: 60,
|
right: 60,
|
||||||
left: 8,
|
left: 8,
|
||||||
child: CoordinatePanel(
|
child: CoordinatePanel(
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
import 'dart:math';
|
||||||
import 'dart:typed_data';
|
import 'dart:typed_data';
|
||||||
|
|
||||||
import 'package:geolocator/geolocator.dart';
|
import 'package:geolocator/geolocator.dart';
|
||||||
@ -93,6 +94,13 @@ class GnssService extends GetxService {
|
|||||||
return activeSatelliteKeys.contains(sat.satelliteKey);
|
return activeSatelliteKeys.contains(sat.satelliteKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double? get horizontalAccuracy {
|
||||||
|
final lat = latitudeError.value;
|
||||||
|
final lon = longitudeError.value;
|
||||||
|
|
||||||
|
return sqrt(lat * lat + lon * lon);
|
||||||
|
}
|
||||||
|
|
||||||
// ── Belső ─────────────────────────────────────────────────────────
|
// ── Belső ─────────────────────────────────────────────────────────
|
||||||
final NmeaDecoder _decoder = NmeaDecoder();
|
final NmeaDecoder _decoder = NmeaDecoder();
|
||||||
StreamSubscription? _nmeaSub;
|
StreamSubscription? _nmeaSub;
|
||||||
|
|||||||
204
lib/widgets/gnss_quality_card.dart
Normal file
204
lib/widgets/gnss_quality_card.dart
Normal file
@ -0,0 +1,204 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:get/get.dart';
|
||||||
|
import 'package:terepi_seged/pages/map_survey/presentations/controllers/map_survey_controller.dart';
|
||||||
|
|
||||||
|
import 'map_info_card.dart';
|
||||||
|
import 'quality_mini_value.dart';
|
||||||
|
|
||||||
|
class GnssQualityCard extends StatelessWidget {
|
||||||
|
final MapSurveyController controller;
|
||||||
|
|
||||||
|
const GnssQualityCard({
|
||||||
|
super.key,
|
||||||
|
required this.controller,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Obx(() {
|
||||||
|
final hError = controller.horizontalAccuracy;
|
||||||
|
final vError = controller.gpsAltitudeError.value;
|
||||||
|
|
||||||
|
return MapInfoCard(
|
||||||
|
onClose: controller.toggleShowGnssQualityCard,
|
||||||
|
title: Row(
|
||||||
|
children: [
|
||||||
|
const Icon(Icons.speed, size: 18),
|
||||||
|
const SizedBox(width: 6),
|
||||||
|
Text(
|
||||||
|
'Minőség',
|
||||||
|
style: Theme.of(context).textTheme.titleSmall?.copyWith(
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: QualityMiniValue(
|
||||||
|
label: 'PDOP',
|
||||||
|
value: controller.formatDop(controller.pdop.value),
|
||||||
|
color: qualityColorForDop(
|
||||||
|
context,
|
||||||
|
controller.pdop.value,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: QualityMiniValue(
|
||||||
|
label: 'HDOP',
|
||||||
|
value: controller.formatDop(controller.hdop.value),
|
||||||
|
color: qualityColorForDop(
|
||||||
|
context,
|
||||||
|
controller.hdop.value,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: QualityMiniValue(
|
||||||
|
label: 'VDOP',
|
||||||
|
value: controller.formatDop(controller.vdop.value),
|
||||||
|
color: qualityColorForDop(
|
||||||
|
context,
|
||||||
|
controller.vdop.value,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const SizedBox(height: 3),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: QualityMiniValue(
|
||||||
|
label: 'Latσ',
|
||||||
|
value: controller.formatMeterCompact(
|
||||||
|
controller.gpsLatitudeError.value,
|
||||||
|
),
|
||||||
|
color: qualityColorForHorizontalError(
|
||||||
|
context,
|
||||||
|
controller.gpsLatitudeError.value,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: QualityMiniValue(
|
||||||
|
label: 'Lonσ',
|
||||||
|
value: controller.formatMeterCompact(
|
||||||
|
controller.gpsLongitudeError.value,
|
||||||
|
),
|
||||||
|
color: qualityColorForHorizontalError(
|
||||||
|
context,
|
||||||
|
controller.gpsLongitudeError.value,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: QualityMiniValue(
|
||||||
|
label: 'H',
|
||||||
|
value: controller.formatMeterCompact(hError),
|
||||||
|
color: qualityColorForHorizontalError(
|
||||||
|
context,
|
||||||
|
hError,
|
||||||
|
),
|
||||||
|
emphasized: true,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: QualityMiniValue(
|
||||||
|
label: 'V',
|
||||||
|
value: controller.formatMeterCompact(vError),
|
||||||
|
color: qualityColorForVerticalError(
|
||||||
|
context,
|
||||||
|
vError,
|
||||||
|
),
|
||||||
|
emphasized: true,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Color qualityColorForDop(
|
||||||
|
BuildContext context,
|
||||||
|
double? value,
|
||||||
|
) {
|
||||||
|
final colorScheme = Theme.of(context).colorScheme;
|
||||||
|
|
||||||
|
if (value == null || value.isNaN || value.isInfinite) {
|
||||||
|
return colorScheme.onSurface.withOpacity(0.45);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value <= 1.0) {
|
||||||
|
return Colors.green.shade700;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value <= 2.0) {
|
||||||
|
return Colors.lightGreen.shade700;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value <= 5.0) {
|
||||||
|
return Colors.orange.shade800;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Colors.red.shade700;
|
||||||
|
}
|
||||||
|
|
||||||
|
Color qualityColorForHorizontalError(
|
||||||
|
BuildContext context,
|
||||||
|
double? value,
|
||||||
|
) {
|
||||||
|
final colorScheme = Theme.of(context).colorScheme;
|
||||||
|
|
||||||
|
if (value == null || value.isNaN || value.isInfinite) {
|
||||||
|
return colorScheme.onSurface.withOpacity(0.45);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value <= 0.03) {
|
||||||
|
return Colors.green.shade700;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value <= 0.10) {
|
||||||
|
return Colors.lightGreen.shade700;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value <= 0.50) {
|
||||||
|
return Colors.orange.shade800;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Colors.red.shade700;
|
||||||
|
}
|
||||||
|
|
||||||
|
Color qualityColorForVerticalError(
|
||||||
|
BuildContext context,
|
||||||
|
double? value,
|
||||||
|
) {
|
||||||
|
final colorScheme = Theme.of(context).colorScheme;
|
||||||
|
|
||||||
|
if (value == null || value.isNaN || value.isInfinite) {
|
||||||
|
return colorScheme.onSurface.withOpacity(0.45);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value <= 0.05) {
|
||||||
|
return Colors.green.shade700;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value <= 0.15) {
|
||||||
|
return Colors.lightGreen.shade700;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value <= 0.75) {
|
||||||
|
return Colors.orange.shade800;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Colors.red.shade700;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -45,7 +45,7 @@ class MapInfoCard extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(height: 6),
|
const SizedBox(height: 1),
|
||||||
child,
|
child,
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:terepi_seged/pages/map_survey/presentations/controllers/map_survey_controller.dart';
|
import 'package:terepi_seged/pages/map_survey/presentations/controllers/map_survey_controller.dart';
|
||||||
|
import 'package:terepi_seged/widgets/gnss_quality_card.dart';
|
||||||
import 'package:terepi_seged/widgets/wgs84_coordinate_card.dart';
|
import 'package:terepi_seged/widgets/wgs84_coordinate_card.dart';
|
||||||
|
|
||||||
import 'eov_coordinate_card.dart';
|
import 'eov_coordinate_card.dart';
|
||||||
@ -27,6 +28,9 @@ class MapInfoCardColumn extends StatelessWidget {
|
|||||||
if (controller.showEovCard.value) {
|
if (controller.showEovCard.value) {
|
||||||
cards.add(EovCoordinateCard(controller: controller));
|
cards.add(EovCoordinateCard(controller: controller));
|
||||||
}
|
}
|
||||||
|
if (controller.showGnssQualityCard.value) {
|
||||||
|
cards.add(GnssQualityCard(controller: controller));
|
||||||
|
}
|
||||||
|
|
||||||
if (cards.isEmpty) {
|
if (cards.isEmpty) {
|
||||||
return const SizedBox.shrink();
|
return const SizedBox.shrink();
|
||||||
@ -41,7 +45,7 @@ class MapInfoCardColumn extends StatelessWidget {
|
|||||||
children: [
|
children: [
|
||||||
for (var i = 0; i < cards.length; i++) ...[
|
for (var i = 0; i < cards.length; i++) ...[
|
||||||
cards[i],
|
cards[i],
|
||||||
if (i != cards.length - 1) const SizedBox(height: 8)
|
if (i != cards.length - 1) const SizedBox(height: 4)
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|||||||
50
lib/widgets/quality_mini_value.dart
Normal file
50
lib/widgets/quality_mini_value.dart
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class QualityMiniValue extends StatelessWidget {
|
||||||
|
final String label;
|
||||||
|
final String value;
|
||||||
|
final Color color;
|
||||||
|
final bool emphasized;
|
||||||
|
|
||||||
|
const QualityMiniValue({
|
||||||
|
required this.label,
|
||||||
|
required this.value,
|
||||||
|
required this.color,
|
||||||
|
this.emphasized = false,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final colorScheme = Theme.of(context).colorScheme;
|
||||||
|
|
||||||
|
return Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
label,
|
||||||
|
maxLines: 1,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
style: Theme.of(context).textTheme.labelSmall?.copyWith(
|
||||||
|
color: colorScheme.onSurface.withOpacity(0.65),
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
height: 1.0,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 2),
|
||||||
|
Text(
|
||||||
|
value,
|
||||||
|
maxLines: 1,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
style: Theme.of(context).textTheme.bodySmall?.copyWith(
|
||||||
|
color: color,
|
||||||
|
fontWeight: emphasized ? FontWeight.w800 : FontWeight.w700,
|
||||||
|
height: 1.05,
|
||||||
|
fontFeatures: const [
|
||||||
|
FontFeature.tabularFigures(),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -39,7 +39,7 @@ class Wgs84CoordinateCard extends StatelessWidget {
|
|||||||
label: 'Lat',
|
label: 'Lat',
|
||||||
value: controller.latitudeText,
|
value: controller.latitudeText,
|
||||||
),
|
),
|
||||||
const SizedBox(height: 4),
|
const SizedBox(height: 1),
|
||||||
CoordinateRow(
|
CoordinateRow(
|
||||||
label: 'Lon',
|
label: 'Lon',
|
||||||
value: controller.longitudeText,
|
value: controller.longitudeText,
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user