GNSS eszközhöz való kapcsolódás és bluetooth kommunikáció refraktorálása külön osztályokba
This commit is contained in:
@@ -0,0 +1,111 @@
|
||||
// lib/services/gnss/ble_gnss_connection.dart
|
||||
import 'dart:async';
|
||||
import 'package:flutter_blue_plus/flutter_blue_plus.dart';
|
||||
import 'gnss_connection.dart';
|
||||
|
||||
// Nordic UART Service — a legelterjedtebb BLE UART profil
|
||||
const _nusServiceUuid = '6e400001-b5b3-f393-e0a9-e50e24dcca9e';
|
||||
const _nusTxCharUuid = '6e400003-b5b3-f393-e0a9-e50e24dcca9e'; // notify
|
||||
const _nusRxCharUuid = '6e400002-b5b3-f393-e0a9-e50e24dcca9e'; // write
|
||||
|
||||
class BleGnssConnection implements GnssConnection {
|
||||
@override
|
||||
GnssConnectionType get type => GnssConnectionType.ble;
|
||||
|
||||
final String serviceUuid;
|
||||
final String txCharUuid; // notify (eszköz → telefon)
|
||||
|
||||
BleGnssConnection({
|
||||
this.serviceUuid = _nusServiceUuid,
|
||||
this.txCharUuid = _nusTxCharUuid,
|
||||
});
|
||||
|
||||
BluetoothDevice? _device;
|
||||
StreamSubscription? _notifySub;
|
||||
String _lineBuffer = '';
|
||||
|
||||
final _nmeaController = StreamController<String>.broadcast();
|
||||
final _stateController = StreamController<GnssConnectionState>.broadcast();
|
||||
|
||||
@override
|
||||
Stream<String> get nmeaLines => _nmeaController.stream;
|
||||
|
||||
@override
|
||||
Stream<GnssConnectionState> get connectionState => _stateController.stream;
|
||||
|
||||
@override
|
||||
Future<void> connect(String address) async {
|
||||
_stateController.add(GnssConnectionState.connecting);
|
||||
|
||||
try {
|
||||
_device = BluetoothDevice.fromId(address);
|
||||
|
||||
await _device!.connect(
|
||||
timeout: const Duration(seconds: 10),
|
||||
autoConnect: false,
|
||||
license: License.free);
|
||||
|
||||
// Kapcsolat megszakadás figyelése
|
||||
_device!.connectionState.listen((state) {
|
||||
if (state == BluetoothConnectionState.disconnected) {
|
||||
_stateController.add(GnssConnectionState.disconnected);
|
||||
}
|
||||
});
|
||||
|
||||
// Service discovery
|
||||
final services = await _device!.discoverServices();
|
||||
final gnssService = services.firstWhere(
|
||||
(s) => s.serviceUuid.str.toLowerCase() == serviceUuid.toLowerCase(),
|
||||
orElse: () =>
|
||||
throw Exception('GNSS service nem található: $serviceUuid'),
|
||||
);
|
||||
|
||||
// TX karakterisztika (notify) — eszköztől jönnek az NMEA sorok
|
||||
final txChar = gnssService.characteristics.firstWhere(
|
||||
(c) =>
|
||||
c.characteristicUuid.str.toLowerCase() == txCharUuid.toLowerCase(),
|
||||
orElse: () => throw Exception('TX char nem található: $txCharUuid'),
|
||||
);
|
||||
|
||||
// Notify engedélyezése
|
||||
await txChar.setNotifyValue(true);
|
||||
|
||||
_notifySub = txChar.onValueReceived.listen(_onBleData);
|
||||
|
||||
_stateController.add(GnssConnectionState.connected);
|
||||
} catch (e) {
|
||||
_stateController.add(GnssConnectionState.error);
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
void _onBleData(List<int> bytes) {
|
||||
// BLE csomagok kis méretűek (≤20 byte MTU default),
|
||||
// az NMEA mondatokat össze kell fűzni
|
||||
final chunk = String.fromCharCodes(bytes);
|
||||
_lineBuffer += chunk;
|
||||
|
||||
// Teljes sorok kibocsátása
|
||||
while (_lineBuffer.contains('\n')) {
|
||||
final idx = _lineBuffer.indexOf('\n');
|
||||
final line = _lineBuffer.substring(0, idx).trim();
|
||||
_lineBuffer = _lineBuffer.substring(idx + 1);
|
||||
if (line.isNotEmpty) _nmeaController.add(line);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> disconnect() async {
|
||||
await _notifySub?.cancel();
|
||||
await _device?.disconnect();
|
||||
_stateController.add(GnssConnectionState.disconnected);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_notifySub?.cancel();
|
||||
_device?.disconnect();
|
||||
_nmeaController.close();
|
||||
_stateController.close();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user