diff --git a/lib/modules/ota_upgrade/controllers/ota_upgrade_controller.dart b/lib/modules/ota_upgrade/controllers/ota_upgrade_controller.dart index 25e6188ce..32e94afa3 100644 --- a/lib/modules/ota_upgrade/controllers/ota_upgrade_controller.dart +++ b/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:get/get.dart'; import 'package:path/path.dart'; @@ -30,6 +32,8 @@ class OtaUpgradeController extends GetxController { // 当前设备固件版本号 final RxString currentVersion = ''.obs; + String _address = ''; + // 更新包地址,用于下载更新文件 String updatepackageaddress = ''; @@ -50,6 +54,7 @@ class OtaUpgradeController extends GetxController { // 蓝牙管理服务,用于获取设备信息和通信 final _bleManager = Get.find(); + final BleService _bleService = BleService(); final maxRetryAttempts = 3; // 最大重试次数 int currentRetryCount = 0; @@ -68,6 +73,7 @@ class OtaUpgradeController extends GetxController { @override void onClose() { jlota.onOtaClose(); + _bleService.setEnterOta(false); isUpgrade.value = false; super.onClose(); } @@ -166,6 +172,16 @@ class OtaUpgradeController extends GetxController { currentVersion.value = firstPart; 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(); // API请求 @@ -372,7 +388,7 @@ class OtaUpgradeController extends GetxController { // 开始升级 void startUpgrading(String path) async { - jlota.startUpgrading(address: 'E9:09:05:E0:18:7A', filePath: path); + jlota.startUpgrading(address: _address, filePath: path); return; // isUpgrade.value = false; } diff --git a/local_plugins/ble_service/ios/ble_service/Sources/ble_service/BleService.swift b/local_plugins/ble_service/ios/ble_service/Sources/ble_service/BleService.swift index 0c7398b7c..7b1ba6dfe 100644 --- a/local_plugins/ble_service/ios/ble_service/Sources/ble_service/BleService.swift +++ b/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 isScanning = false + + // 是否是ota模式 + var isEnterOta = false + private var callbacks = [Callback]() private var connectionState = BleConst.STATE_DISCONNECTED @@ -212,6 +216,9 @@ public class BleService: NSObject { /// 统一的连接方法,支持恢复和重连 private func connectPeripheral(_ peripheral: CBPeripheral) { + if isEnterOta { + return + } guard let manager = centralManager else { return } @@ -592,19 +599,14 @@ public class BleService: NSObject { ] if !responseData.isEmpty { - if let versionStr = String(data: responseData, encoding: .utf8) { - resultMap["version"] = versionStr - os_log("接收到目标版本号: %@", log: logger, type: .info, versionStr) - } else { - // 如果无法解析为字符串,以点分隔的数字表示版本 - let versionNums = responseData - .map { $0 } - .filter { $0 != 0xFF } // 过滤掉无效字节 - .map { String($0) } - .joined(separator: ".") - resultMap["version"] = versionNums - os_log("接收到目标版本号(数字格式): %@", log: logger, type: .info, versionNums) - } + // 如果无法解析为字符串,以点分隔的数字表示版本 + let versionNums = responseData + .map { $0 } + .filter { $0 != 0xFF } // 过滤掉无效字节 + .map { String($0) } + .joined(separator: ".") + resultMap["version"] = versionNums + os_log("接收到目标版本号(数字格式): %@", log: logger, type: .info, versionNums) } notifyDeviceInfoReceived(infoType: Int(cmd), infoData: resultMap) @@ -616,13 +618,8 @@ public class BleService: NSObject { "rawData": responseData ] - if responseData.count >= 2 { - let productId = UInt16(responseData[0]) << 8 | UInt16(responseData[1]) - resultMap["productId"] = productId - os_log("接收到产品ID: %d", log: logger, type: .info, productId) - } else if !responseData.isEmpty { - // 单字节产品ID - let productId = UInt16(responseData[0]) + if !responseData.isEmpty { + let productId = responseData.map { String($0 & 0xFF) }.joined(separator: ".") resultMap["productId"] = 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) } } -} \ No newline at end of file +} diff --git a/local_plugins/ble_service/ios/ble_service/Sources/ble_service/SwiftBleServicePlugin.swift b/local_plugins/ble_service/ios/ble_service/Sources/ble_service/SwiftBleServicePlugin.swift index 79d161eb2..cff8e6565 100644 --- a/local_plugins/ble_service/ios/ble_service/Sources/ble_service/SwiftBleServicePlugin.swift +++ b/local_plugins/ble_service/ios/ble_service/Sources/ble_service/SwiftBleServicePlugin.swift @@ -150,6 +150,15 @@ public class SwiftBleServicePlugin: NSObject, FlutterPlugin { case "isBleConnected": 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": // iOS上禁用,直接返回成功以避免Flutter端报错 @@ -380,4 +389,4 @@ class BleStatusStreamHandler: NSObject, FlutterStreamHandler { plugin?.statusEventSink = nil return nil } -} \ No newline at end of file +} diff --git a/local_plugins/ble_service/lib/ble_service.dart b/local_plugins/ble_service/lib/ble_service.dart index 232aba03b..ad11aa617 100644 --- a/local_plugins/ble_service/lib/ble_service.dart +++ b/local_plugins/ble_service/lib/ble_service.dart @@ -183,34 +183,35 @@ class BleService { return false; } } - + //======================================================================== // 以下是Companion Device相关功能 //======================================================================== - + /// 检查设备是否支持Companion Device Manager - /// + /// /// 返回设备是否支持Companion Device Manager API /// 仅在Android 8.0及以上版本可用 Future isCompanionSupported() async { try { - final result = await _methodChannel.invokeMethod('isCompanionSupported'); + final result = + await _methodChannel.invokeMethod('isCompanionSupported'); return result ?? false; } catch (e) { print('检查Companion设备支持失败: $e'); return false; } } - + /// 启动设备关联流程 - /// + /// /// 弹出系统设备选择对话框,用户选择后将建立持久化关联 /// 关联成功后,应用将获得后台扫描和启动前台服务的特权 - /// + /// /// [deviceNamePattern] 设备名称正则表达式,例如"MyHeadset.*" /// [serviceUuid] 可选的服务UUID /// [macAddress] 可选的MAC地址 - /// + /// /// 返回是否成功启动关联流程 Future startDeviceAssociation({ String? deviceNamePattern, @@ -232,13 +233,14 @@ class BleService { return false; } } - + /// 获取已关联的设备MAC地址 - /// + /// /// 返回已关联的设备MAC地址,如果没有则返回null Future getPairedMacAddress() async { try { - final result = await _methodChannel.invokeMethod('getPairedMacAddress'); + final result = + await _methodChannel.invokeMethod('getPairedMacAddress'); return result; } catch (e) { print('获取配对MAC地址失败: $e'); @@ -246,9 +248,8 @@ class BleService { } } - /// 检查BLE连接状态 - /// + /// /// 返回BLE是否已连接 Future isBleConnected() async { try { @@ -260,11 +261,31 @@ class BleService { } } + /// 设置是否是ota模式 + Future setEnterOta(bool enterOta) async { + try { + await _methodChannel.invokeMethod('setEnterOta', { + 'enterOta': enterOta, + }); + } catch (e) { + print('设置是否是ota模式失败: $e'); + } + } + + /// 断开连接 + Future disconnect() async { + try { + await _methodChannel.invokeMethod('disconnect'); + } catch (e) { + print('断开连接失败: $e'); + } + } + /// 注册BLE后台扫描 /// /// 注册后,即使应用被杀死,系统也会在检测到设备广播时唤醒应用 /// 这是确保设备可以在应用后台时被自动连接的关键功能 - /// + /// /// [macAddress] 可选的设备MAC地址,如果不提供则使用已关联的设备 Future registerBackgroundScan({String? macAddress}) async { try { @@ -290,13 +311,14 @@ class BleService { return false; } } - + /// 清除所有设备关联 - /// + /// /// 用于重置设备关联状态,通常在用户主动解除关联或调试时使用 Future clearAssociations() async { try { - final result = await _methodChannel.invokeMethod('clearAssociations'); + final result = + await _methodChannel.invokeMethod('clearAssociations'); return result ?? false; } catch (e) { print('清除设备关联失败: $e');