import 'dart:async'; import 'dart:convert'; import 'dart:typed_data'; import 'package:flutter/material.dart'; import 'package:flutter_bluetooth_serial/flutter_bluetooth_serial.dart'; import 'package:fluttertoast/fluttertoast.dart'; import '../objects/cloud_service_api.dart'; class BluetoothObject { late int _rssi = -1; late BluetoothDevice _device; String _address = ""; String _name = ""; String id = ""; String _primaryThumbprint = ""; final String _secondaryThumbprint = ""; late BluetoothConnection? _connection; late Stream _connectionStream; late StreamSubscription _connectionStreamSubscription; final CloudServiceAPI _cloudServiceAPI = CloudServiceAPI(); //late Uint8List _messageBufferBits; late String _messageBufferChars = ""; bool _isDisconnecting = false; String get primaryThumbprint { return _primaryThumbprint; } String get secondaryThumbprint { return _secondaryThumbprint; } int get rssi { return _rssi; } String get name { return _name; } String get address { return _address; } BluetoothDevice get device { return _device; } BluetoothConnection? get connection { return _connection; } bool get isConnected { return (_connection == null ? false : true); } BluetoothObject(BluetoothDiscoveryResult result) { _rssi = result.rssi; _device = result.device; _address = _device.address; _name = _device.name ?? "device.name.UNKNOWN"; _connection = null; } Future bondDevice() async { try { bool bonded = false; if (_device.isBonded) { debugPrint('Unbonding from $_address...'); await FlutterBluetoothSerial.instance.removeDeviceBondWithAddress(_address); debugPrint('Unbonding from $_address has succed'); } else { debugPrint('Bonding with $_address...'); bonded = (await FlutterBluetoothSerial.instance.bondDeviceAtAddress(_address))!; debugPrint('Bonding with $_address has ${bonded ? 'succed' : 'failed'}.'); } /*setState(() { _discoveryResults[_discoveryResults.indexOf( result)] = BluetoothDiscoveryResult( device: BluetoothDevice( name: device.name ?? '', address: address, type: device.type, bondState: bonded ? BluetoothBondState.bonded : BluetoothBondState.none, ), rssi: result.rssi); });*/ } catch (ex) { /* showDialog( context: context, builder: (BuildContext context) { return AlertDialog( title: const Text( 'Error occured while bonding'), content: Text(ex.toString()), actions: [ TextButton( child: const Text("Close"), onPressed: () { Navigator.of(context).pop(); }, ), ], ); }, );*/ } } Future disconnectDevice() async { _isDisconnecting = true; if (_connection != null) { await _connection!.finish(); _connection = null; } _isDisconnecting = false; } Future connectDevice() async { if (isConnected) { await _connection!.finish(); _connection = null; } _connection = await BluetoothConnection.toAddress(_address); debugPrint("Connected to the device"); _connectionStream = _connection!.input!; _connectionStreamSubscription = _connectionStream.listen(_connectionOnListen); _connectionStreamSubscription.onDone(_connectionOnDone); } void _connectionOnDone() { if (_isDisconnecting) { debugPrint("Disconnecting locally!"); } else { debugPrint("Disconnected remotely!"); } } Future _connectionOnListen(Uint8List data) async { final String dataDecoded = const AsciiDecoder().convert(data); debugPrint("received: $data"); debugPrint("received decoded: $dataDecoded"); _messageBufferChars += dataDecoded; if (data[data.length - 1] == 10) { debugPrint("received buffer: $_messageBufferChars"); int spaceIndex = _messageBufferChars.indexOf(" "); String firstParameter = ""; String secondParameter = ""; try { firstParameter = _messageBufferChars.substring(0, spaceIndex); secondParameter = _messageBufferChars.substring(spaceIndex + 1, _messageBufferChars.length - 2); } catch (ex) { debugPrint(ex.toString()); } debugPrint("we still go on!"); _messageBufferChars = ""; debugPrint("first: $firstParameter"); debugPrint("second: $secondParameter"); if (firstParameter == "fingerprint") { debugPrint("received final buffer: $secondParameter"); _primaryThumbprint = secondParameter; debugPrint("{ _secondaryThumbprint: $_secondaryThumbprint }"); debugPrint("{ id: $id, _primaryThumbprint: $_primaryThumbprint, _secondaryThumbprint: $_secondaryThumbprint }"); await _registerDevice(); } } /* // Allocate buffer for parsed data int backspacesCounter = 0; 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) { _messageBuffer = dataString.substring(index); } else { _messageBuffer = (backspacesCounter > 0 ? _messageBuffer.substring(0, _messageBuffer.length - backspacesCounter) : _messageBuffer + dataString); } */ } Future sendData(String output) async { if (_connection == null) return; bool nameAvailable = await _cloudServiceAPI.checkNameAvailability(output); if (!nameAvailable) return; id = output; _connection!.output.add(Uint8List.fromList(const AsciiEncoder().convert("$output \r\n"))); await _connection!.output.allSent; debugPrint("sent: $output"); } Future _registerDevice() async { bool registered = false; registered = await _cloudServiceAPI.createDevice(id, _primaryThumbprint, ""); String statusText = registered ? "das Gerät wurde erfolgreich registriert" : "das Gerät konnte nicht registriert werden"; Fluttertoast.showToast( msg: statusText, toastLength: Toast.LENGTH_SHORT, gravity: ToastGravity.BOTTOM, timeInSecForIosWeb: 2, backgroundColor: Colors.grey[200], textColor: Colors.black, fontSize: 16.0); } } /*setState(() { _discoveryResults[_discoveryResults.indexOf( result)] = BluetoothDiscoveryResult( device: BluetoothDevice( name: device.name ?? '', address: address, type: device.type, isConnected: connected, ), rssi: result.rssi); }); */