Browse Source

ota升级断开ble连接

weicu
tanlongsheng 1 year ago
parent
commit
7ad217a649
  1. 18
      lib/modules/ota_upgrade/controllers/ota_upgrade_controller.dart
  2. 39
      local_plugins/ble_service/ios/ble_service/Sources/ble_service/BleService.swift
  3. 11
      local_plugins/ble_service/ios/ble_service/Sources/ble_service/SwiftBleServicePlugin.swift
  4. 56
      local_plugins/ble_service/lib/ble_service.dart

18
lib/modules/ota_upgrade/controllers/ota_upgrade_controller.dart

@ -1,3 +1,5 @@
import 'package:ble_service/ble_service.dart';
import 'package:classic_bluetooth/classic_bluetooth.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:path/path.dart'; import 'package:path/path.dart';
@ -30,6 +32,8 @@ class OtaUpgradeController extends GetxController {
// 当前设备固件版本号 // 当前设备固件版本号
final RxString currentVersion = ''.obs; final RxString currentVersion = ''.obs;
String _address = '';
// 更新包地址,用于下载更新文件 // 更新包地址,用于下载更新文件
String updatepackageaddress = ''; String updatepackageaddress = '';
@ -50,6 +54,7 @@ class OtaUpgradeController extends GetxController {
// 蓝牙管理服务,用于获取设备信息和通信 // 蓝牙管理服务,用于获取设备信息和通信
final _bleManager = Get.find<BleManager>(); final _bleManager = Get.find<BleManager>();
final BleService _bleService = BleService();
final maxRetryAttempts = 3; // 最大重试次数 final maxRetryAttempts = 3; // 最大重试次数
int currentRetryCount = 0; int currentRetryCount = 0;
@ -68,6 +73,7 @@ class OtaUpgradeController extends GetxController {
@override @override
void onClose() { void onClose() {
jlota.onOtaClose(); jlota.onOtaClose();
_bleService.setEnterOta(false);
isUpgrade.value = false; isUpgrade.value = false;
super.onClose(); super.onClose();
} }
@ -166,6 +172,16 @@ class OtaUpgradeController extends GetxController {
currentVersion.value = firstPart; currentVersion.value = firstPart;
print('getequipmentinfo,id: ${deviceInfo.firmwareProductId}'); print('getequipmentinfo,id: ${deviceInfo.firmwareProductId}');
final connectedDevices = await ClassicBluetooth.getConnectedDevices();
if (connectedDevices.isNotEmpty) {
_address = connectedDevices.first.address;
}
await _bleService.setEnterOta(true);
await _bleService.disconnect();
await Future.delayed(const Duration(seconds: 2));
jlota.init(); jlota.init();
// API请求 // API请求
@ -372,7 +388,7 @@ class OtaUpgradeController extends GetxController {
// 开始升级 // 开始升级
void startUpgrading(String path) async { void startUpgrading(String path) async {
jlota.startUpgrading(address: 'E9:09:05:E0:18:7A', filePath: path); jlota.startUpgrading(address: _address, filePath: path);
return; return;
// isUpgrade.value = false; // isUpgrade.value = false;
} }

39
local_plugins/ble_service/ios/ble_service/Sources/ble_service/BleService.swift

@ -43,6 +43,10 @@ public class BleService: NSObject {
private var audioCharacteristic: CBCharacteristic? private var audioCharacteristic: CBCharacteristic?
private var isScanning = false private var isScanning = false
// 是否是ota模式
var isEnterOta = false
private var callbacks = [Callback]() private var callbacks = [Callback]()
private var connectionState = BleConst.STATE_DISCONNECTED private var connectionState = BleConst.STATE_DISCONNECTED
@ -212,6 +216,9 @@ public class BleService: NSObject {
/// 统一的连接方法,支持恢复和重连 /// 统一的连接方法,支持恢复和重连
private func connectPeripheral(_ peripheral: CBPeripheral) { private func connectPeripheral(_ peripheral: CBPeripheral) {
if isEnterOta {
return
}
guard let manager = centralManager else { guard let manager = centralManager else {
return return
} }
@ -592,19 +599,14 @@ public class BleService: NSObject {
] ]
if !responseData.isEmpty { if !responseData.isEmpty {
if let versionStr = String(data: responseData, encoding: .utf8) { // 如果无法解析为字符串,以点分隔的数字表示版本
resultMap["version"] = versionStr let versionNums = responseData
os_log("接收到目标版本号: %@", log: logger, type: .info, versionStr) .map { $0 }
} else { .filter { $0 != 0xFF } // 过滤掉无效字节
// 如果无法解析为字符串,以点分隔的数字表示版本 .map { String($0) }
let versionNums = responseData .joined(separator: ".")
.map { $0 } resultMap["version"] = versionNums
.filter { $0 != 0xFF } // 过滤掉无效字节 os_log("接收到目标版本号(数字格式): %@", log: logger, type: .info, versionNums)
.map { String($0) }
.joined(separator: ".")
resultMap["version"] = versionNums
os_log("接收到目标版本号(数字格式): %@", log: logger, type: .info, versionNums)
}
} }
notifyDeviceInfoReceived(infoType: Int(cmd), infoData: resultMap) notifyDeviceInfoReceived(infoType: Int(cmd), infoData: resultMap)
@ -616,13 +618,8 @@ public class BleService: NSObject {
"rawData": responseData "rawData": responseData
] ]
if responseData.count >= 2 { if !responseData.isEmpty {
let productId = UInt16(responseData[0]) << 8 | UInt16(responseData[1]) let productId = responseData.map { String($0 & 0xFF) }.joined(separator: ".")
resultMap["productId"] = productId
os_log("接收到产品ID: %d", log: logger, type: .info, productId)
} else if !responseData.isEmpty {
// 单字节产品ID
let productId = UInt16(responseData[0])
resultMap["productId"] = productId resultMap["productId"] = productId
os_log("接收到产品ID: %d", log: logger, type: .info, productId) os_log("接收到产品ID: %d", log: logger, type: .info, productId)
} }
@ -1263,4 +1260,4 @@ extension BleService: CBPeripheralDelegate {
os_log("✅ 描述符写入成功: %{public}@", log: logger, type: .debug, descriptor.uuid.uuidString) os_log("✅ 描述符写入成功: %{public}@", log: logger, type: .debug, descriptor.uuid.uuidString)
} }
} }
} }

11
local_plugins/ble_service/ios/ble_service/Sources/ble_service/SwiftBleServicePlugin.swift

@ -150,6 +150,15 @@ public class SwiftBleServicePlugin: NSObject, FlutterPlugin {
case "isBleConnected": case "isBleConnected":
result(BleService.shared.isConnected()) result(BleService.shared.isConnected())
case "setEnterOta":
let arguments = call.arguments as? [String: Any]
BleService.shared.isEnterOta = (arguments?["enterOta"] as? Bool) ?? false
result("")
case "disconnect":
BleService.shared.disconnect()
result("")
case "registerBackgroundScan", "unregisterBackgroundScan": case "registerBackgroundScan", "unregisterBackgroundScan":
// iOS上禁用,直接返回成功以避免Flutter端报错 // iOS上禁用,直接返回成功以避免Flutter端报错
@ -380,4 +389,4 @@ class BleStatusStreamHandler: NSObject, FlutterStreamHandler {
plugin?.statusEventSink = nil plugin?.statusEventSink = nil
return nil return nil
} }
} }

56
local_plugins/ble_service/lib/ble_service.dart

@ -183,34 +183,35 @@ class BleService {
return false; return false;
} }
} }
//======================================================================== //========================================================================
// 以下是Companion Device相关功能 // 以下是Companion Device相关功能
//======================================================================== //========================================================================
/// 检查设备是否支持Companion Device Manager /// 检查设备是否支持Companion Device Manager
/// ///
/// 返回设备是否支持Companion Device Manager API /// 返回设备是否支持Companion Device Manager API
/// 仅在Android 8.0及以上版本可用 /// 仅在Android 8.0及以上版本可用
Future<bool> isCompanionSupported() async { Future<bool> isCompanionSupported() async {
try { try {
final result = await _methodChannel.invokeMethod<bool>('isCompanionSupported'); final result =
await _methodChannel.invokeMethod<bool>('isCompanionSupported');
return result ?? false; return result ?? false;
} catch (e) { } catch (e) {
print('检查Companion设备支持失败: $e'); print('检查Companion设备支持失败: $e');
return false; return false;
} }
} }
/// 启动设备关联流程 /// 启动设备关联流程
/// ///
/// 弹出系统设备选择对话框,用户选择后将建立持久化关联 /// 弹出系统设备选择对话框,用户选择后将建立持久化关联
/// 关联成功后,应用将获得后台扫描和启动前台服务的特权 /// 关联成功后,应用将获得后台扫描和启动前台服务的特权
/// ///
/// [deviceNamePattern] 设备名称正则表达式,例如"MyHeadset.*" /// [deviceNamePattern] 设备名称正则表达式,例如"MyHeadset.*"
/// [serviceUuid] 可选的服务UUID /// [serviceUuid] 可选的服务UUID
/// [macAddress] 可选的MAC地址 /// [macAddress] 可选的MAC地址
/// ///
/// 返回是否成功启动关联流程 /// 返回是否成功启动关联流程
Future<bool> startDeviceAssociation({ Future<bool> startDeviceAssociation({
String? deviceNamePattern, String? deviceNamePattern,
@ -232,13 +233,14 @@ class BleService {
return false; return false;
} }
} }
/// 获取已关联的设备MAC地址 /// 获取已关联的设备MAC地址
/// ///
/// 返回已关联的设备MAC地址,如果没有则返回null /// 返回已关联的设备MAC地址,如果没有则返回null
Future<String?> getPairedMacAddress() async { Future<String?> getPairedMacAddress() async {
try { try {
final result = await _methodChannel.invokeMethod<String>('getPairedMacAddress'); final result =
await _methodChannel.invokeMethod<String>('getPairedMacAddress');
return result; return result;
} catch (e) { } catch (e) {
print('获取配对MAC地址失败: $e'); print('获取配对MAC地址失败: $e');
@ -246,9 +248,8 @@ class BleService {
} }
} }
/// 检查BLE连接状态 /// 检查BLE连接状态
/// ///
/// 返回BLE是否已连接 /// 返回BLE是否已连接
Future<bool> isBleConnected() async { Future<bool> isBleConnected() async {
try { try {
@ -260,11 +261,31 @@ class BleService {
} }
} }
/// 设置是否是ota模式
Future<void> setEnterOta(bool enterOta) async {
try {
await _methodChannel.invokeMethod<String>('setEnterOta', {
'enterOta': enterOta,
});
} catch (e) {
print('设置是否是ota模式失败: $e');
}
}
/// 断开连接
Future<void> disconnect() async {
try {
await _methodChannel.invokeMethod<String>('disconnect');
} catch (e) {
print('断开连接失败: $e');
}
}
/// 注册BLE后台扫描 /// 注册BLE后台扫描
/// ///
/// 注册后,即使应用被杀死,系统也会在检测到设备广播时唤醒应用 /// 注册后,即使应用被杀死,系统也会在检测到设备广播时唤醒应用
/// 这是确保设备可以在应用后台时被自动连接的关键功能 /// 这是确保设备可以在应用后台时被自动连接的关键功能
/// ///
/// [macAddress] 可选的设备MAC地址,如果不提供则使用已关联的设备 /// [macAddress] 可选的设备MAC地址,如果不提供则使用已关联的设备
Future<bool> registerBackgroundScan({String? macAddress}) async { Future<bool> registerBackgroundScan({String? macAddress}) async {
try { try {
@ -290,13 +311,14 @@ class BleService {
return false; return false;
} }
} }
/// 清除所有设备关联 /// 清除所有设备关联
/// ///
/// 用于重置设备关联状态,通常在用户主动解除关联或调试时使用 /// 用于重置设备关联状态,通常在用户主动解除关联或调试时使用
Future<bool> clearAssociations() async { Future<bool> clearAssociations() async {
try { try {
final result = await _methodChannel.invokeMethod<bool>('clearAssociations'); final result =
await _methodChannel.invokeMethod<bool>('clearAssociations');
return result ?? false; return result ?? false;
} catch (e) { } catch (e) {
print('清除设备关联失败: $e'); print('清除设备关联失败: $e');

Loading…
Cancel
Save