198 lines
5.4 KiB
Dart
198 lines
5.4 KiB
Dart
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<Uint8List> _connectionStream;
|
|
late StreamSubscription<Uint8List> _connectionStreamSubscription;
|
|
late BuildContext _context;
|
|
|
|
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<void> bondDevice(BuildContext context) 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'}.');
|
|
}
|
|
} catch (ex) {
|
|
showDialog(
|
|
context: context,
|
|
builder: (BuildContext context) {
|
|
return AlertDialog(
|
|
title: const Text(
|
|
'Error occured while bonding'),
|
|
content: Text(ex.toString()),
|
|
actions: <Widget>[
|
|
TextButton(
|
|
child: const Text("Close"),
|
|
onPressed: () {
|
|
Navigator.of(context).pop();
|
|
},
|
|
),
|
|
],
|
|
);
|
|
},
|
|
);
|
|
}
|
|
}
|
|
|
|
Future<void> disconnectDevice() async {
|
|
_isDisconnecting = true;
|
|
if (_connection != null) {
|
|
await _connection!.finish();
|
|
_connection = null;
|
|
}
|
|
_isDisconnecting = false;
|
|
}
|
|
|
|
Future<void> connectDevice() async {
|
|
if (isConnected) {
|
|
await _connection!.finish();
|
|
_connection = null;
|
|
}
|
|
|
|
try {
|
|
_connection = await BluetoothConnection.toAddress(_address);
|
|
debugPrint("Connected to the device");
|
|
_connectionStream = _connection!.input!;
|
|
_connectionStreamSubscription = _connectionStream.listen(_connectionOnListen);
|
|
_connectionStreamSubscription.onDone(_connectionOnDone);
|
|
} catch (ex) {
|
|
debugPrint("$ex");
|
|
}
|
|
}
|
|
|
|
void _connectionOnDone() {
|
|
if (_isDisconnecting) {
|
|
debugPrint("Disconnecting locally!");
|
|
} else {
|
|
debugPrint("Disconnected remotely!");
|
|
}
|
|
}
|
|
|
|
Future<void> _connectionOnListen(Uint8List data) async {
|
|
final String dataDecoded = const AsciiDecoder().convert(data);
|
|
debugPrint("received decoded: $dataDecoded");
|
|
_messageBufferChars += dataDecoded;
|
|
|
|
if (!(data[data.length - 1] == 10)) {
|
|
return;
|
|
}
|
|
if (!_messageBufferChars.contains(" ")) {
|
|
_messageBufferChars = "";
|
|
return;
|
|
}
|
|
|
|
List<String> input = _messageBufferChars.split(" ");
|
|
if (input[0] == "fingerprint") {
|
|
_primaryThumbprint = input[1].trim();
|
|
debugPrint("_primaryThumbprint: ${const AsciiEncoder().convert(_primaryThumbprint)}");
|
|
debugPrint("id: ${const AsciiEncoder().convert(id)}");
|
|
debugPrint("_secondaryThumbprint: $_secondaryThumbprint");
|
|
await _registerDevice();
|
|
}
|
|
_messageBufferChars = "";
|
|
}
|
|
|
|
Future<void> sendData(BuildContext context, 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;
|
|
_context = context;
|
|
debugPrint("sent: $output");
|
|
}
|
|
|
|
Future<void> _registerDevice() async {
|
|
bool registered = false;
|
|
registered = await _cloudServiceAPI.createDevice(id, _primaryThumbprint, "");
|
|
_confirmRegistration(registered);
|
|
}
|
|
|
|
void _confirmRegistration(bool registered) {
|
|
showDialog<String>(
|
|
context: _context,
|
|
builder: (BuildContext context) => AlertDialog(
|
|
title: const Text('Device Info'),
|
|
content: Text(registered ? "das Gerät wurde erfolgreich registriert" : "das Gerät konnte nicht registriert werden"),
|
|
backgroundColor: Colors.white,
|
|
actions: <Widget>[
|
|
TextButton(onPressed: () => Navigator.pop(context, 'Cancel'),
|
|
child: const Text('OK'),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
}
|