import 'dart:async'; import 'dart:convert'; import 'dart:io'; import 'dart:typed_data'; import 'package:crypto/crypto.dart'; import 'package:file_picker/file_picker.dart'; import 'package:flutter_blue_plus/flutter_blue_plus.dart'; import 'package:get/get.dart'; import 'package:permission_handler/permission_handler.dart'; import 'package:star_lock/blue/blue_manage.dart'; import 'package:star_lock/blue/io_protocol/io_otaUpgrade.dart'; import 'package:star_lock/blue/io_protocol/io_processOtaUpgrade.dart'; import 'package:star_lock/blue/io_reply.dart'; import 'package:star_lock/blue/io_tool/io_tool.dart'; import 'package:star_lock/blue/io_tool/manager_event_bus.dart'; import 'package:star_lock/blue/sender_manage.dart'; import 'package:star_lock/main/lockDetail/lockSet/lockSet/lockSet_logic.dart'; import 'package:star_lock/permission/permission_dialog.dart'; import 'package:star_lock/tools/baseGetXController.dart'; import 'package:star_lock/tools/commonDataManage.dart'; import 'package:star_lock/tools/storage.dart'; import '../../../../app_settings/app_settings.dart'; import 'lockEscalation_state.dart'; class LockEscalationLogic extends BaseGetXController { LockEscalationState state = LockEscalationState(); StreamSubscription? _replySubscription; int otaCount = 0; int otaIndex = 0; Uint8List? otaBin; int startSecond = 0; Map? headJson = null; // 锁升级 Future setLockSetGeneralSetting() async { // var entity = await ApiRepository.to.getLockVersionInfoData( // lockId: state.getKeyInfosData.value.lockId.toString(), // ); // if(entity.errorCode!.codeIsSuccessful){ // // } } //手动升级 Future otaUpdate() async { var status = await PermissionDialog.request( Permission.storage, '需要访问读写权限才能使用手动升级固件'.tr); if (status != true) { return; } FilePickerResult? result = await FilePicker.platform.pickFiles(); if (result == null || result.files.single.path is! String) { return; } File file = File(result.files.single.path!); Uint8List data = await file.readAsBytes(); headJson = await getHeadFile(data); if (headJson is! Map) { return; } otaBin = await checkFile(data, headJson!); if (otaBin == null) { return; } String md5Str = md5.convert(otaBin!).toString(); headJson!['fwMd5'] = md5Str; blueOTAUpgrade(headJson!, [0, 0, 0, 0]); } //蓝牙操作 ota 升级 void blueOTAUpgrade(Map data, List token) { BlueManage().bludSendData(BlueManage().connectDeviceName, (BluetoothConnectionState deviceConnectionState) async { if (deviceConnectionState == BluetoothConnectionState.connected) { var privateKey = await Storage.getStringList(saveBluePrivateKey); List getPrivateKeyList = changeStringListToIntList(privateKey!); var signKey = await Storage.getStringList(saveBlueSignKey); List signKeyDataList = changeStringListToIntList(signKey!); String uid = await Storage.getUid() ?? ''; BlueManage().writeCharacteristicWithResponse(OTAUpgradeCommand( lockID: BlueManage().connectDeviceName, userID: uid, keyID: BlueManage().connectDeviceName, platform: int.tryParse(data['platform']) ?? 0, product: int.tryParse(data['product']) ?? 0, hwVersion: data['hwVersion'], fwVersion: data['fwVersion'], fwSize: data['fwSize'], fwMD5: data['fwMd5'], needAuthor: 1, token: token, signKey: signKeyDataList, privateKey: getPrivateKeyList) .packageData()); } else if (deviceConnectionState == BluetoothConnectionState.disconnected) {} }); } //循环传输升级固件包 Future processOtaUpgrade() async { if (!state.otaUpdateIng.value) { return; } int length = otaBin?.length ?? 0; if (otaCount == 0) { //首次 int difference = length % 240; otaCount = length ~/ 240 + (difference > 0 ? 1 : 0); startSecond = DateTime.now().millisecondsSinceEpoch ~/ 1000; startOTAData(); } if (otaCount <= otaIndex) { int now = DateTime.now().millisecondsSinceEpoch ~/ 1000; String msg = '传输完成 时间:${now - startSecond}秒 otaCount:$otaCount otaIndex:$otaIndex '; closeOTADAta(); AppLog.log(msg); // showToast(msg); return; } int star = otaIndex * 240; int end = (otaIndex + 1) * 240; if (end > length) { end = length; } int size = end - star; List data = otaBin!.sublist(star, end); state.otaProgress.value = otaIndex / otaCount; await BlueManage().writeCharacteristicWithResponse( ProcessOtaUpgradeCommand(index: otaIndex, size: size, data: data) .packageData()); } //开始 ota升级 void startOTAData() { state.otaUpdateIng.value = true; } //清楚 ata 安装文件 void closeOTADAta() { state.otaUpdateIng.value = false; state.otaProgress.value = 0; otaIndex = 0; otaCount = 0; startSecond = 0; otaBin = null; } // 拦截返回事件 void getBack() { if (state.otaUpdateIng.value) { closeOTADAta(); } else { Get.back(); } } // 检查文件头 Future getHeadFile(Uint8List data) async { if (data.length <= 16) { showToast('错误固件,请选择正确的文件'.tr); return null; } // 检查文件头 String header; try { header = utf8.decode(data.sublist(0, 12)); } catch (e) { showToast('非SYD固件,请选择正确的文件'.tr); return null; } if (header != 'SYD-BIN-DATA') { showToast('非SYD固件,请选择正确的文件'.tr); return null; } // 解析元数据长度 Uint8List metaLenList; int metaLen; try { metaLenList = data.sublist(12, 16); metaLen = ByteData.sublistView(metaLenList).getUint32(0); } catch (e) { showToast('文件校验失败 0x01'.tr); return null; } if (metaLen < 2 || metaLen > 10240) { showToast('文件校验失败 0x01'.tr); return null; } // 读取和解析元数据 Uint8List metaStrList; String metaStr; try { metaStrList = data.sublist(16, 16 + metaLen); metaStr = utf8.decode(metaStrList); } catch (e) { showToast('解析元数据失败,请选择正确的文件'.tr); return null; } AppLog.log(metaStr); var meta = jsonDecode(metaStr); if (meta is! Map) { showToast('解析元数据失败,请选择正确的文件'.tr); return null; } return meta..['metaLen'] = metaLen; } //检测升级文件并读取 bin Future checkFile(Uint8List data, Map meta) async { num binOffset = 16 + (meta['metaLen'] ?? 0); // 获取固件数据部分 Uint8List bin = data.sublist(binOffset.toInt(), data.length); //md5 校验有问题,暂时不解析 String md5Str = md5.convert(bin).toString().toUpperCase(); AppLog.log('---> $md5Str ${meta['fwMd5']}'); if (md5Str != meta['fwMd5']) { showToast('文件校验失败 0x02'.tr); return null; } if (bin.length != meta['fwSize']) { showToast('文件校验失败 0x03'.tr); return null; } return bin; } @override void onReady() { super.onReady(); setLockSetGeneralSetting(); } @override void onInit() { super.onInit(); _replySubscription = EventBusManager().eventBus!.on().listen((reply) { if (reply is OTAUpgradeReply) { if (reply.status == 0x00) { //验证通过,开始发送数据包 startOTAData(); processOtaUpgrade(); } else if (reply.status == 0x06) { blueOTAUpgrade(headJson!, reply.token); } } else if (reply is ProcessOtaUpgradeReply && reply.status == 0x00) { otaIndex++; processOtaUpgrade(); } else if (reply is ConfirmationOTAUpgradeReply && reply.status == 0x00) { closeOTADAta(); showToast('固件升级完成'.tr); } }); } @override void onClose() { _replySubscription?.cancel(); } }