370 lines
14 KiB
Dart
370 lines
14 KiB
Dart
import 'dart:async';
|
|
|
|
import 'package:flutter_easyloading/flutter_easyloading.dart';
|
|
import 'package:flutter_reactive_ble/flutter_reactive_ble.dart';
|
|
import 'package:get/get.dart';
|
|
|
|
import 'io_tool/io_model.dart';
|
|
import 'io_tool/io_tool.dart';
|
|
import 'io_tool/manager_event_bus.dart';
|
|
import 'reciver_data.dart';
|
|
|
|
//连接状态回调
|
|
typedef ConnectStateCallBack = Function(DeviceConnectionState connectionState);
|
|
|
|
class BlueManage {
|
|
FlutterReactiveBle? _flutterReactiveBle;
|
|
final List<DiscoveredDevice> scanDevices = [];
|
|
|
|
// 用来写入的服务id
|
|
final Uuid _serviceIdConnect = Uuid.parse("fff0");
|
|
// 用来写入的服务id
|
|
final Uuid _serviceIdWrite = Uuid.parse('0000FFF0-0000-1000-8000-00805F9B34FB');
|
|
// 用来订阅的特征id
|
|
final Uuid _characteristicIdSubscription = Uuid.parse("fff1");
|
|
// 用来写入的特征id
|
|
final Uuid _characteristicIdWrite = Uuid.parse("fff2");
|
|
|
|
// 监听发送事件
|
|
StreamSubscription<EventSendModel>? _sendStreamSubscription;
|
|
// 监听蓝牙扫描的事件
|
|
StreamSubscription? _scanSubscription;
|
|
// 监听蓝牙连接的事件
|
|
StreamSubscription<dynamic>? _currentConnectionStream;
|
|
|
|
// 当前连接设备的名字
|
|
String connectDeviceName = "";
|
|
// 当前连接设备的mac地址
|
|
String connectDeviceMacAddress = "";
|
|
// 监听蓝牙连接状态
|
|
DeviceConnectionState? deviceConnectionState = DeviceConnectionState.disconnected;
|
|
|
|
static BlueManage? _manager;
|
|
BlueManage._init();
|
|
|
|
static BlueManage? shareManager() {
|
|
_manager ??= BlueManage._init();
|
|
_manager!._initBlue();
|
|
return _manager;
|
|
}
|
|
|
|
factory BlueManage() => shareManager()!;
|
|
BlueManage? get manager => shareManager();
|
|
|
|
void _initBlue(){
|
|
// print("蓝牙功能初始化了");
|
|
_flutterReactiveBle ??= FlutterReactiveBle();
|
|
_initSendStreamSubscription();
|
|
}
|
|
|
|
void _initSendStreamSubscription() {
|
|
_sendStreamSubscription ??= EventBusManager().eventBus!.on<EventSendModel>().listen((EventSendModel model) {
|
|
if (model.sendChannel == DataChannel.ble) {
|
|
// managerAppWriteData(model.data);
|
|
_flutterReactiveBle!.statusStream.listen((status) {
|
|
if (status == BleStatus.ready) {
|
|
// 蓝牙已开启,可以进行蓝牙操作
|
|
writeCharacteristicWithResponse(model.data);
|
|
}else{
|
|
Get.log("写入数据 蓝牙未开启,不能进行蓝牙操作");
|
|
}
|
|
});
|
|
}
|
|
});
|
|
}
|
|
|
|
/// 开始扫描蓝牙设备
|
|
void startScan({List<Uuid>? idList}) {
|
|
// List<Service>? list = _flutterReactiveBle!.getDiscoveredServices("deviceId").then((value));
|
|
_flutterReactiveBle!.statusStream.listen((status) {
|
|
if (status == BleStatus.ready) {
|
|
// 蓝牙已开启,可以进行蓝牙操作
|
|
scanDevices.clear();
|
|
_scanSubscription = _flutterReactiveBle!.scanForDevices(withServices:[]).listen((device) {
|
|
// 判断名字为空的直接剔除
|
|
if (device.name.isEmpty) {
|
|
return;
|
|
}
|
|
print("startScanDevice:$device");
|
|
if (((device.serviceUuids.isNotEmpty ? device.serviceUuids[0] : "").toString().contains("758824")) && (device.rssi >= -100)) {
|
|
// 查询id相同的元素
|
|
final knownDeviceIndex = scanDevices.indexWhere((d) => d.id == device.id);
|
|
// 不存在的时候返回-1
|
|
if (knownDeviceIndex >= 0) {
|
|
scanDevices[knownDeviceIndex] = device;
|
|
} else {
|
|
scanDevices.add(device);
|
|
}
|
|
EventBusManager().eventBusFir(scanDevices);
|
|
}
|
|
}, onError: (Object e) {
|
|
print('Device scan fails with error: $e');
|
|
});
|
|
}else{
|
|
Get.log("开始扫描 蓝牙未开启,不能进行蓝牙操作");
|
|
}
|
|
});
|
|
|
|
}
|
|
|
|
/// 调用发送数据
|
|
Future<void> bludSendData(String deviceName, ConnectStateCallBack stateCallBack, {bool isAddEquipment = false}) async {
|
|
_flutterReactiveBle!.statusStream.listen((status) {
|
|
if (status == BleStatus.ready) {
|
|
// 蓝牙已开启,可以进行蓝牙操作
|
|
if(deviceConnectionState != DeviceConnectionState.connected){
|
|
if(isAddEquipment == false){
|
|
// print("666666666");
|
|
startScan();
|
|
}
|
|
|
|
_connect(deviceName, (state){
|
|
stateCallBack(deviceConnectionState!);
|
|
});
|
|
}else{
|
|
// stopScan();
|
|
stateCallBack(deviceConnectionState!);
|
|
}
|
|
}else{
|
|
Get.log("调用发送数据 蓝牙未开启,不能进行蓝牙操作");
|
|
}
|
|
});
|
|
}
|
|
|
|
/// 连接监听状态
|
|
Future<void> _connect(String deviceName, ConnectStateCallBack connectStateCallBack) async {
|
|
connectDeviceName = deviceName;
|
|
// 判断数组列表里面是否有这个设备
|
|
final knownDeviceIndex = scanDevices.indexWhere((d) => d.name == deviceName);
|
|
if (knownDeviceIndex >= 0) {
|
|
// 存在的时候赋值
|
|
connectDeviceMacAddress = scanDevices[knownDeviceIndex].id;
|
|
} else {
|
|
// 不存在的时候返回-1 然后循环5秒
|
|
var index = 0;
|
|
Completer? completer = Completer();
|
|
Timer.periodic(const Duration(seconds: 1), (timer) async {
|
|
///定时任务
|
|
// print("timer index0:$index");
|
|
if(index >= 9){
|
|
// 当超过5秒的时候取消定时任务 弹窗显示连接失败
|
|
connectDeviceMacAddress = "";
|
|
connectStateCallBack(DeviceConnectionState.disconnected);
|
|
completer.complete();
|
|
stopScan();
|
|
timer.cancel();
|
|
// deviceConnectionState = DeviceConnectionState.disconnected;
|
|
// print("timer index1:$index");
|
|
}else{
|
|
// 每秒判断数组列表里面是否有这个设备
|
|
final knownDeviceIndex = scanDevices.indexWhere((d) => d.name == deviceName);
|
|
|
|
if (knownDeviceIndex >= 0) {
|
|
// 存在的时候销毁定时器,赋值
|
|
connectDeviceMacAddress = scanDevices[knownDeviceIndex].id;
|
|
stopScan();
|
|
completer.complete();
|
|
timer.cancel();
|
|
// print("timer index2:$index");
|
|
|
|
// var uuidStr = (scanDevices[knownDeviceIndex].serviceUuids.isNotEmpty ? scanDevices[knownDeviceIndex].serviceUuids[0] : "").toString();
|
|
// if(uuidStr[31] == "0"){
|
|
// // 未配对 表示这把锁已被强制初始化 处于可添加状态 不再连接
|
|
// EasyLoading.showToast("当前设备已被清除配对,请删除后重新添加", duration: 2000.milliseconds);
|
|
// Future.delayed(2100.milliseconds);
|
|
// connectStateCallBack(DeviceConnectionState.disconnected);
|
|
// return;
|
|
// }
|
|
} else {
|
|
// 不存在的时候返回-1 然后循环5秒
|
|
index++;
|
|
print("index:$index");
|
|
}
|
|
}
|
|
});
|
|
// 等待Completer完成
|
|
await completer.future;
|
|
}
|
|
print("1 connectDeviceId:$connectDeviceMacAddress connectDeviceName:$connectDeviceName");
|
|
// stopScan();
|
|
if (connectDeviceMacAddress.isEmpty) {
|
|
return;
|
|
}
|
|
|
|
/// 用来判断是否返回了连接结果 还是放了一段时间后蓝牙主动断开的
|
|
var isReturnedConnectResults = false;
|
|
_currentConnectionStream = _flutterReactiveBle!.connectToDevice(id: connectDeviceMacAddress, connectionTimeout: const Duration(seconds: 5)).listen((connectionStateUpdate) async {
|
|
// 获取状态
|
|
deviceConnectionState = connectionStateUpdate.connectionState;
|
|
stopScan();
|
|
print('2 deviceConnectionState:$deviceConnectionState connectionStateUpdate.connectionState:${connectionStateUpdate.connectionState}');
|
|
if (connectionStateUpdate.connectionState == DeviceConnectionState.connected) {
|
|
isReturnedConnectResults = true;
|
|
// 如果状态是连接的开始发现服务
|
|
try {
|
|
_subScribeToCharacteristic(QualifiedCharacteristic(characteristicId: _characteristicIdSubscription, serviceId: _serviceIdConnect, deviceId: connectDeviceMacAddress));
|
|
print('Discovering services finished');
|
|
|
|
deviceConnectionState = connectionStateUpdate.connectionState;
|
|
connectStateCallBack(deviceConnectionState!);
|
|
} on Exception catch (e) {
|
|
deviceConnectionState = DeviceConnectionState.disconnected;
|
|
connectStateCallBack(deviceConnectionState!);
|
|
print('Error occurred when discovering services: $e');
|
|
rethrow;
|
|
}
|
|
} else if (connectionStateUpdate.connectionState == DeviceConnectionState.disconnected) {
|
|
// 如果状态是断开的
|
|
deviceConnectionState = connectionStateUpdate.connectionState;
|
|
if(isReturnedConnectResults == false){
|
|
isReturnedConnectResults = true;
|
|
// 如果是在连接中断开的
|
|
connectStateCallBack(deviceConnectionState!);
|
|
}
|
|
}
|
|
print('ConnectionState for device $connectDeviceMacAddress : ${connectionStateUpdate.connectionState}');
|
|
}, onError: (Object e) {
|
|
deviceConnectionState = DeviceConnectionState.disconnected;
|
|
connectStateCallBack(deviceConnectionState!);
|
|
print('Connecting to device $connectDeviceMacAddress resulted in error $e');
|
|
});
|
|
}
|
|
|
|
// 听上报来的数据,参数来自前面扫描到的结果
|
|
var allData = <int>[];
|
|
// 保存上一次的数据,用来判断是否收到重复的数据
|
|
var lastTimeData = <int>[];
|
|
int? dataLen;
|
|
_subScribeToCharacteristic(QualifiedCharacteristic characteristic) {
|
|
_flutterReactiveBle!.subscribeToCharacteristic(characteristic).listen((data) {
|
|
if(data == lastTimeData){
|
|
return;
|
|
}else{
|
|
lastTimeData = data;
|
|
}
|
|
// code to handle incoming data
|
|
// print("subscribeToCharacteristic: deviceId = ${characteristic.deviceId} characteristicId =${characteristic.characteristicId}---上报来的数据data = $data");
|
|
if ((data[0] == 0xEF) && (data[1] == 0x01) && (data[2] == 0xEE) && (data[3] == 0x02)) {
|
|
// 当包有头时
|
|
// 判断是否需要分包
|
|
dataLen = data[8] * 256 + data[9]; // 高16位用来指示后面数据块内容的长度
|
|
// print("dataLen1111:$dataLen getDataLength:${data.length}");
|
|
if (dataLen! + 12 > data.length) {
|
|
// 当前包的长度小于实际的包时 分包添加 不解析
|
|
allData.addAll(data);
|
|
} else {
|
|
// 当前包的长度小于实际的包时 不分包 解析
|
|
allData.addAll(data);
|
|
// print("dataLen2222:$dataLen getDataLength:${data.length}");
|
|
CommandReciverManager.appDataReceive(allData);
|
|
// 发送完解析初始化数组
|
|
allData = <int>[];
|
|
}
|
|
} else {
|
|
// 当包没有头时 是分包的包 直接添加
|
|
allData.addAll(data);
|
|
// var len = allData[8] * 256 + allData[9];
|
|
// print("dataLen3333:$dataLen");
|
|
if ((dataLen! + 14) <= allData.length) {
|
|
// print("44444数据被解析了");
|
|
// 当长度小于等于当前包的数据时 直接解析数据
|
|
CommandReciverManager.appDataReceive(allData);
|
|
// 发送完解析初始化数组
|
|
allData = <int>[];
|
|
}
|
|
}
|
|
}, onError: (dynamic error) {
|
|
EasyLoading.dismiss();
|
|
print("subscribeToCharacteristic error:$error");
|
|
});
|
|
}
|
|
|
|
// 写入
|
|
Future<void> writeCharacteristicWithResponse(List<int> value) async {
|
|
QualifiedCharacteristic characteristic = QualifiedCharacteristic(characteristicId: _characteristicIdWrite, serviceId: _serviceIdWrite, deviceId: connectDeviceMacAddress);
|
|
int mtuLength = await _flutterReactiveBle!.requestMtu(deviceId: characteristic.deviceId, mtu: 250);
|
|
print("mtuLength:$mtuLength");
|
|
try {
|
|
List<int> valueList = value;
|
|
List subData = splitList(valueList, mtuLength);
|
|
print('得到的分割数据:$subData');
|
|
|
|
for (int i = 0; i < subData.length; i++) {
|
|
await _flutterReactiveBle!
|
|
.writeCharacteristicWithResponse(characteristic, value: subData[i])
|
|
.then((value) async {
|
|
await Future.delayed(const Duration(milliseconds: 1))
|
|
.then((value) async {
|
|
print('分包发送成功了');
|
|
});
|
|
});
|
|
}
|
|
} on Exception catch (e, s) {
|
|
print('Error occurred when writing: $e');
|
|
// ignore: avoid_print
|
|
print(s);
|
|
rethrow;
|
|
}
|
|
}
|
|
|
|
// 读取
|
|
Future<List<int>> _readCharacteristic(QualifiedCharacteristic characteristic) async {
|
|
try {
|
|
final result =
|
|
await _flutterReactiveBle!.readCharacteristic(characteristic);
|
|
print("readListresult$result");
|
|
return result;
|
|
} on Exception catch (e, s) {
|
|
print(
|
|
'Error occurred when reading ${characteristic.characteristicId} : $e',
|
|
);
|
|
rethrow;
|
|
}
|
|
}
|
|
|
|
Future<void> writeCharacteristicWithoutResponse(
|
|
QualifiedCharacteristic characteristic, List<int> value) async {
|
|
try {
|
|
await _flutterReactiveBle!
|
|
.writeCharacteristicWithoutResponse(characteristic, value: value);
|
|
} on Exception catch (e, s) {
|
|
// ignore: avoid_print
|
|
print(s);
|
|
rethrow;
|
|
}
|
|
}
|
|
|
|
// 停止扫描蓝牙设备
|
|
void stopScan() {
|
|
// print("444444444");
|
|
if(_scanSubscription != null){
|
|
// print("555555555555");
|
|
_scanSubscription?.cancel();
|
|
_scanSubscription = null;
|
|
}
|
|
}
|
|
|
|
// 断开连接
|
|
Future<void> disconnect(String deviceMAC) async {
|
|
try {
|
|
connectDeviceMacAddress = "";
|
|
// if(_currentConnectionStream != null){
|
|
_currentConnectionStream?.cancel();
|
|
_currentConnectionStream = null;
|
|
// }
|
|
|
|
print('disconnecting to device: $connectDeviceName');
|
|
} on Exception catch (e, _) {
|
|
print("Error disconnecting from a device: $e");
|
|
} finally {
|
|
deviceConnectionState = DeviceConnectionState.disconnected;
|
|
}
|
|
}
|
|
|
|
disposed() {
|
|
_sendStreamSubscription?.cancel();
|
|
_currentConnectionStream?.cancel();
|
|
_scanSubscription?.cancel();
|
|
}
|
|
}
|