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.UNKNOWN.obs; RxList devices = RxList([]); Rx? selectedDevice; final NmeaDecoder nmeaDecoder = NmeaDecoder(); BluetoothConnection? connection; StreamSubscription? _bluetoothDiscoveryStream; RxList bluetoothDiscoveryResults = RxList.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 boundedDevices) { devices.value = boundedDevices; devices.refresh(); }); } void setSelectedDevice(BluetoothDevice device) { selectedDevice = Rx(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 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"); } } } } } }