From 3a43d8972569d14c48a4b27e0942df22228d7b8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=AD=8F=E5=B0=91=E9=98=B3?= <786612630@qq.com> Date: Wed, 30 Aug 2023 18:36:02 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E8=87=AA=E5=AE=9A=E4=B9=89?= =?UTF-8?q?=E5=AF=86=E7=A0=81=E5=8D=8F=E8=AE=AE=E5=8F=8A=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../io_protocol/io_senderCustomPasswords.dart | 146 ++++++++++++++++++ star_lock/lib/blue/reciver_data.dart | 29 ++++ star_lock/lib/blue/sender_manage.dart | 62 ++++++-- .../authorizedAdmin_logic.dart | 133 ++++++++++++++++ .../authorizedAdmin/authorizedAdmin_page.dart | 6 +- .../authorizedAdmin_state.dart | 4 + .../lockDetail/lockDetail_logic.dart | 29 ---- .../passwordKey_perpetual_logic.dart | 133 ++++++++++++++++ 8 files changed, 496 insertions(+), 46 deletions(-) create mode 100644 star_lock/lib/blue/io_protocol/io_senderCustomPasswords.dart create mode 100644 star_lock/lib/main/lockDetail/authorizedAdmin/authorizedAdmin/authorizedAdmin_logic.dart create mode 100644 star_lock/lib/main/lockDetail/authorizedAdmin/authorizedAdmin/authorizedAdmin_state.dart create mode 100644 star_lock/lib/main/lockDetail/passwordKey/passwordKey_perpetual/passwordKey_perpetual_logic.dart diff --git a/star_lock/lib/blue/io_protocol/io_senderCustomPasswords.dart b/star_lock/lib/blue/io_protocol/io_senderCustomPasswords.dart new file mode 100644 index 00000000..5aad1c7f --- /dev/null +++ b/star_lock/lib/blue/io_protocol/io_senderCustomPasswords.dart @@ -0,0 +1,146 @@ + +import 'dart:convert'; + +import '../io_tool/io_tool.dart'; +import '../sm4Encipher/sm4.dart'; +import 'io_reply.dart'; +import 'io_sender.dart'; +import 'io_type.dart'; +import 'package:crypto/crypto.dart' as crypto; + +//TODO:设置自定义密码 +/* +备注:删除单个密码规则:pwd 设置为 6 个 0,UseCountLimit 设置为 0。删除全部密码规则:pwd 设置为 6 个 0,UseCountLimit 设置为 0,pwdNo 设置为 255,userId 设置为“DeleteAll !@#”,只有门锁管理员才有权限 +**/ +class SenderCustomPasswordsCommand extends SenderProtocol { + + String? keyID; + String? userID; + int? pwdNo; + String? pwd; + int? useCountLimit; + List? token; + int? startTime; + int? endTime; + int? needAuthor; + List? publicKey; + List? privateKey; + + SenderCustomPasswordsCommand({ + this.keyID, + this.userID, + this.pwdNo, + this.pwd, + this.useCountLimit, + this.token, + this.startTime, + this.endTime, + this.needAuthor, + this.publicKey, + this.privateKey, + }) : super(CommandType.generalExtendedCommond); + + @override + List messageDetail() { + List data = []; + List subData = []; + List ebcData = []; + + // 指令类型 + int type = commandType!.typeValue; + double typeDouble = type / 256; + int type1 = typeDouble.toInt(); + int type2 = type % 256; + data.add(type1); + data.add(type2); + + // 子命令类型 + data.add(3); + + // keyID 40 + int keyIDLength = utf8.encode(keyID!).length; + // print("${commandType!.typeValue}LockIDLength:$lockIDLength utf8.encode(lockID!)${utf8.encode(lockID!)}"); + subData.addAll(utf8.encode(keyID!)); + subData = getFixedLengthList(subData, 40 - keyIDLength); + + //userID 20 + int userIDLength = utf8.encode(userID!).length; + // print("${commandType!.typeValue}IDLength:$authUserIDLength utf8.encode(authUserID!)${utf8.encode(authUserID!)}"); + subData.addAll(utf8.encode(userID!)); + subData = getFixedLengthList(subData, 20 - userIDLength); + + // PwdNo + subData.add(1); + + // pwd 20 + int pwdLength = utf8.encode(pwd!).length; + // print("${commandType!.typeValue}keyIDLength:$keyIDLength utf8.encode(keyID!)${utf8.encode(keyID!)}"); + subData.addAll(utf8.encode(pwd!)); + subData = getFixedLengthList(subData, 20 - pwdLength); + + // UseCountLimit + subData.add(0xff); + + // token + subData.addAll(token!); + + // startTime 4 + subData.add((startTime! & 0xff000000) >> 24); + subData.add((startTime! & 0xff0000) >> 16); + subData.add((startTime! & 0xff00) >> 8); + subData.add((startTime! & 0xff)); + + // endTime 4 + subData.add((endTime! & 0xff000000) >> 24); + subData.add((endTime! & 0xff0000) >> 16); + subData.add((endTime! & 0xff00) >> 8); + subData.add((endTime! & 0xff)); + + if(needAuthor == 0){ + //AuthCodeLen 1 + subData.add(0); + } else { + List authCodeData = []; + + //authUserID + authCodeData.addAll(utf8.encode(userID!)); + + //KeyID + authCodeData.addAll(utf8.encode(keyID!)); + + //token 4 首次请求 Token 填 0,如果锁需要鉴权操作者身份,则会分配动态口令并在应答消息中返回,二次请求时带上。 + authCodeData.addAll(token!); + + authCodeData.addAll(publicKey!); + + print("${commandType!.typeValue}-authCodeData:$authCodeData"); + + // 把KeyID、authUserID、时间戳、公钥通过md5加密之后就是authCode + var authCode = crypto.md5.convert(authCodeData); + + subData.add(authCode.bytes.length); + subData.addAll(authCode.bytes); + } + + data.add(subData.length); + data.addAll(subData); + + if ((data.length % 16) != 0) { + int add = (16 - data.length % 16); + for (int i = 0; i < add; i++) { + data.add(0); + } + } + print("${commandType!.typeName} SM4Data:$data"); + // 拿到数据之后通过LockId进行SM4 ECB加密 key:544d485f633335373034383064613864 + ebcData = SM4.encrypt(data, key: privateKey, mode: SM4CryptoMode.ECB); + return ebcData; + } +} + +class SenderCustomPasswordsReply extends Reply { + SenderCustomPasswordsReply.parseData(CommandType commandType, List dataDetail) + : super.parseData(commandType, dataDetail) { + data = dataDetail; + } +} \ No newline at end of file diff --git a/star_lock/lib/blue/reciver_data.dart b/star_lock/lib/blue/reciver_data.dart index 5814d185..071d2f4d 100644 --- a/star_lock/lib/blue/reciver_data.dart +++ b/star_lock/lib/blue/reciver_data.dart @@ -16,6 +16,7 @@ import 'io_protocol/io_getPrivateKey.dart'; import 'io_protocol/io_getPublicKey.dart'; import 'io_protocol/io_openLock.dart'; import 'io_protocol/io_reply.dart'; +import 'io_protocol/io_senderCustomPasswords.dart'; import 'io_protocol/io_type.dart'; import 'io_tool/io_manager.dart'; import 'io_tool/io_tool.dart'; @@ -143,8 +144,36 @@ class CommandReciverManager { reply = FactoryDataResetReply.parseData(commandType, data); } break; + case CommandType.generalExtendedCommond: + { + // 子命令类型 + int subType = data[3]; + switch(subType){ + case 3: + { + // 设置开锁密码 + reply = SenderCustomPasswordsReply.parseData(commandType, data); + } + break; + } + } + break; } return reply; } } + + static Future replySubCommand(CommandType commandType, List data){ + int subType = data[3]; + var reply; + switch(subType){ + case 3: + { + // 设置开锁密码 + reply = SenderCustomPasswordsReply.parseData(commandType, data); + } + break; + } + return reply; + } } \ No newline at end of file diff --git a/star_lock/lib/blue/sender_manage.dart b/star_lock/lib/blue/sender_manage.dart index 9a471bdc..489dfa9f 100644 --- a/star_lock/lib/blue/sender_manage.dart +++ b/star_lock/lib/blue/sender_manage.dart @@ -8,6 +8,7 @@ import 'io_protocol/io_factoryDataReset.dart'; import 'io_protocol/io_getPrivateKey.dart'; import 'io_protocol/io_getPublicKey.dart'; import 'io_protocol/io_openLock.dart'; +import 'io_protocol/io_senderCustomPasswords.dart'; import 'io_protocol/io_transferPermissions.dart'; import 'sender_data.dart'; @@ -175,15 +176,15 @@ class IoSenderManage { //todo:转移权限 static void senderTransferPermissions({ - String? lockID, - String? authUserID, - String? keyID, - String? oldUserID, - String? newUserID, - int? needAuthor, - List? publicKey, - List? privateKey, - List? token, + required String? lockID, + required String? authUserID, + required String? keyID, + required String? oldUserID, + required String? newUserID, + required int? needAuthor, + required List? publicKey, + required List? privateKey, + required List? token, CommandSendCallBack? callBack}) { CommandSenderManager().managerSendData( command: TransferPermissionsCommand( @@ -201,13 +202,13 @@ class IoSenderManage { //todo:恢复出厂设置 static void senderFactoryDataReset({ - String? lockID, - String? userID, - String? keyID, - List? publicKey, - List? privateKey, - List? token, - int? needAuthor, + required String? lockID, + required String? userID, + required String? keyID, + required List? publicKey, + required List? privateKey, + required List? token, + required int? needAuthor, CommandSendCallBack? callBack}) { CommandSenderManager().managerSendData( command: FactoryDataResetCommand( @@ -221,4 +222,33 @@ class IoSenderManage { ), callBack:callBack); } + //todo:设置开锁密码 + static void senderCustomPasswordsCommand({ + required String? keyID, + required String? userID, + required int? pwdNo, + required String? pwd, + required int? useCountLimit, + required List? token, + required int? startTime, + required int? endTime, + required int? needAuthor, + required List? publicKey, + required List? privateKey, + CommandSendCallBack? callBack}) { + CommandSenderManager().managerSendData( + command: SenderCustomPasswordsCommand( + keyID: keyID, + userID: userID, + pwdNo: pwdNo, + pwd:pwd, + useCountLimit: useCountLimit, + token: token, + startTime: startTime, + endTime: endTime, + needAuthor: needAuthor, + publicKey: publicKey, + privateKey: privateKey, + ), callBack:callBack); + } } \ No newline at end of file diff --git a/star_lock/lib/main/lockDetail/authorizedAdmin/authorizedAdmin/authorizedAdmin_logic.dart b/star_lock/lib/main/lockDetail/authorizedAdmin/authorizedAdmin/authorizedAdmin_logic.dart new file mode 100644 index 00000000..b8363ade --- /dev/null +++ b/star_lock/lib/main/lockDetail/authorizedAdmin/authorizedAdmin/authorizedAdmin_logic.dart @@ -0,0 +1,133 @@ + +import 'dart:async'; + +import 'package:flutter_reactive_ble/flutter_reactive_ble.dart'; +import 'package:star_lock/blue/io_protocol/io_type.dart'; + +import '../../../../blue/blue_manage.dart'; +import '../../../../blue/io_protocol/io_reply.dart'; +import '../../../../blue/io_protocol/io_transferPermissions.dart'; +import '../../../../blue/io_tool/io_manager.dart'; +import '../../../../blue/io_tool/io_tool.dart'; +import '../../../../blue/io_tool/manager_event_bus.dart'; +import '../../../../blue/sender_manage.dart'; +import '../../../../tools/baseGetXController.dart'; +import '../../../../tools/storage.dart'; +import 'authorizedAdmin_state.dart'; + +class AuthorizedAdminLogic extends BaseGetXController { + final AuthorizedAdminState state = AuthorizedAdminState(); + + // 监听设备返回的数据 + late StreamSubscription _replySubscription; + void _initReplySubscription() { + _replySubscription = EventBusManager().eventBus!.on().listen((reply) async { + // 开门 + if(reply is TransferPermissionsReply) { + var token = reply.data.sublist(2, 6); + var saveStrList = changeIntListToStringList(token); + print("_replyFactoryDataResetKeyToken:$token"); + Storage.setStringList(saveBlueToken, saveStrList); + + int status = reply.data[6]; + print("status:$status"); + + switch(status){ + case 0x00: + //成功 + print("${reply.commandType!.typeValue} 数据解析成功"); + + break; + case 0x06: + //无权限 + print("${reply.commandType!.typeValue} 需要鉴权"); + var privateKey = await Storage.getStringList(saveBluePrivateKey); + List getPrivateKeyList = changeStringListToIntList(privateKey!); + + var publicKey = await Storage.getStringList(saveBluePublicKey); + List publicKeyDataList = changeStringListToIntList(publicKey!); + + var token = await Storage.getStringList(saveBlueToken); + List getTokenList = changeStringListToIntList(token!); + + IoSenderManage.senderFactoryDataReset( + lockID:BlueManage().connectDeviceName, + userID:await Storage.getUserId(), + keyID:"1", + needAuthor:1, + publicKey:publicKeyDataList, + privateKey:getPrivateKeyList, + token: getTokenList + ); + break; + case 0x07: + //无权限 + print("${reply.commandType!.typeValue} 用户无权限"); + + break; + case 0x09: + // 权限校验错误 + print("${reply.commandType!.typeValue} 权限校验错误"); + + break; + default: + //失败 + print("${reply.commandType!.typeValue} 失败"); + + break; + } + } + }); + } + + // 转移权限 + Future transferPermissionsAction() async { + BlueManage().judgeReconnect(BlueManage().connectDeviceMacAddress, BlueManage().connectDeviceName, (DeviceConnectionState state) async { + if (state == DeviceConnectionState.connected){ + var privateKey = await Storage.getStringList(saveBluePrivateKey); + List getPrivateKeyList = changeStringListToIntList(privateKey!); + + var publicKey = await Storage.getStringList(saveBluePublicKey); + List publicKeyDataList = changeStringListToIntList(publicKey!); + + var token = await Storage.getStringList(saveBlueToken); + List getTokenList = changeStringListToIntList(token!); + print("openDoorTokenPubToken:$getTokenList"); + + IoSenderManage.senderTransferPermissions( + lockID:BlueManage().connectDeviceName, + authUserID:await Storage.getUserId(), + keyID:"1", + oldUserID:await Storage.getUserId(), + newUserID:"100002", + needAuthor:1, + publicKey:publicKeyDataList, + privateKey:getPrivateKeyList, + token: getTokenList + ); + } + }); + } + + @override + void onReady() { + // TODO: implement onReady + super.onReady(); + + _initReplySubscription(); + } + + @override + void onInit() { + // TODO: implement onInit + super.onInit(); + + } + + @override + void onClose() { + // TODO: implement onClose + _replySubscription.cancel(); + } + +} \ No newline at end of file diff --git a/star_lock/lib/main/lockDetail/authorizedAdmin/authorizedAdmin/authorizedAdmin_page.dart b/star_lock/lib/main/lockDetail/authorizedAdmin/authorizedAdmin/authorizedAdmin_page.dart index 162ef5fb..cb1462cd 100644 --- a/star_lock/lib/main/lockDetail/authorizedAdmin/authorizedAdmin/authorizedAdmin_page.dart +++ b/star_lock/lib/main/lockDetail/authorizedAdmin/authorizedAdmin/authorizedAdmin_page.dart @@ -13,16 +13,20 @@ import '../../../../app_settings/app_colors.dart'; import '../../../../tools/commonItem.dart'; import '../../../../tools/submitBtn.dart'; import '../../../../translations/trans_lib.dart'; +import 'authorizedAdmin_logic.dart'; class AuthorizedAdminPage extends StatefulWidget { final String type; - AuthorizedAdminPage({Key? key, required this.type}) : super(key: key); + const AuthorizedAdminPage({Key? key, required this.type}) : super(key: key); @override State createState() => _AuthorizedAdminPageState(); } class _AuthorizedAdminPageState extends State { + final logic = Get.put(AuthorizedAdminLogic()); + final state = Get.find().state; + final FlutterContactPicker _contactPicker = FlutterContactPicker(); late Contact _contact; diff --git a/star_lock/lib/main/lockDetail/authorizedAdmin/authorizedAdmin/authorizedAdmin_state.dart b/star_lock/lib/main/lockDetail/authorizedAdmin/authorizedAdmin/authorizedAdmin_state.dart new file mode 100644 index 00000000..6ab1b40d --- /dev/null +++ b/star_lock/lib/main/lockDetail/authorizedAdmin/authorizedAdmin/authorizedAdmin_state.dart @@ -0,0 +1,4 @@ + +class AuthorizedAdminState { + +} \ No newline at end of file diff --git a/star_lock/lib/main/lockDetail/lockDetail/lockDetail_logic.dart b/star_lock/lib/main/lockDetail/lockDetail/lockDetail_logic.dart index d3859d55..9c95b22d 100644 --- a/star_lock/lib/main/lockDetail/lockDetail/lockDetail_logic.dart +++ b/star_lock/lib/main/lockDetail/lockDetail/lockDetail_logic.dart @@ -373,35 +373,6 @@ class LockDetailLogic extends BaseGetXController{ }); } - // 转移权限 - Future transferPermissionsAction() async { - BlueManage().judgeReconnect(BlueManage().connectDeviceMacAddress, BlueManage().connectDeviceName, (DeviceConnectionState state) async { - if (state == DeviceConnectionState.connected){ - var privateKey = await Storage.getStringList(saveBluePrivateKey); - List getPrivateKeyList = changeStringListToIntList(privateKey!); - - var publicKey = await Storage.getStringList(saveBluePublicKey); - List publicKeyDataList = changeStringListToIntList(publicKey!); - - var token = await Storage.getStringList(saveBlueToken); - List getTokenList = changeStringListToIntList(token!); - print("openDoorTokenPubToken:$getTokenList"); - - IoSenderManage.senderTransferPermissions( - lockID:BlueManage().connectDeviceName, - authUserID:await Storage.getUserId(), - keyID:"1", - oldUserID:await Storage.getUserId(), - newUserID:"100002", - needAuthor:1, - publicKey:publicKeyDataList, - privateKey:getPrivateKeyList, - token: getTokenList - ); - } - }); - } - // 恢复出厂设置 Future factoryDataResetAction() async { BlueManage().judgeReconnect(BlueManage().connectDeviceMacAddress, BlueManage().connectDeviceName, (DeviceConnectionState state) async { diff --git a/star_lock/lib/main/lockDetail/passwordKey/passwordKey_perpetual/passwordKey_perpetual_logic.dart b/star_lock/lib/main/lockDetail/passwordKey/passwordKey_perpetual/passwordKey_perpetual_logic.dart new file mode 100644 index 00000000..c3836a73 --- /dev/null +++ b/star_lock/lib/main/lockDetail/passwordKey/passwordKey_perpetual/passwordKey_perpetual_logic.dart @@ -0,0 +1,133 @@ +import 'dart:async'; + +import 'package:flutter_reactive_ble/flutter_reactive_ble.dart'; +import 'package:star_lock/blue/io_protocol/io_type.dart'; + +import '../../../../blue/blue_manage.dart'; +import '../../../../blue/io_protocol/io_reply.dart'; +import '../../../../blue/io_protocol/io_senderCustomPasswords.dart'; +import '../../../../blue/io_tool/io_manager.dart'; +import '../../../../blue/io_tool/io_tool.dart'; +import '../../../../blue/io_tool/manager_event_bus.dart'; +import '../../../../blue/sender_manage.dart'; +import '../../../../tools/baseGetXController.dart'; +import '../../../../tools/storage.dart'; + +class PasswordKeyPerpetualLogic extends BaseGetXController { + + // 监听设备返回的数据 + late StreamSubscription _replySubscription; + void _initReplySubscription() { + _replySubscription = EventBusManager().eventBus!.on().listen((reply) async { + // 设置自定义密码 + if(reply is SenderCustomPasswordsReply) { + var token = reply.data.sublist(2, 6); + var saveStrList = changeIntListToStringList(token); + print("_replyFactoryDataResetKeyToken:$token"); + Storage.setStringList(saveBlueToken, saveStrList); + + int status = reply.data[6]; + print("status:$status"); + + switch(status){ + case 0x00: + //成功 + print("${reply.commandType!.typeValue} 数据解析成功"); + + break; + case 0x06: + //无权限 + print("${reply.commandType!.typeValue} 需要鉴权"); + var privateKey = await Storage.getStringList(saveBluePrivateKey); + List getPrivateKeyList = changeStringListToIntList(privateKey!); + + var publicKey = await Storage.getStringList(saveBluePublicKey); + List publicKeyDataList = changeStringListToIntList(publicKey!); + + IoSenderManage.senderCustomPasswordsCommand( + keyID:"1", + userID:await Storage.getUserId(), + pwdNo:1, + pwd: "123456", + useCountLimit:0xff, + startTime:0x11223344, + endTime:0x11223344, + needAuthor:1, + publicKey:publicKeyDataList, + privateKey:getPrivateKeyList, + token: token + ); + break; + case 0x07: + //无权限 + print("${reply.commandType!.typeValue} 用户无权限"); + + break; + case 0x09: + // 权限校验错误 + print("${reply.commandType!.typeValue} 权限校验错误"); + + break; + default: + //失败 + print("${reply.commandType!.typeValue} 失败"); + + break; + } + } + }); + } + + // 设置自定义密码 + Future senderCustomPasswords() async { + BlueManage().judgeReconnect(BlueManage().connectDeviceMacAddress, BlueManage().connectDeviceName, (DeviceConnectionState state) async { + if (state == DeviceConnectionState.connected){ + var publicKey = await Storage.getStringList(saveBluePublicKey); + List publicKeyDataList = changeStringListToIntList(publicKey!); + + var privateKey = await Storage.getStringList(saveBluePrivateKey); + List getPrivateKeyList = changeStringListToIntList(privateKey!); + + var token = await Storage.getStringList(saveBlueToken); + List getTokenList = changeStringListToIntList(token!); + print("openDoorTokenPubToken:$getTokenList"); + + IoSenderManage.senderCustomPasswordsCommand( + keyID:"1", + userID:await Storage.getUserId(), + pwdNo:1, + pwd: "123456", + useCountLimit:0xff, + startTime:0x11223344, + endTime:0x11223344, + needAuthor:1, + publicKey:publicKeyDataList, + privateKey:getPrivateKeyList, + token: getTokenList + ); + } + }); + } + + @override + void onReady() { + // TODO: implement onReady + super.onReady(); + + _initReplySubscription(); + } + + @override + void onInit() { + // TODO: implement onInit + super.onInit(); + + } + + @override + void onClose() { + // TODO: implement onClose + _replySubscription.cancel(); + } + +} \ No newline at end of file