From 63fa85f5fea2ede40d3c61c1439c71ef9c29e616 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=AD=8F=E5=B0=91=E9=98=B3?= <786612630@qq.com> Date: Tue, 23 Jul 2024 15:02:57 +0800 Subject: [PATCH] =?UTF-8?q?1=E3=80=81=E6=B7=BB=E5=8A=A0=E8=8E=B7=E5=8F=96?= =?UTF-8?q?=E9=81=A5=E6=8E=A7=E5=BC=80=E9=94=81=E8=AE=B0=E5=BD=95=E9=97=AE?= =?UTF-8?q?=E9=A2=98=E3=80=822=E3=80=81=E6=B7=BB=E5=8A=A0=E9=81=A5?= =?UTF-8?q?=E6=8E=A7=E6=95=B0=E6=8D=AE=E5=90=8C=E6=AD=A5=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 4 +- .../io_updataLockRemoteControlList.dart | 119 ++++++++++++++++++ lib/blue/io_type.dart | 1 + lib/blue/reciver_data.dart | 6 + lib/blue/sender_manage.dart | 26 ++++ .../otherTypeKeyChangeDate_page.dart | 1 - .../lockOperatingRecord_logic.dart | 1 + .../lockOperatingRecord_state.dart | 2 +- .../lockSet/faceUnlock/faceUnlock_logic.dart | 3 - .../lockSet/faceUnlock/faceUnlock_page.dart | 5 +- .../lockSet/uploadData/uploadData_logic.dart | 104 ++++++++++++++- .../lockSet/uploadData/uploadData_state.dart | 3 + .../remoteControlDetail_page.dart | 6 +- lib/network/api_provider.dart | 2 + lib/network/api_repository.dart | 2 + 15 files changed, 269 insertions(+), 16 deletions(-) create mode 100644 lib/blue/io_protocol/io_updataLockRemoteControlList.dart diff --git a/.gitignore b/.gitignore index ecc8fce9..b8807ff9 100755 --- a/.gitignore +++ b/.gitignore @@ -35,7 +35,6 @@ *.lock # Web related -lib/generated_plugin_registrant.dart # Symbolication related app.*.symbols @@ -58,10 +57,9 @@ flutter_plugins/*/example/ios/Flutter/flutter_export_environment.sh /flutter_plugins/flutter_html-2.1.5/example/ios/Runner/GeneratedPluginRegistrant.h /flutter_plugins/flutter_html-2.1.5/example/ios/Runner/GeneratedPluginRegistrant.m /flutter_plugins/flutter_html-2.1.5/example/android/app/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java -/flutter_plugins/flutter_html-2.1.5/example/lib/generated_plugin_registrant.dart https://build_sh.sh ios/Runner.app.dSYM.zip ios/Runner.ipa # 忽略打包生成的文件 -script/gen/* \ No newline at end of file +script/gen/* diff --git a/lib/blue/io_protocol/io_updataLockRemoteControlList.dart b/lib/blue/io_protocol/io_updataLockRemoteControlList.dart new file mode 100644 index 00000000..19cb5902 --- /dev/null +++ b/lib/blue/io_protocol/io_updataLockRemoteControlList.dart @@ -0,0 +1,119 @@ + +import 'dart:convert'; + +import 'package:crypto/crypto.dart' as crypto; + +import '../io_reply.dart'; +import '../io_sender.dart'; +import '../io_tool/io_tool.dart'; +import '../io_type.dart'; +import '../sm4Encipher/sm4.dart'; + +class UpdataLockRemoteControlListCommand extends SenderProtocol { + UpdataLockRemoteControlListCommand({ + this.lockID, + this.keyID, + this.userID, + this.page, + this.countReq, + this.token, + this.needAuthor, + this.signKey, + this.privateKey + }) : super(CommandType.updataLockRemoteControlList); + + String? lockID; + String? keyID; + String? userID; + int? page; + int? countReq; + List? token; + int? needAuthor; + List? signKey; + List? privateKey; + + @override + String toString() { + return 'UpdataLockCardListCommand{lockID: $lockID, keyID:$keyID userID: $userID, ' + 'page:$page countReq: $countReq, token: $token, ' + 'signKey: $signKey, privateKey: $privateKey}'; + } + + @override + List messageDetail() { + List data = []; + List ebcData = []; + + // 指令类型 + final int type = commandType!.typeValue; + final double typeDouble = type / 256; + final int type1 = typeDouble.toInt(); + final int type2 = type % 256; + data.add(type1); + data.add(type2); + + // 锁id 40 + final int lockIDLength = utf8.encode(lockID!).length; + data.addAll(utf8.encode(lockID!)); + data = getFixedLengthList(data, 40 - lockIDLength); + + //userID 要接受钥匙的用户的useid 20 + final int userIDLength = utf8.encode(userID!).length; + data.addAll(utf8.encode(userID!)); + data = getFixedLengthList(data, 20 - userIDLength); + + // page + data.add(page!); + + // countReq + data.add(countReq!); + + // token 长度4 首次请求 Token 填 0,如果锁需要鉴权 操作者身份,则会分配动态口令并在应答消息中返回,二次请求时带上。 当token失效或者第一次发送的时候token为0 + data.addAll(token!); + + if(needAuthor == 0){ + //AuthCodeLen 1 + data.add(0); + } else { + final List authCodeData = []; + //KeyID + authCodeData.addAll(utf8.encode(lockID!)); + + //UserID + authCodeData.addAll(utf8.encode(userID!)); + + //token 4 首次请求 Token 填 0,如果锁需要鉴权操作者身份,则会分配动态口令并在应答消息中返回,二次请求时带上。 + authCodeData.addAll(token!); + + authCodeData.addAll(signKey!); + + // 把KeyID、authUserID、时间戳、公钥通过md5加密之后就是authCode + final authCode = crypto.md5.convert(authCodeData); + + data.add(authCode.bytes.length); + data.addAll(authCode.bytes); + } + + if ((data.length % 16) != 0) { + final int add = 16 - data.length % 16; + for (int i = 0; i < add; i++) { + data.add(0); + } + } + + printLog(data); + // 拿到数据之后通过LockId进行SM4 ECB加密 key:544d485f633335373034383064613864 + ebcData = SM4.encrypt(data, key: privateKey, mode: SM4CryptoMode.ECB); + return ebcData; + } +} + +class UpdataLockRemoteControlListReply extends Reply { + UpdataLockRemoteControlListReply.parseData(CommandType commandType, List dataDetail) + : super.parseData(commandType, dataDetail) { + data = dataDetail; + + final int status = data[2]; + errorWithStstus(status); + } +} \ No newline at end of file diff --git a/lib/blue/io_type.dart b/lib/blue/io_type.dart index 9bb992c9..28780e82 100755 --- a/lib/blue/io_type.dart +++ b/lib/blue/io_type.dart @@ -15,6 +15,7 @@ enum CommandType { updataLockFingerprintList, //上传数据-获取锁指纹列表 0x3023 updataLockFaceList, //上传数据-获取锁指纹列表 0x3024 updataLockPalmVeinList, //上传数据-获取锁指纹列表 0x3025 + updataLockRemoteControlList, //上传数据-获取锁遥控列表 0x3026 updataLockSet, //上传数据-获取锁设置 0x302A getLockPublicKey, // 获取锁公钥 = 0x3090 getLockPrivateKey, // 获取锁私钥 = 0x3091 diff --git a/lib/blue/reciver_data.dart b/lib/blue/reciver_data.dart index d57f4c3e..4e15480e 100755 --- a/lib/blue/reciver_data.dart +++ b/lib/blue/reciver_data.dart @@ -45,6 +45,7 @@ import 'io_protocol/io_updataLockFaceList.dart'; import 'io_protocol/io_updataLockFingerprintList.dart'; import 'io_protocol/io_updataLockPalmVeinList.dart'; import 'io_protocol/io_updataLockPasswordList.dart'; +import 'io_protocol/io_updataLockRemoteControlList.dart'; import 'io_protocol/io_updataLockSet.dart'; import 'io_reply.dart'; import 'io_tool/io_manager.dart'; @@ -238,6 +239,11 @@ class CommandReciverManager { reply = UpdataLockPalmVeinListReply.parseData(commandType, data); } break; + case CommandType.updataLockRemoteControlList: + { + reply = UpdataLockRemoteControlListReply.parseData(commandType, data); + } + break; case CommandType.updataLockSet: { reply = UpdataLockSetReply.parseData(commandType, data); diff --git a/lib/blue/sender_manage.dart b/lib/blue/sender_manage.dart index 20cd27b9..329e05f2 100755 --- a/lib/blue/sender_manage.dart +++ b/lib/blue/sender_manage.dart @@ -43,6 +43,7 @@ import 'io_protocol/io_updataLockFaceList.dart'; import 'io_protocol/io_updataLockFingerprintList.dart'; import 'io_protocol/io_updataLockPalmVeinList.dart'; import 'io_protocol/io_updataLockPasswordList.dart'; +import 'io_protocol/io_updataLockRemoteControlList.dart'; import 'io_protocol/io_updataLockSet.dart'; import 'sender_data.dart'; @@ -1414,6 +1415,31 @@ class IoSenderManage { callBack: callBack); } + // 上传数据获取锁掌静脉列表 + static void updataLockRemoteControlListCommand( + {required String? lockID, + required String? userID, + required int? page, + required int? countReq, + required List? token, + required int? needAuthor, + required List? signKey, + required List? privateKey, + CommandSendCallBack? callBack}) { + CommandSenderManager().managerSendData( + command: UpdataLockRemoteControlListCommand( + lockID: lockID, + userID: userID, + page:page, + countReq:countReq, + token: token, + needAuthor: needAuthor, + signKey: signKey, + privateKey: privateKey, + ), + callBack: callBack); + } + // 上传数据获取锁设置 static void updataLockSetCommand( {required String? lockID, diff --git a/lib/main/lockDetail/card/otherTypeKeyChangeDate/otherTypeKeyChangeDate_page.dart b/lib/main/lockDetail/card/otherTypeKeyChangeDate/otherTypeKeyChangeDate_page.dart index f56fded8..880158a1 100755 --- a/lib/main/lockDetail/card/otherTypeKeyChangeDate/otherTypeKeyChangeDate_page.dart +++ b/lib/main/lockDetail/card/otherTypeKeyChangeDate/otherTypeKeyChangeDate_page.dart @@ -1,4 +1,3 @@ -import 'dart:ffi'; import 'package:flutter/material.dart'; import 'package:flutter_easyloading/flutter_easyloading.dart'; diff --git a/lib/main/lockDetail/lockOperatingRecord/lockOperatingRecord_logic.dart b/lib/main/lockDetail/lockOperatingRecord/lockOperatingRecord_logic.dart index 6d710392..0f16a437 100755 --- a/lib/main/lockDetail/lockOperatingRecord/lockOperatingRecord_logic.dart +++ b/lib/main/lockDetail/lockOperatingRecord/lockOperatingRecord_logic.dart @@ -151,6 +151,7 @@ class LockOperatingRecordLogic extends BaseGetXController { fingerprintId: state.type == 3 ? state.idStr : '', keyId: state.type == 5 ? state.idStr : '', faceId: state.type == 4 ? state.idStr : '', + remoteId:state.type == 6 ? state.idStr : '', pageSize:pageSize, ); if (entity.errorCode!.codeIsSuccessful) { diff --git a/lib/main/lockDetail/lockOperatingRecord/lockOperatingRecord_state.dart b/lib/main/lockDetail/lockOperatingRecord/lockOperatingRecord_state.dart index 8f96ed49..308daede 100755 --- a/lib/main/lockDetail/lockOperatingRecord/lockOperatingRecord_state.dart +++ b/lib/main/lockDetail/lockOperatingRecord/lockOperatingRecord_state.dart @@ -29,6 +29,6 @@ class LockOperatingRecordState { // 记录名称 bool ifHaveNext = false; // 页码 int logCountPage = 10; // 蓝牙记录一页多少个 String idStr = ''; // - int type = 0; // 1:密码 2:卡 3:指纹 4:人脸 5:钥匙 + int type = 0; // 1:密码 2:卡 3:指纹 4:人脸 5:钥匙 6:遥控 RxString recordName = ''.obs; } diff --git a/lib/main/lockDetail/lockSet/faceUnlock/faceUnlock_logic.dart b/lib/main/lockDetail/lockSet/faceUnlock/faceUnlock_logic.dart index 4d07b6bc..1f065db9 100755 --- a/lib/main/lockDetail/lockSet/faceUnlock/faceUnlock_logic.dart +++ b/lib/main/lockDetail/lockSet/faceUnlock/faceUnlock_logic.dart @@ -28,7 +28,6 @@ class FaceUnlockLogic extends BaseGetXController { if (entity.errorCode!.codeIsSuccessful) { showToast('设置成功'.tr, something: (){ eventBus.fire(PassCurrentLockInformationEvent(state.lockSetInfoData.value)); - Get.back(); }); } } @@ -58,7 +57,6 @@ class FaceUnlockLogic extends BaseGetXController { if (entity.errorCode!.codeIsSuccessful) { showToast('设置成功'.tr, something: (){ eventBus.fire(PassCurrentLockInformationEvent(state.lockSetInfoData.value)); - Get.back(); }); } } @@ -72,7 +70,6 @@ class FaceUnlockLogic extends BaseGetXController { if (entity.errorCode!.codeIsSuccessful) { showToast('设置成功'.tr, something: (){ eventBus.fire(PassCurrentLockInformationEvent(state.lockSetInfoData.value)); - Get.back(); }); } } diff --git a/lib/main/lockDetail/lockSet/faceUnlock/faceUnlock_page.dart b/lib/main/lockDetail/lockSet/faceUnlock/faceUnlock_page.dart index cdcedb5f..8ebd87bc 100755 --- a/lib/main/lockDetail/lockSet/faceUnlock/faceUnlock_page.dart +++ b/lib/main/lockDetail/lockSet/faceUnlock/faceUnlock_page.dart @@ -71,10 +71,7 @@ class _FaceUnlockPageState extends State { }); // _openBottomItemSheet(state.antiMisoperationStrList.value, 1); }), - Expanded( - child: SizedBox( - height: 30.h, - )), + Expanded(child: SizedBox(height: 30.h)), _buildTipsView(), SizedBox( height: 60.h, diff --git a/lib/main/lockDetail/lockSet/uploadData/uploadData_logic.dart b/lib/main/lockDetail/lockSet/uploadData/uploadData_logic.dart index d439337b..af8a465e 100644 --- a/lib/main/lockDetail/lockSet/uploadData/uploadData_logic.dart +++ b/lib/main/lockDetail/lockSet/uploadData/uploadData_logic.dart @@ -2,6 +2,7 @@ import 'dart:async'; import 'package:flutter_blue_plus/flutter_blue_plus.dart'; +import 'package:star_lock/blue/io_protocol/io_updataLockRemoteControlList.dart'; import 'package:star_lock/login/login/entity/LoginEntity.dart'; import 'package:star_lock/tools/baseGetXController.dart'; import 'package:star_lock/tools/commonDataManage.dart'; @@ -53,6 +54,11 @@ class UploadDataLogic extends BaseGetXController{ _replyUpdataLockPalmVeinListReply(reply); } + // 上传数据获取锁遥控 + if (reply is UpdataLockRemoteControlListReply && (state.ifCurrentScreen.value == true)) { + _replyUpdataLockRemoteControlListReply(reply); + } + // 上传数据获取锁设置 if (reply is UpdataLockSetReply && (state.ifCurrentScreen.value == true) && (state.ifSeletUpdataBtnState == true)) { _replyUpdataLockSetReply(reply); @@ -291,6 +297,52 @@ class UploadDataLogic extends BaseGetXController{ } } + // 上传数据获取锁遥控列表解析 + Future _replyUpdataLockRemoteControlListReply(Reply reply) async { + final int status = reply.data[2]; + switch(status){ + case 0x00: + //成功 + state.indexCount.value = state.indexCount.value + 1; + dismissEasyLoading(); + cancelBlueConnetctToastTimer(); + + final int dataLength = reply.data[8]; + state.uploadRemoteControlDataList.addAll(reply.data.sublist(9, reply.data.length)); + if(dataLength == 10){ + // 当数据是10的时候继续请求 + state.uploadRemoteControlPage = state.uploadRemoteControlPage + 1; + + final List token = reply.data.sublist(3, 7); + updataLockRemoteControlList(token, state.uploadRemoteControlPage); + }else{ + // // 当数据不是10的时候解析数据上传 + // if(state.uploadPalmVeinDataList.isEmpty){ + // // 不需要上传 如果是空的直接上传下一个 + // getUpdataLockSet(); + // }else{ + // // 如果不是空的解析数据上传 + _lockDataUpload(uploadType:2, recordType:7, records:state.uploadRemoteControlDataList); + // } + } + break; + case 0x06: + //无权限 + final List token = reply.data.sublist(3, 7); + final List saveStrList = changeIntListToStringList(token); + Storage.setStringList(saveBlueToken, saveStrList); + + updataLockRemoteControlList(token, state.uploadRemoteControlPage); + break; + default: + dismissEasyLoading(); + state.sureBtnState.value = 0; + state.indexCount.value = 0; + cancelBlueConnetctToastTimer(); + break; + } + } + // 上传数据获取锁设置解析 Future _replyUpdataLockSetReply(Reply reply) async { final int status = reply.data[2]; @@ -555,6 +607,52 @@ class UploadDataLogic extends BaseGetXController{ ); } + // 上传数据获取锁遥控列表 + Future getUpdataLockRemoteControlList() async { + showEasyLoading(); + showBlueConnetctToastTimer(action: (){ + dismissEasyLoading(); + state.indexCount.value = 0; + state.sureBtnState.value = 0; + }); + BlueManage().blueSendData(BlueManage().connectDeviceName, (BluetoothConnectionState connectionState) async { + if (connectionState == BluetoothConnectionState.connected) { + final List? token = await Storage.getStringList(saveBlueToken); + final List getTokenList = changeStringListToIntList(token!); + + updataLockRemoteControlList(getTokenList, state.uploadRemoteControlPage); + } else if (connectionState == BluetoothConnectionState.disconnected) { + dismissEasyLoading(); + cancelBlueConnetctToastTimer(); + state.sureBtnState.value = 0; + state.indexCount.value = 0; + if(state.ifCurrentScreen.value == true){ + showBlueConnetctToast(); + } + } + }); + } + + // 公共的获取遥控列表 + Future updataLockRemoteControlList(List token, int page) async { + final List? privateKey = await Storage.getStringList(saveBluePrivateKey); + final List getPrivateKeyList = changeStringListToIntList(privateKey!); + + final List? signKey = await Storage.getStringList(saveBlueSignKey); + final List signKeyDataList = changeStringListToIntList(signKey!); + + IoSenderManage.updataLockRemoteControlListCommand( + lockID: BlueManage().connectDeviceName, + userID: await Storage.getUid(), + page: page, + countReq: state.countReq, + token: token, + needAuthor: 1, + signKey: signKeyDataList, + privateKey: getPrivateKeyList + ); + } + // 上传数据获取设置 Future getUpdataLockSet() async { showEasyLoading(); @@ -642,7 +740,11 @@ class UploadDataLogic extends BaseGetXController{ getUpdataLockPalmVeinList(); break; case 6: - // 掌静脉上传成功,获取锁设置 + // 掌静脉上传成功,获取锁遥控 + getUpdataLockRemoteControlList(); + break; + case 7: + // 遥控上传成功,获取锁设置 getUpdataLockSet(); break; default: diff --git a/lib/main/lockDetail/lockSet/uploadData/uploadData_state.dart b/lib/main/lockDetail/lockSet/uploadData/uploadData_state.dart index d2d0ac52..adf46afd 100644 --- a/lib/main/lockDetail/lockSet/uploadData/uploadData_state.dart +++ b/lib/main/lockDetail/lockSet/uploadData/uploadData_state.dart @@ -24,5 +24,8 @@ class UploadDataState{ int uploadPalmVeinPage = 0;// 上传掌静脉的页数 List uploadPalmVeinDataList = [];// 上传掌静脉的数据 + int uploadRemoteControlPage = 0;// 上传遥控的页数 + List uploadRemoteControlDataList = [];// 上传遥控的数据 + List uploadLockSetDataList = [];// 上传锁设置数据 } \ No newline at end of file diff --git a/lib/main/lockDetail/remoteControl/remoteControlDetail/remoteControlDetail_page.dart b/lib/main/lockDetail/remoteControl/remoteControlDetail/remoteControlDetail_page.dart index dcc396db..585c749d 100755 --- a/lib/main/lockDetail/remoteControl/remoteControlDetail/remoteControlDetail_page.dart +++ b/lib/main/lockDetail/remoteControl/remoteControlDetail/remoteControlDetail_page.dart @@ -196,9 +196,9 @@ class _RemoteControlDetailPageState extends State with action: () { Get.toNamed(Routers.lockOperatingRecordPage, arguments: { - 'type': 2, - 'id': state.fingerprintItemData.value.cardId.toString(), - 'recordName': state.fingerprintItemData.value.cardName + 'type': 6, + 'id': state.fingerprintItemData.value.remoteId.toString(), + 'recordName': state.fingerprintItemData.value.remoteName }); }), // SizedBox(height: 40.h), diff --git a/lib/network/api_provider.dart b/lib/network/api_provider.dart index c0df687b..8499afa5 100755 --- a/lib/network/api_provider.dart +++ b/lib/network/api_provider.dart @@ -286,6 +286,7 @@ class ApiProvider extends BaseProvider { required String fingerprintId, required String keyId, required String faceId, + required String remoteId, required String pageSize}) => post( keyOperationRecordURL.toUrl, @@ -301,6 +302,7 @@ class ApiProvider extends BaseProvider { 'fingerprintId': fingerprintId, 'keyId': keyId, 'faceId': faceId, + 'remoteId': remoteId, 'pageSize': pageSize })); diff --git a/lib/network/api_repository.dart b/lib/network/api_repository.dart index 43f72529..d41935dd 100755 --- a/lib/network/api_repository.dart +++ b/lib/network/api_repository.dart @@ -253,6 +253,7 @@ class ApiRepository { required String fingerprintId, required String keyId, required String faceId, + required String remoteId, required String pageSize, }) async { final res = await apiProvider.lockRecordList( @@ -267,6 +268,7 @@ class ApiRepository { fingerprintId: fingerprintId, keyId: keyId, faceId: faceId, + remoteId: remoteId, pageSize: pageSize, ); return KeyOperationRecordEntity.fromJson(res.body);