app-starlock/lib/blue/blue_manage.dart

793 lines
33 KiB
Dart
Raw Normal View History

import 'dart:async';
import 'dart:io';
import 'package:flutter_blue_plus/flutter_blue_plus.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:get/get.dart';
2024-04-26 15:38:59 +08:00
import 'package:star_lock/app_settings/app_settings.dart';
2024-09-29 13:47:50 +08:00
import 'package:star_lock/tools/bugly/bugly_tool.dart';
2024-05-27 17:38:23 +08:00
import 'package:star_lock/tools/commonDataManage.dart';
2023-08-08 09:42:35 +08:00
import 'io_tool/io_model.dart';
2023-08-08 09:42:35 +08:00
import 'io_tool/io_tool.dart';
import 'io_tool/manager_event_bus.dart';
import 'io_type.dart';
2023-08-09 10:07:27 +08:00
import 'reciver_data.dart';
2023-08-08 09:42:35 +08:00
//连接状态回调
typedef ConnectStateCallBack = Function(
BluetoothConnectionState connectionState);
typedef ScanDevicesCallBack = Function(List<ScanResult>);
2023-08-08 09:42:35 +08:00
class BlueManage {
factory BlueManage() => shareManager()!;
BlueManage._init() {
_initBlue();
}
2024-05-27 17:38:23 +08:00
2024-05-20 16:37:49 +08:00
final List<ScanResult> scanDevices = <ScanResult>[];
2023-12-27 10:47:58 +08:00
// 用来写入的服务id
2024-05-20 16:37:49 +08:00
final Guid _serviceIdConnect = Guid('fff0');
2024-01-02 18:03:50 +08:00
// 用来写入的服务id
final Guid _serviceIdWrite = Guid('0000FFF0-0000-1000-8000-00805F9B34FB');
2023-12-27 10:47:58 +08:00
// 用来订阅的特征id
2024-05-20 16:37:49 +08:00
final Guid _characteristicIdSubscription = Guid('fff1');
2023-12-27 10:47:58 +08:00
// 用来写入的特征id
2024-05-20 16:37:49 +08:00
final Guid _characteristicIdWrite = Guid('fff2');
2023-08-08 09:42:35 +08:00
// 监听发送事件
StreamSubscription<EventSendModel>? _sendStreamSubscription;
StreamSubscription<BluetoothConnectionState>? _connectionStateSubscription;
StreamSubscription<int>? _mtuSubscription;
int? _mtuSize = 20;
2023-12-27 10:47:58 +08:00
// 当前连接设备的名字
2024-05-20 16:37:49 +08:00
String connectDeviceName = '';
2023-12-27 10:47:58 +08:00
// 当前连接设备的mac地址
2024-05-20 16:37:49 +08:00
String connectDeviceMacAddress = '';
// 当前连接的设备
BluetoothDevice? bluetoothConnectDevice;
// 当前扫描到结果要连接设备
ScanResult? scanResult;
// 监听蓝牙连接状态
BluetoothConnectionState? bluetoothConnectionState =
BluetoothConnectionState.disconnected;
BluetoothAdapterState? _adapterState = BluetoothAdapterState.on;
StreamSubscription<BluetoothAdapterState>? _adapterStateStateSubscription;
// 听上报来的数据,参数来自前面扫描到的结果
List<int> allData = <int>[];
// 保存上一次的数据,用来判断是否收到重复的数据
List<int> lastTimeData = <int>[];
int? dataLen;
Timer? scanSingleTimer;
bool needScanSingle = false;
static BlueManage? _manager;
2023-08-08 09:42:35 +08:00
static BlueManage? shareManager() {
_manager ??= BlueManage._init();
// _manager!._initBlue();
2023-08-08 09:42:35 +08:00
return _manager;
}
BlueManage? get manager => shareManager();
void _initBlue() {
FlutterBluePlus.setLogLevel(LogLevel.error, color: true);
_initSendStreamSubscription();
_initAdapterStateStateSubscription();
}
void _initGetMtuSubscription() {
2024-05-20 16:37:49 +08:00
_mtuSubscription ??= bluetoothConnectDevice!.mtu.listen((int value) {
_mtuSize = value - 3;
2024-04-26 15:38:59 +08:00
AppLog.log('_mtuSizeValue:$value mtuSize:$_mtuSize');
});
}
void _initAdapterStateStateSubscription() {
_adapterStateStateSubscription ??=
2024-05-20 16:37:49 +08:00
FlutterBluePlus.adapterState.listen((BluetoothAdapterState state) {
2024-09-29 13:47:50 +08:00
AppLog.log('蓝牙状态:$state');
_adapterState = state;
});
}
void _initListenConnectionState() {
_connectionStateSubscription?.cancel();
_connectionStateSubscription = null;
2024-05-20 16:37:49 +08:00
_connectionStateSubscription = bluetoothConnectDevice!.connectionState
.listen((BluetoothConnectionState state) async {
bluetoothConnectionState = state;
AppLog.log('蓝牙连接回调状态:$state');
});
}
void _initSendStreamSubscription() {
_sendStreamSubscription ??= EventBusManager()
.eventBus!
.on<EventSendModel>()
.listen((EventSendModel model) {
if (model.sendChannel == DataChannel.ble) {
2024-05-20 16:37:49 +08:00
FlutterBluePlus.isSupported.then((bool isAvailable) async {
if (isAvailable) {
if (_adapterState == BluetoothAdapterState.on) {
// 蓝牙已开启,可以进行蓝牙操作
writeCharacteristicWithResponse(model.data);
} else {
try {} catch (e) {
2024-05-20 16:37:49 +08:00
AppLog.log('蓝牙打开失败');
}
}
} else {
2024-05-20 16:37:49 +08:00
AppLog.log('写入数据 蓝牙不可用,不能进行蓝牙操作');
}
});
}
});
2023-08-08 09:42:35 +08:00
}
/// 开始指定设备名称的扫描蓝牙设备
Future<void> startScanSingle(String deviceName, int timeout,
ScanDevicesCallBack scanDevicesCallBack) async {
2024-05-20 18:18:09 +08:00
final DateTime start = DateTime.now();
2024-05-20 16:37:49 +08:00
FlutterBluePlus.isSupported.then((bool isAvailable) async {
if (isAvailable) {
// AppLog.log('startScanSingle 蓝牙状态 系统蓝牙状态:$_adapterState 蓝牙连接状态:$bluetoothConnectionState');
if (_adapterState == BluetoothAdapterState.on) {
try {
2024-09-30 10:35:44 +08:00
BuglyTool.uploadException(
message: '开始指定设备名称的扫描蓝牙设备',
detail: '调用方法是:startScanSingle 指定设备名称是:$deviceName',
upload: false);
//android 扫描比较慢,取样只要 3 分之一
final int divisor = Platform.isAndroid ? 3 : 1;
2024-05-20 18:18:09 +08:00
FlutterBluePlus.startScan(
continuousDivisor: divisor,
continuousUpdates: true,
2024-05-21 11:05:10 +08:00
withKeywords: <String>[deviceName],
2024-05-20 18:18:09 +08:00
timeout: Duration(seconds: timeout));
2024-05-20 16:37:49 +08:00
final Completer<dynamic> completer = Completer<dynamic>();
final StreamSubscription<List<ScanResult>> subscription =
FlutterBluePlus.scanResults.listen((List<ScanResult> results) {
final bool isExit = results.any((ScanResult element) =>
(element.device.platformName == deviceName) ||
(element.advertisementData.advName == deviceName));
2024-05-20 18:18:09 +08:00
final int milliseconds = DateTime.now().millisecondsSinceEpoch -
start.millisecondsSinceEpoch;
AppLog.log(
'扫描到的设备数:${results.length} 是否查找到 $isExit 以查找$milliseconds毫秒');
2024-09-30 10:35:44 +08:00
BuglyTool.uploadException(
message: '指定设备名称的扫描蓝牙设备 监听扫描结果',
detail:
'startScanSingle$deviceName 监听扫描结果 是否查找到 $isExit 以查找$milliseconds毫秒 扫描到的设备数:${results.length} results:$results',
upload: false);
if (isExit) {
2024-05-20 16:37:49 +08:00
for (final ScanResult scanResult in results) {
if (((scanResult.advertisementData.serviceUuids.isNotEmpty
? scanResult.advertisementData.serviceUuids[0]
2024-05-20 16:37:49 +08:00
: '')
.toString()
2024-05-20 16:37:49 +08:00
.contains('758824')) &&
(scanResult.rssi >= -100)) {
// 查询id相同的元素
2024-05-20 16:37:49 +08:00
final int knownDeviceIndex = scanDevices.indexWhere(
(ScanResult d) =>
(d.device.platformName ==
scanResult.device.platformName) ||
(d.advertisementData.advName ==
scanResult.advertisementData.advName));
// 不存在的时候返回-1
if (knownDeviceIndex >= 0) {
scanDevices[knownDeviceIndex] = scanResult;
} else {
scanDevices.add(scanResult);
}
2024-09-30 10:35:44 +08:00
BuglyTool.uploadException(
message: '遍历扫描到的结果跟缓存的结果对比,如果有最新的就更新缓存',
detail:
'startScanSingle deviceName:$deviceName 查询到的结果scanResult:$scanResult',
upload: false);
}
}
2024-05-20 18:18:09 +08:00
completer.complete();
}
}, onError: (e) {
BuglyTool.uploadException(
message: '指定设备名称的扫描蓝牙设备 监听扫描结果失败',
detail: '打印失败问题 e${e.toString()}',
upload: false);
AppLog.log('扫描失败:$e');
});
FlutterBluePlus.cancelWhenScanComplete(subscription);
await completer.future;
scanDevicesCallBack(scanDevices);
subscription.cancel();
} catch (e) {
2024-09-30 10:35:44 +08:00
BuglyTool.uploadException(
message: '指定设备名称的扫描蓝牙设备 内部逻辑整形失败',
detail: 'tartScanSingle内部逻辑整形失败 e:${e.toString()}',
upload: false);
2024-05-20 16:37:49 +08:00
AppLog.log('扫描失败');
}
} else {
try {
2024-09-30 10:35:44 +08:00
openBlue();
} catch (e) {
2024-05-20 16:37:49 +08:00
AppLog.log('蓝牙打开失败');
}
}
} else {
2024-05-20 16:37:49 +08:00
AppLog.log('开始扫描 蓝牙不可用,不能进行蓝牙操作');
}
});
}
/// 开始扫描蓝牙设备
Future<void> startScan(int timeout, DeviceType deviceType,
ScanDevicesCallBack scanDevicesCallBack,
{List<Guid>? idList}) async {
2024-05-20 16:37:49 +08:00
FlutterBluePlus.isSupported.then((bool isAvailable) async {
if (isAvailable) {
// AppLog.log('startScan 蓝牙状态 系统蓝牙状态:$_adapterState 蓝牙连接状态:$bluetoothConnectionState');
if (_adapterState == BluetoothAdapterState.on) {
try {
FlutterBluePlus.startScan(timeout: Duration(seconds: timeout));
2024-09-29 13:47:50 +08:00
final StreamSubscription<List<ScanResult>> subscription =
FlutterBluePlus.scanResults.listen((List<ScanResult> results) {
scanDevices.clear();
2024-05-20 16:37:49 +08:00
for (final ScanResult scanResult in results) {
// AppLog.log('扫描到的设备:${scanResult.device.platformName} ${scanResult.advertisementData.advName} ${scanResult.rssi}');
// 判断名字为空的直接剔除
if (((scanResult.advertisementData.serviceUuids.isNotEmpty
? scanResult.advertisementData.serviceUuids[0]
2024-05-20 16:37:49 +08:00
: '')
.toString()
.contains(getDeviceType(deviceType))) &&
(scanResult.rssi >= -100)) {
// 查询id相同的元素
2024-05-20 16:37:49 +08:00
final int knownDeviceIndex = scanDevices.indexWhere(
(ScanResult d) =>
(d.device.platformName ==
scanResult.device.platformName) ||
(d.advertisementData.advName ==
scanResult.advertisementData.advName));
// 不存在的时候返回-1
if (knownDeviceIndex >= 0) {
scanDevices[knownDeviceIndex] = scanResult;
} else {
scanDevices.add(scanResult);
}
}
}
scanDevicesCallBack(scanDevices);
}, onError: (e) {
2024-05-07 16:45:59 +08:00
AppLog.log(
2024-05-20 16:37:49 +08:00
'扫描失败:$e',
2024-05-07 16:45:59 +08:00
);
});
FlutterBluePlus.cancelWhenScanComplete(subscription);
} catch (e) {
2024-05-20 16:37:49 +08:00
AppLog.log('扫描失败');
}
} else {
try {
2024-09-30 10:35:44 +08:00
openBlue();
} catch (e) {
2024-05-20 16:37:49 +08:00
AppLog.log('蓝牙打开失败');
}
}
} else {
2024-05-20 16:37:49 +08:00
AppLog.log('开始扫描 蓝牙不可用,不能进行蓝牙操作');
2023-08-08 09:42:35 +08:00
}
});
}
/// 调用发送数据 List senderData,
Future<void> blueSendData(
2024-05-07 16:45:59 +08:00
String deviceName, ConnectStateCallBack stateCallBack,
{bool isAddEquipment = false}) async {
2024-05-20 16:37:49 +08:00
FlutterBluePlus.isSupported.then((bool isAvailable) async {
if (isAvailable) {
// AppLog.log('蓝牙状态 系统蓝牙状态:$_adapterState 蓝牙连接状态:$bluetoothConnectionState');
if (_adapterState == BluetoothAdapterState.on) {
// 蓝牙已开启,可以进行蓝牙操作
if (bluetoothConnectionState != BluetoothConnectionState.connected) {
2024-09-30 10:35:44 +08:00
BuglyTool.uploadException(
message: '点击按钮 蓝牙未连接 下一步扫描连接蓝牙',
detail:
'blueSendData 蓝牙连接状态 bluetoothConnectionState$bluetoothConnectionState deviceName:$deviceName',
upload: false);
2024-05-20 16:37:49 +08:00
_connect(deviceName, (BluetoothConnectionState state) {
stateCallBack(bluetoothConnectionState!);
}, isAddEquipment: isAddEquipment);
} else {
2024-09-30 10:35:44 +08:00
BuglyTool.uploadException(
message: '点击按钮 蓝牙已经连接 下一步扫描连接蓝牙',
detail:
'blueSendData 直接回调状态 蓝牙连接状态bluetoothConnectionState$bluetoothConnectionState deviceName:$deviceName',
upload: false);
stateCallBack(bluetoothConnectionState!);
}
} else {
2024-09-30 10:35:44 +08:00
BuglyTool.uploadException(
message: '点击按钮 蓝牙未打开',
detail:
'blueSendData 蓝牙未打开--_adapterState:${BluetoothAdapterState.on} deviceName:$deviceName',
upload: false);
try {
stateCallBack(BluetoothConnectionState.disconnected);
openBlue();
} catch (e) {
2024-05-20 16:37:49 +08:00
AppLog.log('蓝牙打开失败');
2024-09-30 10:35:44 +08:00
BuglyTool.uploadException(
message: '点击按钮 蓝牙未打开 然后蓝牙打开失败',
detail:
'blueSendData 蓝牙打开失败--_adapterState:${BluetoothAdapterState.on} deviceName:$deviceName',
upload: false);
}
}
} else {
2024-09-29 13:47:50 +08:00
BuglyTool.uploadException(
message: '点击按钮 蓝牙状态不可用',
detail: 'blueSendData 蓝牙状态不可用--isAvailable:$isAvailable',
upload: false);
stateCallBack(BluetoothConnectionState.disconnected);
2024-05-20 16:37:49 +08:00
AppLog.log('开始扫描 蓝牙不可用,不能进行蓝牙操作');
}
});
2024-01-02 18:03:50 +08:00
}
/// 连接
Future<void> _connect(
String deviceName, ConnectStateCallBack connectStateCallBack,
{bool isAddEquipment = false}) async {
connectDeviceName = deviceName;
2024-09-30 10:35:44 +08:00
// 当前已扫描到的缓存设备
2024-05-20 16:37:49 +08:00
final List<ScanResult> devicesList = scanDevices;
2024-09-30 10:35:44 +08:00
// 是否有缓存设备 true是有缓存设备
2024-05-21 11:05:10 +08:00
final bool isExistDevice = isExistScanDevices(connectDeviceName);
2024-09-30 10:35:44 +08:00
// 是否是当前设备
final bool isCurrentDevice =
CommonDataManage().currentKeyInfo.lockName == deviceName;
2024-09-30 10:35:44 +08:00
// mac地址
2024-05-27 17:38:23 +08:00
final String? mac = CommonDataManage().currentKeyInfo.mac;
AppLog.log('开始连接 是否存在缓存:$isExistDevice 是否是当前设备:$isCurrentDevice mac$mac');
if (GetPlatform.isAndroid &&
!isExistDevice &&
isCurrentDevice &&
mac != null) {
2024-09-30 10:35:44 +08:00
// 当是安卓设备 且不存在缓存设备 且是当前设备 且mac地址不为空
BuglyTool.uploadException(
message: '开始连接 当是安卓设备 且不存在缓存设备 且是当前设备 且mac地址不为空 上传记录当前方法是_connect',
detail:
'调用方法_connect deviceName:$deviceName GetPlatform.isAndroid:${GetPlatform.isAndroid} isExistDevice:$isExistDevice mac:$mac needScanSingle$needScanSingle',
upload: false);
// scanSingleTimer?.cancel();
2024-09-30 10:35:44 +08:00
// 兼容android 的低配手机
try {
if (!needScanSingle) {
BuglyTool.uploadException(
message:
'开始连接 当是安卓设备 且不存在缓存设备 且是当前设备 且mac地址不为空 上传记录当前方法是_connect',
detail: '调用方法doNotSearchBLE直接连接,needScanSingle$needScanSingle',
upload: false);
await doNotSearchBLE(mac, connectStateCallBack,
isAddEquipment: isAddEquipment);
} else {
BuglyTool.uploadException(
message:
'开始连接 当是安卓设备 且不存在缓存设备 且是当前设备 且mac地址不为空 上传记录当前方法是_connect',
detail:
'调用方法startScanSingle执行扫描函数,needScanSingle$needScanSingle',
upload: false);
startScanSingle(deviceName, 15, (List<ScanResult> scanDevices) {
_connectDevice(scanDevices, deviceName, connectStateCallBack,
isAddEquipment: isAddEquipment);
});
}
} catch (e) {
2024-09-30 10:35:44 +08:00
BuglyTool.uploadException(
message: '开始连接 当是安卓设备 且不存在缓存设备 且是当前设备 且mac地址不为空 上传记录当前方法是_connect',
detail: '调用方法doNotSearchBLE发生异常执行扫描函数 startScanSingle异常信息$e',
upload: false);
startScanSingle(deviceName, 15, (List<ScanResult> scanDevices) {
_connectDevice(scanDevices, deviceName, connectStateCallBack,
isAddEquipment: isAddEquipment);
});
}
//
// scanSingleTimer = Timer(3.seconds, () {
// scanSingleTimer?.cancel();
// BuglyTool.uploadException(
// message:
// '开始连接 当是安卓设备 且不存在缓存设备 且是当前设备 且mac地址不为空 3秒以后调用startScanSingle 上传记录当前方法是_connect',
// detail:
// '_connect deviceName:$deviceName scanSingleTimer调用startScanSingle',
// upload: false);
// startScanSingle(deviceName, 15, (List<ScanResult> scanDevices) => null);
// });ƒ
2024-05-27 17:38:23 +08:00
} else if (isAddEquipment == false && isExistDevice == false) {
// 取消缓存直接使用,存在配对场景设备信息会更变
2024-09-30 10:35:44 +08:00
BuglyTool.uploadException(
message:
'取消缓存直接使用,存在配对场景设备信息会更变 然后开始指定设备名称的扫描蓝牙设备 上传记录当前方法是_connect',
detail:
'符合条件(isAddEquipment == false && isExistDevice == false) 下一步调用startScanSingle',
upload: false);
2024-09-30 10:35:44 +08:00
// AppLog.log('无存在设备需要扫描 deviceName:$deviceName isAddEquipment:$isAddEquipment');
startScanSingle(deviceName, 15, (List<ScanResult> scanDevices) {
_connectDevice(scanDevices, deviceName, connectStateCallBack,
isAddEquipment: isAddEquipment);
});
} else {
2024-09-30 10:35:44 +08:00
BuglyTool.uploadException(
message: '没有扫描直接调用连接设备 上传记录当前方法是_connect',
detail:
'走这个方法是有缓存或者添加设备的时候以及不符合(GetPlatform.isAndroid && !isExistDevice && isCurrentDevice && mac != null) deviceName:$deviceName 直接调用_connectDevice',
upload: false);
// AppLog.log('安卓或者iOS 存在设备不需要扫描 deviceName:$deviceName isAddEquipment:$isAddEquipment');
_connectDevice(devicesList, deviceName, connectStateCallBack,
isAddEquipment: isAddEquipment);
}
}
2024-05-21 11:05:10 +08:00
//查找缓存里面是否有设备
bool isExistScanDevices(String connectDeviceName) {
final bool isExistDevice = scanDevices.any((ScanResult element) =>
element.device.platformName == connectDeviceName ||
element.advertisementData.advName == connectDeviceName);
2024-05-21 11:05:10 +08:00
return isExistDevice;
}
Future<void> _connectDevice(
2024-09-29 13:47:50 +08:00
List<ScanResult> devicesList,
String deviceName,
ConnectStateCallBack connectStateCallBack, {
bool isAddEquipment = false, // 是否是添加设备之前
bool isReconnect = true, // 是否是重连
}) async {
2023-12-27 10:47:58 +08:00
// 判断数组列表里面是否有这个设备
2024-04-26 15:38:59 +08:00
// AppLog.log("devicesList:$devicesList");
2024-09-30 10:35:44 +08:00
2024-05-20 16:37:49 +08:00
final int knownDeviceIndex = devicesList.indexWhere((ScanResult d) =>
(d.device.platformName == deviceName) ||
(d.advertisementData.advName == deviceName));
2024-05-07 16:45:59 +08:00
ScanResult? scanResult; //使用局部变量防止出现缓存
2023-12-27 10:47:58 +08:00
if (knownDeviceIndex >= 0) {
// 存在的时候赋值
connectDeviceMacAddress =
devicesList[knownDeviceIndex].advertisementData.advName.isNotEmpty
? devicesList[knownDeviceIndex].advertisementData.advName
: devicesList[knownDeviceIndex].device.platformName;
bluetoothConnectDevice = devicesList[knownDeviceIndex].device;
scanResult = devicesList[knownDeviceIndex];
// AppLog.log('bluetoothConnectDevice: $bluetoothConnectDevice scanResult:$scanResult');
_initGetMtuSubscription();
_initListenConnectionState();
}
if (scanResult == null || connectDeviceMacAddress.isEmpty) {
2024-09-30 10:35:44 +08:00
BuglyTool.uploadException(
message:
'扫描结果scanResult == null || connectDeviceMacAddress.isEmpty不往下执行 return 上传记录当前方法是_connectDevice',
detail:
'scanResult:$scanResult connectDeviceMacAddress$connectDeviceMacAddress',
upload: false);
return;
}
AppLog.log('调用了停止扫描的方法');
await stopScan();
if ((scanResult.advertisementData.serviceUuids[0].toString()[31] == '0') &&
isAddEquipment == false) {
// 添加这个判断是因为有些苹果设备或者安卓等性能比较好的设备时,添加完锁之后,锁板未改变为已添加状态之前,就进行了蓝牙连接,导致添加完锁就失败,这里进行了判断,如果第一次连接失败,就清除缓存重新扫描连接
2024-09-29 13:47:50 +08:00
if (isReconnect == true) {
AppLog.log('该锁已被重置, 重新发送扫描命令');
2024-09-30 10:35:44 +08:00
BuglyTool.uploadException(
message: '该锁已被重置, 重新发送扫描命令startScanSingle 上传记录当前方法是_connectDevice',
detail:
'添加这个判断是因为有些苹果设备或者安卓等性能比较好的设备时,添加完锁之后,锁板未改变为已添加状态之前,就进行了蓝牙连接,导致添加完锁就失败,这里进行了判断,如果第一次连接失败,就清除缓存重新扫描连接 该锁已被重置, 重新发送扫描命令 serviceUuids:${scanResult.advertisementData.serviceUuids[0].toString()}',
upload: false);
2024-09-30 10:35:44 +08:00
2024-08-08 11:00:03 +08:00
scanDevices.clear();
startScanSingle(deviceName, 15, (List<ScanResult> scanDevices) {
2024-09-29 13:47:50 +08:00
_connectDevice(scanDevices, deviceName, connectStateCallBack,
isAddEquipment: isAddEquipment, isReconnect: false);
});
2024-09-29 13:47:50 +08:00
} else {
connectStateCallBack(BluetoothConnectionState.disconnected);
EasyLoading.showToast('该锁已被重置'.tr, duration: 2000.milliseconds);
scanDevices.clear();
BuglyTool.uploadException(
message: '提示该锁已被重置, 回调断开连接, 清除缓存上传记录当前方法是_connectDevice',
detail:
'isReconnect:$isReconnect serviceUuids:${scanResult.advertisementData.serviceUuids[0].toString()}',
upload: false);
}
return;
}
BuglyTool.uploadException(
message: '从devicesList里面查到了设备 下一步连接设备 上传记录当前方法是_connectDevice',
detail:
'devicesList:$devicesList scanResult:${scanResult.toString()} bluetoothConnectDevice${bluetoothConnectDevice.toString()} connectDeviceMacAddress$connectDeviceMacAddress',
upload: false);
//连接设备
await bluetoothDeviceConnect(bluetoothConnectDevice!, connectStateCallBack);
}
//直接给蓝牙设备写入
Future<void> doNotSearchBLE(
String masAdds, ConnectStateCallBack connectStateCallBack,
{bool isAddEquipment = false}) async {
await FlutterBluePlus.stopScan();
if (bluetoothConnectDevice == null ||
bluetoothConnectDevice?.remoteId.str != masAdds) {
bluetoothConnectDevice = BluetoothDevice.fromId(masAdds);
_initGetMtuSubscription();
_initListenConnectionState();
BuglyTool.uploadException(
message: '直接给蓝牙设备写入 上传记录当前方法是doNotSearchBLE',
detail: '直接给蓝牙设备写入 通过fromId方法创建一个BluetoothDevice masAdds$masAdds',
upload: false);
} else {
2024-09-30 10:35:44 +08:00
BuglyTool.uploadException(
message: '直接给蓝牙设备写入 上传记录当前方法是doNotSearchBLE',
detail:
'直接给蓝牙设备写入 用传入的bluetoothConnectDevice${bluetoothConnectDevice.toString()}连接 masAdds:$masAdds',
upload: false);
}
//尝试连接设备
await bluetoothDeviceConnect(bluetoothConnectDevice!, connectStateCallBack,
isAddEquipment: isAddEquipment);
}
//设备连接
Future<void> bluetoothDeviceConnect(BluetoothDevice bluetoothConnectDevice,
ConnectStateCallBack connectStateCallBack,
{bool isAddEquipment = false}) async {
// 重连三次
2024-05-20 18:18:09 +08:00
const int maxAttempts = 3;
int attempt = 0;
while (attempt < maxAttempts) {
try {
await bluetoothConnectDevice.connect(timeout: 5.seconds);
break; // If the connection is successful, break the loop
} catch (e) {
2024-04-26 15:38:59 +08:00
AppLog.log('连接失败 重连了: $e');
attempt++; // Increase the attempt count
if (attempt < maxAttempts) {
2024-04-26 15:38:59 +08:00
AppLog.log('重新尝试连接...');
2024-01-16 10:41:08 +08:00
}
2023-08-08 09:42:35 +08:00
}
}
if (attempt >= maxAttempts) {
2024-04-26 15:38:59 +08:00
AppLog.log('$maxAttempts次后尝试连接失败');
2024-09-30 10:35:44 +08:00
BuglyTool.uploadException(
message: '连接三次超时断开连接 回调断开连接 上传记录当前方法是bluetoothDeviceConnect',
detail:
'bluetoothDeviceConnect:${bluetoothConnectDevice.toString()} $maxAttempts次后尝试连接失败',
upload: false);
needScanSingle = true;
connectStateCallBack(BluetoothConnectionState.disconnected);
}
if (bluetoothConnectionState == BluetoothConnectionState.connected) {
try {
needScanSingle = false;
final List<BluetoothService> services =
await bluetoothConnectDevice.discoverServices();
//循环判断服务
for (final BluetoothService service in services) {
if (service.uuid == _serviceIdConnect) {
for (final BluetoothCharacteristic characteristic
in service.characteristics) {
if (characteristic.characteristicUuid ==
_characteristicIdSubscription) {
_subScribeToCharacteristic(characteristic);
bluetoothConnectionState = BluetoothConnectionState.connected;
connectStateCallBack(bluetoothConnectionState!);
2024-09-30 10:35:44 +08:00
BuglyTool.uploadException(
message: '订阅成功 上传记录当前方法是bluetoothDeviceConnect',
detail:
'发现服务,连接成功,订阅数据 bluetoothDeviceConnect:${bluetoothConnectDevice.toString()} ',
upload: false);
} else {
2024-09-30 10:35:44 +08:00
BuglyTool.uploadException(
message: '订阅失败 上传记录当前方法是bluetoothDeviceConnect',
detail:
'失败原因: characteristic.characteristicUuid:${characteristic.characteristicUuid} != _characteristicIdSubscription:$_characteristicIdSubscription bluetoothDeviceConnect:${bluetoothConnectDevice.toString()}',
upload: false);
}
}
} else {
2024-09-30 10:35:44 +08:00
BuglyTool.uploadException(
message: '订阅失败 上传记录当前方法是bluetoothDeviceConnect',
detail:
'失败原因: service.uuid:${service.uuid} != _serviceIdConnect:$_serviceIdConnect bluetoothDeviceConnect:${bluetoothConnectDevice.toString()}',
upload: false);
}
}
} on Exception catch (e) {
needScanSingle = true;
bluetoothConnectionState = BluetoothConnectionState.disconnected;
connectStateCallBack(bluetoothConnectionState!);
2024-05-07 16:45:59 +08:00
AppLog.log(
'发现设备时失败 e:$e bluetoothConnectionState:$bluetoothConnectionState');
2024-09-30 10:35:44 +08:00
BuglyTool.uploadException(
message: '发现服务时失败',
detail:
'发现服务时报错原因e$e bluetoothDeviceConnect:${bluetoothConnectDevice.toString()}',
upload: false);
rethrow;
}
}
2023-08-08 09:42:35 +08:00
}
2024-05-20 18:18:09 +08:00
Future<void> _subScribeToCharacteristic(
BluetoothCharacteristic characteristic) async {
2024-05-20 16:37:49 +08:00
final StreamSubscription<List<int>> subscription =
characteristic.onValueReceived.listen((List<int> data) {
AppLog.log('订阅获取的数据: $data ');
if (data == lastTimeData || data.isEmpty) {
return;
} else {
lastTimeData = data;
}
final bool dataHeadCorrect = isDataHeadCorrect(data);
final bool allDataHeadCorrect = isDataHeadCorrect(allData);
if (dataHeadCorrect && allDataHeadCorrect) {
//缓存数据和新数据都有包头,直接放弃缓存数据
allData = <int>[];
}
if (dataHeadCorrect) {
// 当包有头时
// 判断是否需要分包
2023-12-20 11:54:54 +08:00
dataLen = data[8] * 256 + data[9]; // 高16位用来指示后面数据块内容的长度
2024-05-07 16:45:59 +08:00
if (dataLen! + 14 > data.length) {
// 当前包的长度小于实际的包时 分包添加 不解析
2023-09-04 15:00:42 +08:00
allData.addAll(data);
} else {
// 当前包的长度小于实际的包时 不分包 解析
allData.addAll(data);
CommandReciverManager.appDataReceive(allData);
// 发送完解析初始化数组
allData = <int>[];
}
} else if (allDataHeadCorrect) {
// 当包没有头时 是分包的包 直接添加
allData.addAll(data);
2024-05-09 13:41:53 +08:00
if (((dataLen ?? 0) + 14) <= allData.length) {
// 当长度小于等于当前包的数据时 直接解析数据
CommandReciverManager.appDataReceive(allData);
// 发送完解析初始化数组
allData = <int>[];
2023-09-04 15:00:42 +08:00
}
}
2023-08-08 09:42:35 +08:00
});
bluetoothConnectDevice!.cancelWhenDisconnected(subscription);
await characteristic.setNotifyValue(true);
2023-08-08 09:42:35 +08:00
}
//判断数据头是否正确
bool isDataHeadCorrect(List<int> data) {
if (data.length < 4) {
return false;
}
//239, 1, 238, 2, 是数据包头
if ((data[0] == 0xEF) &&
(data[1] == 0x01) &&
(data[2] == 0xEE) &&
(data[3] == 0x02)) {
return true;
} else {
return false;
}
}
2023-08-08 09:42:35 +08:00
// 写入
Future<void> writeCharacteristicWithResponse(List<int> value) async {
2024-05-20 16:37:49 +08:00
final List<BluetoothService> services =
2024-05-07 16:45:59 +08:00
await bluetoothConnectDevice!.discoverServices();
2024-05-20 16:37:49 +08:00
for (final BluetoothService service in services) {
if (service.uuid == _serviceIdConnect) {
2024-05-20 16:37:49 +08:00
for (final BluetoothCharacteristic characteristic
2024-05-07 16:45:59 +08:00
in service.characteristics) {
if (characteristic.characteristicUuid == _characteristicIdWrite) {
try {
2024-05-20 16:37:49 +08:00
final List<int> valueList = value;
final List subData = splitList(valueList, _mtuSize!);
2024-04-26 15:38:59 +08:00
// AppLog.log('writeCharacteristicWithResponse _mtuSize:$_mtuSize 得到的分割数据:$subData');
for (int i = 0; i < subData.length; i++) {
if (characteristic.properties.writeWithoutResponse) {
// 使用WRITE_NO_RESPONSE属性写入值
await characteristic.write(subData[i], withoutResponse: true);
} else if (characteristic.properties.write) {
// 使用WRITE属性写入值
await characteristic.write(subData[i]);
} else {
// 特性不支持写入
2024-05-07 16:45:59 +08:00
throw Exception(
'This characteristic does not support writing.');
}
}
} on Exception catch (e, s) {
AppLog.log('APP写入失败: $e $s');
rethrow;
}
}
}
2023-08-09 10:07:27 +08:00
}
}
2023-08-08 09:42:35 +08:00
}
2023-12-27 10:47:58 +08:00
// 停止扫描蓝牙设备
Future<void> stopScan() async {
try {
await FlutterBluePlus.stopScan();
AppLog.log('调用停止扫描成功');
} catch (e) {
2024-05-20 16:37:49 +08:00
AppLog.log('停止扫描失败');
}
}
2023-12-27 10:47:58 +08:00
// 断开连接
Future<void> disconnect() async {
2023-12-27 10:47:58 +08:00
try {
2024-05-20 16:37:49 +08:00
connectDeviceMacAddress = '';
if (bluetoothConnectionState == BluetoothConnectionState.connected) {
//加快蓝牙断连
await bluetoothConnectDevice!.disconnect(timeout: 3);
2024-05-20 16:37:49 +08:00
AppLog.log('断开连接成功');
}
2023-12-27 10:47:58 +08:00
} on Exception catch (e, _) {
2024-05-20 16:37:49 +08:00
AppLog.log('断开连接失败: $e');
2023-12-27 10:47:58 +08:00
} finally {
bluetoothConnectionState = BluetoothConnectionState.disconnected;
2023-12-27 10:47:58 +08:00
}
}
Future<void> openBlue() async {
if (Platform.isAndroid) {
await FlutterBluePlus.turnOn();
}
if (Platform.isIOS) {
2024-05-20 16:37:49 +08:00
EasyLoading.showToast('请开启蓝牙'.tr, duration: 2000.milliseconds);
}
}
void disposed() {
_sendStreamSubscription?.cancel();
_mtuSubscription!.cancel();
_adapterStateStateSubscription!.cancel();
_connectionStateSubscription!.cancel();
}
}