2026-05-17 15:04:48 +02:00
|
|
|
// lib/services/gnss/phone_gps_connection.dart
|
|
|
|
|
import 'dart:async';
|
|
|
|
|
import 'dart:typed_data';
|
|
|
|
|
import 'package:geolocator/geolocator.dart';
|
|
|
|
|
import 'gnss_connection.dart';
|
|
|
|
|
import 'gnss_device_service.dart';
|
|
|
|
|
|
|
|
|
|
class PhoneGpsConnection implements GnssConnection {
|
|
|
|
|
@override
|
|
|
|
|
GnssConnectionType get type => GnssConnectionType.phoneGps;
|
|
|
|
|
|
|
|
|
|
final _stateController = StreamController<GnssConnectionState>.broadcast();
|
|
|
|
|
final _positionController = StreamController<Position>.broadcast();
|
|
|
|
|
StreamSubscription<Position>? _positionSub;
|
|
|
|
|
|
2026-07-12 02:14:49 +02:00
|
|
|
int _retryCount = 0;
|
|
|
|
|
static const _maxRetries = 5;
|
|
|
|
|
Timer? _retryTimer;
|
|
|
|
|
|
2026-05-17 15:04:48 +02:00
|
|
|
@override
|
|
|
|
|
Stream<String> get nmeaLines => const Stream.empty(); // Nincs NMEA
|
|
|
|
|
|
|
|
|
|
@override
|
|
|
|
|
Stream<Position> get positionStream => _positionController.stream;
|
|
|
|
|
|
|
|
|
|
@override
|
|
|
|
|
Stream<GnssConnectionState> get connectionState => _stateController.stream;
|
|
|
|
|
|
|
|
|
|
@override
|
|
|
|
|
Future<void> connect(String address) async {
|
|
|
|
|
_stateController.add(GnssConnectionState.connecting);
|
|
|
|
|
|
|
|
|
|
bool serviceEnabled = await Geolocator.isLocationServiceEnabled();
|
|
|
|
|
if (!serviceEnabled) {
|
|
|
|
|
_stateController.add(GnssConnectionState.error);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LocationPermission permission = await Geolocator.checkPermission();
|
|
|
|
|
if (permission == LocationPermission.denied) {
|
|
|
|
|
permission = await Geolocator.requestPermission();
|
|
|
|
|
if (permission == LocationPermission.denied) {
|
|
|
|
|
_stateController.add(GnssConnectionState.error);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_stateController.add(GnssConnectionState.connected);
|
2026-07-12 02:14:49 +02:00
|
|
|
_retryCount = 0;
|
|
|
|
|
await _startPositionStream();
|
|
|
|
|
}
|
2026-05-17 15:04:48 +02:00
|
|
|
|
2026-07-12 02:14:49 +02:00
|
|
|
Future<void> _startPositionStream() async {
|
|
|
|
|
await _positionSub?.cancel();
|
2026-05-17 15:04:48 +02:00
|
|
|
_positionSub = Geolocator.getPositionStream(
|
|
|
|
|
locationSettings: const LocationSettings(
|
|
|
|
|
accuracy: LocationAccuracy.high,
|
|
|
|
|
distanceFilter: 0, // Folyamatos frissítés
|
|
|
|
|
),
|
2026-07-12 02:14:49 +02:00
|
|
|
).listen(
|
|
|
|
|
(Position pos) {
|
|
|
|
|
_retryCount = 0;
|
|
|
|
|
_positionController.add(pos);
|
|
|
|
|
},
|
|
|
|
|
onError: _handleStreamError,
|
|
|
|
|
onDone: () =>
|
|
|
|
|
_handleStreamError(Exception('A GPS-stream váratlanul lezárult.')),
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// A Geolocator stream NEM öngyógyuló — lásd a PhoneGpsSource-nál már
|
|
|
|
|
/// javított, ugyanilyen hibát. Ez a kapcsolat idáig SEMMILYEN hiba
|
|
|
|
|
/// esetén nem próbálkozott újra, csendben, véglegesen elhallgatott.
|
|
|
|
|
void _handleStreamError(Object e) {
|
|
|
|
|
_retryCount++;
|
|
|
|
|
if (_retryCount > _maxRetries) {
|
|
|
|
|
_stateController.add(GnssConnectionState.error);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
_retryTimer?.cancel();
|
|
|
|
|
_retryTimer = Timer(const Duration(seconds: 1), _startPositionStream);
|
2026-05-17 15:04:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@override
|
|
|
|
|
Future<void> disconnect() async {
|
2026-07-12 02:14:49 +02:00
|
|
|
_retryTimer?.cancel();
|
2026-05-17 15:04:48 +02:00
|
|
|
await _positionSub?.cancel();
|
|
|
|
|
_stateController.add(GnssConnectionState.disconnected);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@override
|
|
|
|
|
void sendData(Uint8List data) {
|
|
|
|
|
// A telefon beépített GPS-e nem fogad RTCM adatokat
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@override
|
|
|
|
|
void dispose() {
|
2026-07-12 02:14:49 +02:00
|
|
|
_retryTimer?.cancel();
|
2026-05-17 15:04:48 +02:00
|
|
|
_positionSub?.cancel();
|
|
|
|
|
_positionController.close();
|
|
|
|
|
_stateController.close();
|
|
|
|
|
}
|
|
|
|
|
}
|