From edd99cbe48ce717c736359715919947b4d9e1ca2 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, 24 Apr 2024 13:39:47 +0800 Subject: [PATCH 1/4] =?UTF-8?q?=E6=A0=B9=E6=8D=AE=E5=8E=82=E5=95=86?= =?UTF-8?q?=E7=B1=BB=E5=9E=8B=E6=B7=BB=E5=8A=A0=E7=A6=BB=E7=BA=BF=E9=99=90?= =?UTF-8?q?=E6=97=B6=E5=AF=86=E7=A0=81=E6=98=AF=E5=90=A6=E9=80=89=E6=8B=A9?= =?UTF-8?q?=E5=BC=80=E5=A7=8B=E6=97=B6=E9=97=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../card/addCardType/addCardType_page.dart | 19 -------- .../passwordKey_perpetual_logic.dart | 46 +++++++++++-------- .../passwordKey_perpetual_page.dart | 36 ++++++++------- .../lockMian/entity/lockListInfo_entity.dart | 18 +++++++- 4 files changed, 64 insertions(+), 55 deletions(-) diff --git a/star_lock/lib/main/lockDetail/card/addCardType/addCardType_page.dart b/star_lock/lib/main/lockDetail/card/addCardType/addCardType_page.dart index c17cddb9..a773a8df 100644 --- a/star_lock/lib/main/lockDetail/card/addCardType/addCardType_page.dart +++ b/star_lock/lib/main/lockDetail/card/addCardType/addCardType_page.dart @@ -290,25 +290,6 @@ class _AddCardPageState extends State { ); } - String getAppBarTitle(int type) { - String title; - switch (type) { - case 0: - title = TranslationLoader.lanKeys!.stressCard!.tr; - break; - case 1: - title = TranslationLoader.lanKeys!.stressFingerprint!.tr; - break; - case 2: - title = TranslationLoader.lanKeys!.remoteControl!.tr; - break; - default: - title = ""; - break; - } - return title; - } - // 接受者信息输入框 Widget getTFWidget(String tfStr) { return Container( 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 index 4a57d055..44965008 100644 --- 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 @@ -16,6 +16,7 @@ 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/commonDataManage.dart'; import '../../../../tools/dateTool.dart'; import '../../../../tools/storage.dart'; @@ -46,31 +47,34 @@ class PasswordKeyPerpetualLogic extends BaseGetXController { String lockId = state.keyInfo.value.lockId.toString(); String getKeyType = state.widgetType.value.toString(); - if (state.nameController.text.isEmpty) { - showToast("请输入姓名".tr); - return; - } + if (state.nameController.text.isEmpty) { + showToast("请输入姓名".tr); + return; + } - //循环密码 - if (state.widgetType.value == 4) { - if (startDate < DateTool().dateToTimestamp(DateTool().getNowDateWithType(3), 1)) { - showToast("生效时间不能小于当前时间".tr); - return; - } - } if (state.widgetType.value == 0) { //永久 getKeyType = '2'; } else if (state.widgetType.value == 1) { //限时 - if (startDate < DateTool().dateToTimestamp(DateTool().getNowDateWithType(3), 1)) { - showToast("生效时间不能小于当前时间".tr); - return; - } + if(CommonDataManage().currentKeyInfo.vendor == "XL"){ + // 鑫鸿佳 + //限时 + if (startDate < DateTool().dateToTimestamp(DateTool().getNowDateWithType(3), 1)) { + showToast("生效时间不能小于当前时间".tr); + return; + } - if (startDate >= endDate) { - showToast("失效时间要大于生效时间".tr); - return; + if (startDate >= endDate) { + showToast("失效时间要大于生效时间".tr); + return; + } + }else{ + if (endDate < DateTool().dateToTimestamp(DateTool().getNowDateWithType(3), 1)) { + showToast("生效时间不能小于当前时间".tr); + return; + } + startDate = 0; } getKeyType = '3'; } else if (state.widgetType.value == 2) { @@ -80,7 +84,11 @@ class PasswordKeyPerpetualLogic extends BaseGetXController { //自定义 } else if (state.widgetType.value == 4) { //循环 - //限时 + if (startDate < DateTool().dateToTimestamp(DateTool().getNowDateWithType(3), 1)) { + showToast("生效时间不能小于当前时间".tr); + return; + } + if (endDate < DateTool().dateToTimestamp(DateTool().getNowDateWithType(3), 1)) { showToast("结束时间不能小于当前时间".tr); return; diff --git a/star_lock/lib/main/lockDetail/passwordKey/passwordKey_perpetual/passwordKey_perpetual_page.dart b/star_lock/lib/main/lockDetail/passwordKey/passwordKey_perpetual/passwordKey_perpetual_page.dart index d029fdd3..ac718ede 100644 --- a/star_lock/lib/main/lockDetail/passwordKey/passwordKey_perpetual/passwordKey_perpetual_page.dart +++ b/star_lock/lib/main/lockDetail/passwordKey/passwordKey_perpetual/passwordKey_perpetual_page.dart @@ -7,6 +7,7 @@ import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:get/get.dart'; import 'package:star_lock/app_settings/app_colors.dart'; import 'package:star_lock/main/lockDetail/passwordKey/passwordKey_perpetual/passwordKey_perpetual_logic.dart'; +import 'package:star_lock/tools/commonDataManage.dart'; import 'package:star_lock/tools/pickers/pickers.dart'; import 'package:star_lock/tools/pickers/style/default_style.dart'; import 'package:star_lock/tools/pickers/time_picker/model/date_mode.dart'; @@ -193,22 +194,25 @@ class _PasswordKeyPerpetualPageState extends State wit Widget keyTimeLimitWidget() { return Column( children: [ - CommonItem( - leftTitel: TranslationLoader.lanKeys!.effectiveTime!.tr, - rightTitle: state.beginTime.value, - isHaveLine: true, - isHaveDirection: true, - action: () { - Pickers.showDatePicker(context, mode: state.widgetType.value == 3 ? DateMode.YMDHM:DateMode.YMDH, onConfirm: (p) { - if (state.widgetType.value == 3) { - // 自定义 - state.beginTime.value = DateTool().getYMDHNDateString(p, 1); - } else { - state.beginTime.value = DateTool().getYMDHNDateString(p, 4); - } - Get.log("beginTime:${state.beginTime.value}"); - }); - }), + Visibility( + visible: CommonDataManage().currentKeyInfo.vendor == "XHJ" ? false : true, + child: CommonItem( + leftTitel: TranslationLoader.lanKeys!.effectiveTime!.tr, + rightTitle: state.beginTime.value, + isHaveLine: true, + isHaveDirection: true, + action: () { + Pickers.showDatePicker(context, mode: state.widgetType.value == 3 ? DateMode.YMDHM:DateMode.YMDH, onConfirm: (p) { + if (state.widgetType.value == 3) { + // 自定义 + state.beginTime.value = DateTool().getYMDHNDateString(p, 1); + } else { + state.beginTime.value = DateTool().getYMDHNDateString(p, 4); + } + Get.log("beginTime:${state.beginTime.value}"); + }); + }), + ), CommonItem( leftTitel: TranslationLoader.lanKeys!.failureTime!.tr, rightTitle: state.endTime.value, diff --git a/star_lock/lib/main/lockMian/entity/lockListInfo_entity.dart b/star_lock/lib/main/lockMian/entity/lockListInfo_entity.dart index d359e0b0..042d2fcf 100644 --- a/star_lock/lib/main/lockMian/entity/lockListInfo_entity.dart +++ b/star_lock/lib/main/lockMian/entity/lockListInfo_entity.dart @@ -122,6 +122,10 @@ class LockListInfoItemEntity { int? senderUserId; int? electricQuantityDate; int? electricQuantityStandby; + int? isOnlyManageSelf; + int? restoreCount; + String? model; + String? vendor; Bluetooth? bluetooth; LockFeature? lockFeature; LockSetting? lockSetting; @@ -153,7 +157,11 @@ class LockListInfoItemEntity { this.lockUserNo, this.electricQuantityDate, this.electricQuantityStandby, - this.senderUserId}); + this.senderUserId, + this.isOnlyManageSelf, + this.restoreCount, + this.model, + this.vendor}); LockListInfoItemEntity.fromJson(Map json) { keyId = json['keyId']; @@ -180,6 +188,10 @@ class LockListInfoItemEntity { senderUserId = json['senderUserId']; electricQuantityDate = json['electricQuantityDate']; electricQuantityStandby = json['electricQuantityStandby']; + isOnlyManageSelf = json['isOnlyManageSelf']; + restoreCount = json['restoreCount']; + model = json['model']; + vendor = json['vendor']; bluetooth = json['bluetooth'] != null ? Bluetooth.fromJson(json['bluetooth']) : null; @@ -217,6 +229,10 @@ class LockListInfoItemEntity { data['senderUserId'] = senderUserId; data['electricQuantityDate'] = electricQuantityDate; data['electricQuantityStandby'] = electricQuantityStandby; + data['isOnlyManageSelf'] = isOnlyManageSelf; + data['restoreCount'] = restoreCount; + data['model'] = model; + data['vendor'] = vendor; if (bluetooth != null) { data['bluetooth'] = bluetooth!.toJson(); } From 5561996f05bb6fbef8a7f19cbcb4de30e114295c 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, 24 Apr 2024 13:57:00 +0800 Subject: [PATCH 2/4] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E9=99=90=E6=97=B6?= =?UTF-8?q?=E5=AF=86=E7=A0=81=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../passwordKey_perpetual/passwordKey_perpetual_logic.dart | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 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 index 44965008..3e595dad 100644 --- 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 @@ -70,11 +70,11 @@ class PasswordKeyPerpetualLogic extends BaseGetXController { return; } }else{ - if (endDate < DateTool().dateToTimestamp(DateTool().getNowDateWithType(3), 1)) { - showToast("生效时间不能小于当前时间".tr); + if (endDate <= DateTool().dateToTimestamp(DateTool().getNowDateWithType(3), 1)) { + showToast("生效时间要大于当前时间".tr); return; } - startDate = 0; + // startDate = 0; } getKeyType = '3'; } else if (state.widgetType.value == 2) { From ad4f6c286f6706dd26e0b9fd2f51d3bb130a0023 Mon Sep 17 00:00:00 2001 From: anfe <448468458@qq.com> Date: Wed, 24 Apr 2024 16:04:07 +0800 Subject: [PATCH 3/4] =?UTF-8?q?feat:=E5=AE=8C=E6=88=90=20ota=20=E5=8D=87?= =?UTF-8?q?=E7=BA=A7=E8=B0=83=E7=94=A8=EF=BC=8C=E4=BC=98=E5=8C=96=E8=93=9D?= =?UTF-8?q?=E7=89=99=E4=BC=A0=E8=BE=93=E9=80=9F=E5=BA=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- star_lock/images/lan/lan_en.json | 6 +- star_lock/ios/Podfile.lock | 50 +++ star_lock/lib/blue/blue_manage.dart | 169 +++++---- .../lib/blue/io_protocol/io_otaUpgrade.dart | 149 ++++++++ .../io_protocol/io_processOtaUpgrade.dart | 74 ++++ star_lock/lib/blue/io_reply.dart | 9 +- star_lock/lib/blue/io_sender.dart | 327 +++++++++++++++--- star_lock/lib/blue/io_tool/io_model.dart | 34 +- star_lock/lib/blue/io_type.dart | 95 +++-- star_lock/lib/blue/reciver_data.dart | 37 +- star_lock/lib/blue/sender_data.dart | 21 +- star_lock/lib/blue/sender_manage.dart | 159 ++++++--- .../lockDetail/lockDetail_logic.dart | 2 +- .../lockEscalation/lockEscalation_logic.dart | 214 +++++++++++- .../lockEscalation/lockEscalation_page.dart | 202 +++++++---- .../lockEscalation/lockEscalation_state.dart | 6 +- .../lib/permission/permission_dialog.dart | 4 +- star_lock/pubspec.yaml | 11 +- 18 files changed, 1262 insertions(+), 307 deletions(-) create mode 100644 star_lock/lib/blue/io_protocol/io_otaUpgrade.dart create mode 100644 star_lock/lib/blue/io_protocol/io_processOtaUpgrade.dart diff --git a/star_lock/images/lan/lan_en.json b/star_lock/images/lan/lan_en.json index 02973a34..99191826 100644 --- a/star_lock/images/lan/lan_en.json +++ b/star_lock/images/lan/lan_en.json @@ -769,7 +769,7 @@ "异常警告":"Abnormal warning", "短信提醒":"SMS reminder", "邮件提醒":"Email reminder", - "关锁":"关锁", - "功能":"功能", - "配件":"配件" + "关锁":"close lock", + "功能":"function", + "配件":"parts" } diff --git a/star_lock/ios/Podfile.lock b/star_lock/ios/Podfile.lock index bc49045f..1d1c9856 100644 --- a/star_lock/ios/Podfile.lock +++ b/star_lock/ios/Podfile.lock @@ -41,7 +41,41 @@ PODS: - ReachabilitySwift - device_info_plus (0.0.1): - Flutter + - DKImagePickerController/Core (4.3.8): + - DKImagePickerController/ImageDataManager + - DKImagePickerController/Resource + - DKImagePickerController/ImageDataManager (4.3.8) + - DKImagePickerController/PhotoGallery (4.3.8): + - DKImagePickerController/Core + - DKPhotoGallery + - DKImagePickerController/Resource (4.3.8) + - DKPhotoGallery (0.0.17): + - DKPhotoGallery/Core (= 0.0.17) + - DKPhotoGallery/Model (= 0.0.17) + - DKPhotoGallery/Preview (= 0.0.17) + - DKPhotoGallery/Resource (= 0.0.17) + - SDWebImage + - SwiftyGif + - DKPhotoGallery/Core (0.0.17): + - DKPhotoGallery/Model + - DKPhotoGallery/Preview + - SDWebImage + - SwiftyGif + - DKPhotoGallery/Model (0.0.17): + - SDWebImage + - SwiftyGif + - DKPhotoGallery/Preview (0.0.17): + - DKPhotoGallery/Model + - DKPhotoGallery/Resource + - SDWebImage + - SwiftyGif + - DKPhotoGallery/Resource (0.0.17): + - SDWebImage + - SwiftyGif - EMASRest (11.1.1.2) + - file_picker (0.0.1): + - DKImagePickerController/PhotoGallery + - Flutter - Flutter (1.0.0) - flutter_blue_plus (0.0.1): - Flutter @@ -95,12 +129,16 @@ PODS: - permission_handler_apple (9.3.0): - Flutter - ReachabilitySwift (5.2.2) + - SDWebImage (5.19.1): + - SDWebImage/Core (= 5.19.1) + - SDWebImage/Core (5.19.1) - shared_preferences_foundation (0.0.1): - Flutter - FlutterMacOS - sqflite (0.0.3): - Flutter - FlutterMacOS + - SwiftyGif (5.4.5) - system_settings (0.0.1): - Flutter - Toast (4.1.1) @@ -126,6 +164,7 @@ DEPENDENCIES: - camera_avfoundation (from `.symlinks/plugins/camera_avfoundation/ios`) - connectivity_plus (from `.symlinks/plugins/connectivity_plus/ios`) - device_info_plus (from `.symlinks/plugins/device_info_plus/ios`) + - file_picker (from `.symlinks/plugins/file_picker/ios`) - Flutter (from `Flutter`) - flutter_blue_plus (from `.symlinks/plugins/flutter_blue_plus/ios`) - flutter_local_notifications (from `.symlinks/plugins/flutter_local_notifications/ios`) @@ -163,11 +202,15 @@ SPEC REPOS: - AMap3DMap - AMapFoundation - AMapLocation + - DKImagePickerController + - DKPhotoGallery - GoogleMaps - ios-voice-processor - JCore - JPush - ReachabilitySwift + - SDWebImage + - SwiftyGif - Toast - WechatOpenSDK-XCFramework @@ -194,6 +237,8 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/connectivity_plus/ios" device_info_plus: :path: ".symlinks/plugins/device_info_plus/ios" + file_picker: + :path: ".symlinks/plugins/file_picker/ios" Flutter: :path: Flutter flutter_blue_plus: @@ -261,7 +306,10 @@ SPEC CHECKSUMS: camera_avfoundation: 8b8d780bcfb6a4a02b0fbe2b4bd17b5b71946e68 connectivity_plus: bf0076dd84a130856aa636df1c71ccaff908fa1d device_info_plus: e5c5da33f982a436e103237c0c85f9031142abed + DKImagePickerController: a7836546cfdfe014171694f643a7d575bc8ace7f + DKPhotoGallery: fdfad5125a9fdda9cc57df834d49df790dbb4179 EMASRest: 8df6f87836767a9415ad5cc4af739bc9d215b475 + file_picker: ce3938a0df3cc1ef404671531facef740d03f920 Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854 flutter_blue_plus: 4837da7d00cf5d441fdd6635b3a57f936778ea96 flutter_local_notifications: 4cde75091f6327eb8517fa068a0a5950212d2086 @@ -284,8 +332,10 @@ SPEC CHECKSUMS: path_provider_foundation: 3784922295ac71e43754bd15e0653ccfd36a147c permission_handler_apple: 9878588469a2b0d0fc1e048d9f43605f92e6cec2 ReachabilitySwift: 2128f3a8c9107e1ad33574c6e58e8285d460b149 + SDWebImage: 40b0b4053e36c660a764958bff99eed16610acbb shared_preferences_foundation: b4c3b4cddf1c21f02770737f147a3f5da9d39695 sqflite: 673a0e54cc04b7d6dba8d24fb8095b31c3a99eec + SwiftyGif: 706c60cf65fa2bc5ee0313beece843c8eb8194d4 system_settings: 8f5cdbfa72c677fc8d665b863bcc20d393d87e9d Toast: 1f5ea13423a1e6674c4abdac5be53587ae481c4e url_launcher_ios: bbd758c6e7f9fd7b5b1d4cde34d2b95fcce5e812 diff --git a/star_lock/lib/blue/blue_manage.dart b/star_lock/lib/blue/blue_manage.dart index 996ebb9f..ee2bd718 100644 --- a/star_lock/lib/blue/blue_manage.dart +++ b/star_lock/lib/blue/blue_manage.dart @@ -1,4 +1,3 @@ - import 'dart:async'; import 'dart:io'; @@ -12,7 +11,8 @@ import 'reciver_data.dart'; import 'package:flutter_blue_plus/flutter_blue_plus.dart'; //连接状态回调 -typedef ConnectStateCallBack = Function(BluetoothConnectionState connectionState); +typedef ConnectStateCallBack = Function( + BluetoothConnectionState connectionState); typedef ScanDevicesCallBack = Function(List); class BlueManage { @@ -57,7 +57,8 @@ class BlueManage { ScanResult? scanResult; // 监听蓝牙连接状态 - BluetoothConnectionState? bluetoothConnectionState = BluetoothConnectionState.disconnected; + BluetoothConnectionState? bluetoothConnectionState = + BluetoothConnectionState.disconnected; BluetoothAdapterState? _adapterState = BluetoothAdapterState.unknown; StreamSubscription? _adapterStateStateSubscription; @@ -80,6 +81,7 @@ class BlueManage { void _initBlue() { Get.log("蓝牙功能初始化监听"); + FlutterBluePlus.setLogLevel(LogLevel.error, color: true); _initSendStreamSubscription(); _initAdapterStateStateSubscription(); // _initListenscanResults(); @@ -94,7 +96,8 @@ class BlueManage { } void _initAdapterStateStateSubscription() { - _adapterStateStateSubscription ??= FlutterBluePlus.adapterState.listen((state) { + _adapterStateStateSubscription ??= + FlutterBluePlus.adapterState.listen((state) { _adapterState = state; }); } @@ -142,14 +145,18 @@ class BlueManage { _connectionStateSubscription?.cancel(); _connectionStateSubscription = null; - _connectionStateSubscription = bluetoothConnectDevice!.connectionState.listen((state) async { + _connectionStateSubscription = + bluetoothConnectDevice!.connectionState.listen((state) async { bluetoothConnectionState = state; print("蓝牙连接状态:$state"); }); } void _initSendStreamSubscription() { - _sendStreamSubscription ??= EventBusManager().eventBus!.on().listen((EventSendModel model) { + _sendStreamSubscription ??= EventBusManager() + .eventBus! + .on() + .listen((EventSendModel model) { if (model.sendChannel == DataChannel.ble) { FlutterBluePlus.isSupported.then((isAvailable) async { if (isAvailable) { @@ -157,9 +164,7 @@ class BlueManage { // 蓝牙已开启,可以进行蓝牙操作 writeCharacteristicWithResponse(model.data); } else { - try { - - } catch (e) { + try {} catch (e) { print("Error Turning On:"); } } @@ -172,7 +177,8 @@ class BlueManage { } /// 开始指定设备名称的扫描蓝牙设备 - Future startScanSingle(String deviceName, int timeout, ScanDevicesCallBack scanDevicesCallBack) async { + Future startScanSingle(String deviceName, int timeout, + ScanDevicesCallBack scanDevicesCallBack) async { FlutterBluePlus.isSupported.then((isAvailable) async { if (isAvailable) { if (_adapterState == BluetoothAdapterState.on) { @@ -180,8 +186,10 @@ class BlueManage { FlutterBluePlus.startScan(timeout: Duration(seconds: timeout)); Completer completer = Completer(); var subscription = FlutterBluePlus.scanResults.listen((results) { - print("startScanSingle扫描到的设备:$results"); - bool isExit = results.any((element) => (element.device.platformName == deviceName) || (element.advertisementData.advName == deviceName)); + // print("startScanSingle扫描到的设备:$results"); + bool isExit = results.any((element) => + (element.device.platformName == deviceName) || + (element.advertisementData.advName == deviceName)); if (isExit) { for (var scanResult in results) { if (((scanResult.advertisementData.serviceUuids.isNotEmpty @@ -191,8 +199,11 @@ class BlueManage { .contains("758824")) && (scanResult.rssi >= -100)) { // 查询id相同的元素 - final knownDeviceIndex = scanDevices - .indexWhere((d) => (d.device.platformName == scanResult.device.platformName) || (d.advertisementData.advName == scanResult.advertisementData.advName)); + final knownDeviceIndex = scanDevices.indexWhere((d) => + (d.device.platformName == + scanResult.device.platformName) || + (d.advertisementData.advName == + scanResult.advertisementData.advName)); // 不存在的时候返回-1 if (knownDeviceIndex >= 0) { scanDevices[knownDeviceIndex] = scanResult; @@ -231,7 +242,8 @@ class BlueManage { } /// 开始扫描蓝牙设备 - Future startScan(int timeout, ScanDevicesCallBack scanDevicesCallBack, {List? idList}) async { + Future startScan(int timeout, ScanDevicesCallBack scanDevicesCallBack, + {List? idList}) async { FlutterBluePlus.isSupported.then((isAvailable) async { if (isAvailable) { if (_adapterState == BluetoothAdapterState.on) { @@ -255,8 +267,11 @@ class BlueManage { .contains("758824")) && (scanResult.rssi >= -100)) { // 查询id相同的元素 - final knownDeviceIndex = scanDevices - .indexWhere((d) => (d.device.platformName == scanResult.device.platformName) || (d.advertisementData.advName == scanResult.advertisementData.advName)); + final knownDeviceIndex = scanDevices.indexWhere((d) => + (d.device.platformName == + scanResult.device.platformName) || + (d.advertisementData.advName == + scanResult.advertisementData.advName)); // 不存在的时候返回-1 if (knownDeviceIndex >= 0) { scanDevices[knownDeviceIndex] = scanResult; @@ -294,7 +309,9 @@ class BlueManage { } /// 调用发送数据 List senderData, - Future bludSendData(String deviceName, ConnectStateCallBack stateCallBack, {bool isAddEquipment = false}) async { + Future bludSendData( + String deviceName, ConnectStateCallBack stateCallBack, + {bool isAddEquipment = false}) async { FlutterBluePlus.isSupported.then((isAvailable) async { if (isAvailable) { if (_adapterState == BluetoothAdapterState.on) { @@ -321,33 +338,43 @@ class BlueManage { } /// 连接 - Future _connect(String deviceName, ConnectStateCallBack connectStateCallBack, + Future _connect( + String deviceName, ConnectStateCallBack connectStateCallBack, {bool isAddEquipment = false}) async { connectDeviceName = deviceName; List devicesList = scanDevices; //判断列表里面有设备则不开启扫描 - bool isExistDevice = scanDevices.any((element) => element.device.platformName == connectDeviceName || element.advertisementData.advName == connectDeviceName); + bool isExistDevice = scanDevices.any((element) => + element.device.platformName == connectDeviceName || + element.advertisementData.advName == connectDeviceName); if (isAddEquipment == false && isExistDevice == false) { // startScan(10, (scanDevices){ startScanSingle(deviceName, 10, (List scanDevices) { print("扫描到的设备:$scanDevices"); devicesList = scanDevices; - _connectDevice(devicesList, deviceName, connectStateCallBack, isAddEquipment: isAddEquipment); + _connectDevice(devicesList, deviceName, connectStateCallBack, + isAddEquipment: isAddEquipment); }); } else { - _connectDevice(devicesList, deviceName, connectStateCallBack, isAddEquipment: isAddEquipment); + _connectDevice(devicesList, deviceName, connectStateCallBack, + isAddEquipment: isAddEquipment); } } - Future _connectDevice( - List devicesList, String deviceName, ConnectStateCallBack connectStateCallBack, + Future _connectDevice(List devicesList, String deviceName, + ConnectStateCallBack connectStateCallBack, {bool isAddEquipment = false}) async { // 判断数组列表里面是否有这个设备 print("devicesList:$devicesList"); - final knownDeviceIndex = devicesList.indexWhere((d) => (d.device.platformName == deviceName) || (d.advertisementData.advName == deviceName)); + final knownDeviceIndex = devicesList.indexWhere((d) => + (d.device.platformName == deviceName) || + (d.advertisementData.advName == deviceName)); if (knownDeviceIndex >= 0) { // 存在的时候赋值 - connectDeviceMacAddress = devicesList[knownDeviceIndex].advertisementData.advName.isNotEmpty ? devicesList[knownDeviceIndex].advertisementData.advName : devicesList[knownDeviceIndex].device.platformName; + connectDeviceMacAddress = + devicesList[knownDeviceIndex].advertisementData.advName.isNotEmpty + ? devicesList[knownDeviceIndex].advertisementData.advName + : devicesList[knownDeviceIndex].device.platformName; bluetoothConnectDevice = devicesList[knownDeviceIndex].device; print('bluetoothConnectDevice: $bluetoothConnectDevice'); @@ -356,7 +383,8 @@ class BlueManage { _initGetMtuSubscription(); _initListenConnectionState(); } - print("1 connectDeviceId:$connectDeviceMacAddress connectDeviceName:$connectDeviceName"); + print( + "1 connectDeviceId:$connectDeviceMacAddress connectDeviceName:$connectDeviceName"); // stopScan(); if (connectDeviceMacAddress.isEmpty) { // connectStateCallBack(BluetoothConnectionState.disconnected!); @@ -366,7 +394,8 @@ class BlueManage { print("调用了停止扫描的方法"); await stopScan(); - if ((scanResult!.advertisementData.serviceUuids[0].toString()[31] == "0") && isAddEquipment == false) { + if ((scanResult!.advertisementData.serviceUuids[0].toString()[31] == "0") && + isAddEquipment == false) { connectStateCallBack(BluetoothConnectionState.disconnected); EasyLoading.showToast("该锁已被重置", duration: 2000.milliseconds); return; @@ -403,12 +432,14 @@ class BlueManage { " service.characteristics:${service.characteristics}" " service.includedServices:${service.includedServices}"); if (service.uuid == _serviceIdConnect) { - for (BluetoothCharacteristic characteristic in service.characteristics) { + for (BluetoothCharacteristic characteristic + in service.characteristics) { // Get.log("22222characteristic.remoteId:${characteristic.remoteId}" // " characteristic.uuid:${characteristic.uuid}" // " characteristic.secondaryServiceUuid:${characteristic.secondaryServiceUuid}" // " characteristic.characteristicUuid:${characteristic.characteristicUuid}"); - if (characteristic.characteristicUuid == _characteristicIdSubscription) { + if (characteristic.characteristicUuid == + _characteristicIdSubscription) { _subScribeToCharacteristic(characteristic); print('Discovering services finished'); bluetoothConnectionState = BluetoothConnectionState.connected; @@ -446,18 +477,21 @@ class BlueManage { } // code to handle incoming data // print("subscribeToCharacteristic: deviceId = ${characteristic.deviceId} characteristicId =${characteristic.characteristicId}---上报来的数据data = $data"); - if ((data[0] == 0xEF) && (data[1] == 0x01) && (data[2] == 0xEE) && (data[3] == 0x02)) { + if ((data[0] == 0xEF) && + (data[1] == 0x01) && + (data[2] == 0xEE) && + (data[3] == 0x02)) { // 当包有头时 // 判断是否需要分包 dataLen = data[8] * 256 + data[9]; // 高16位用来指示后面数据块内容的长度 - print("dataLen1111:$dataLen getDataLength:${data.length} data:$data"); + // print("dataLen1111:$dataLen getDataLength:${data.length} data:$data"); if (dataLen! + 12 > data.length) { // 当前包的长度小于实际的包时 分包添加 不解析 allData.addAll(data); } else { // 当前包的长度小于实际的包时 不分包 解析 allData.addAll(data); - print("dataLen2222:$dataLen getDataLength:${data.length}"); + // print("dataLen2222:$dataLen getDataLength:${data.length}"); CommandReciverManager.appDataReceive(allData); // 发送完解析初始化数组 allData = []; @@ -466,7 +500,8 @@ class BlueManage { // 当包没有头时 是分包的包 直接添加 allData.addAll(data); // var len = allData[8] * 256 + allData[9]; - print("dataLen3333:$dataLen allData.length:${allData.length} allData:$allData"); + print( + "dataLen3333:$dataLen allData.length:${allData.length} allData:$allData"); if ((dataLen! + 14) <= allData.length) { print("44444数据被解析了"); // 当长度小于等于当前包的数据时 直接解析数据 @@ -530,44 +565,44 @@ class BlueManage { // 写入 Future writeCharacteristicWithResponse(List value) async { - bluetoothConnectDevice!.discoverServices().then((services) async { - for (BluetoothService service in services) { - // print("33333 service.remoteId:${service.remoteId}" - // " service.uuid:${service.uuid}\n\n" - // " service.characteristics:${service.characteristics}\n\n" - // " service.includedServices:${service.includedServices}"); - if (service.uuid == _serviceIdConnect) { - for (BluetoothCharacteristic characteristic in service.characteristics) { - // print("44444 characteristic.remoteId:${characteristic.remoteId}" - // " characteristic.uuid:${characteristic.uuid}\n\n" - // " characteristic.secondaryServiceUuid:${characteristic - // .secondaryServiceUuid}\n\n" - // " characteristic.characteristicUuid:${characteristic - // .characteristicUuid}"); - if (characteristic.characteristicUuid == _characteristicIdWrite) { - try { - List valueList = value; - List subData = splitList(valueList, _mtuSize!); - print('writeCharacteristicWithResponse _mtuSize:$_mtuSize 得到的分割数据:$subData'); - - for (int i = 0; i < subData.length; i++) { - await characteristic.write(subData[i]).then((value) async { - await Future.delayed(const Duration(milliseconds: 1)).then(( - value) async { - print('分包发送成功了'); - }); - }); - } - } on Exception catch (e, s) { - print('Error occurred when writing: $e'); - // Get.log(s); - rethrow; + List services = + await bluetoothConnectDevice!.discoverServices(); + for (BluetoothService service in services) { + // print("33333 service.remoteId:${service.remoteId}" + // " service.uuid:${service.uuid}\n\n" + // " service.characteristics:${service.characteristics}\n\n" + // " service.includedServices:${service.includedServices}"); + if (service.uuid == _serviceIdConnect) { + for (BluetoothCharacteristic characteristic + in service.characteristics) { + // print("44444 characteristic.remoteId:${characteristic.remoteId}" + // " characteristic.uuid:${characteristic.uuid}\n\n" + // " characteristic.secondaryServiceUuid:${characteristic + // .secondaryServiceUuid}\n\n" + // " characteristic.characteristicUuid:${characteristic + // .characteristicUuid}"); + if (characteristic.characteristicUuid == _characteristicIdWrite) { + try { + List valueList = value; + List subData = splitList(valueList, _mtuSize!); + // print('writeCharacteristicWithResponse _mtuSize:$_mtuSize 得到的分割数据:$subData'); + for (int i = 0; i < subData.length; i++) { + await characteristic.write(subData[i],withoutResponse: true).then((value) async { + // await Future.delayed(const Duration(milliseconds: 1)).then(( + // value) async { + // print('分包发送成功了'); + // }); + }); } + } on Exception catch (e, s) { + print('Error occurred when writing: $e'); + // Get.log(s); + rethrow; } } } } - }); + } // List services = await bluetoothConnectDevice!.discoverServices(); // BluetoothCharacteristic characteristic = services // .firstWhere((service) => service.uuid == _serviceIdWrite) diff --git a/star_lock/lib/blue/io_protocol/io_otaUpgrade.dart b/star_lock/lib/blue/io_protocol/io_otaUpgrade.dart new file mode 100644 index 00000000..23e500dd --- /dev/null +++ b/star_lock/lib/blue/io_protocol/io_otaUpgrade.dart @@ -0,0 +1,149 @@ +import 'dart:convert'; +import 'dart:typed_data'; + +import 'package:get/get.dart'; + +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; + +//oat升级 +class OTAUpgradeCommand extends SenderProtocol { + String? lockID; + String? userID; + String? keyID; + int? platform; + int? product; + String? hwVersion; + String? fwVersion; + int? fwSize; + String? fwMD5; + int? needAuthor; + List? publicKey; + List? privateKey; + List? token; + + OTAUpgradeCommand( + {this.lockID, + this.userID, + this.keyID, + this.platform, + this.product, + this.hwVersion, + this.fwVersion, + this.fwSize, + this.fwMD5, + this.needAuthor, + this.publicKey, + this.privateKey, + this.token}) + : super(CommandType.startOATUpgrade); + + @override + List messageDetail() { + List data = []; + List ebcData = []; + + // 指令类型 + int type = commandType!.typeValue; + double typeDouble = type / 256; + int type1 = typeDouble.toInt(); + int type2 = type % 256; + data.add(type1); + data.add(type2); + + // 锁id 40 + int lockIDLength = utf8.encode(lockID!).length; + data.addAll(utf8.encode(lockID!)); + data = getFixedLengthList(data, 40 - lockIDLength); + + //userID 20 + int userIDLength = utf8.encode(userID!).length; + data.addAll(utf8.encode(userID!)); + data = getFixedLengthList(data, 20 - userIDLength); + + //platform 2 + int platform0 = (platform! & 0xFF00) >> 8; + int platform1 = platform! & 0xFF; + data.add(platform0); + data.add(platform1); + + //product 2 + int product0 = (product! & 0xFF00) >> 8; + int product1 = product! & 0xFF; + data.add(product0); + data.add(product1); + + //HwVersion 20 + int hwVersionLength = utf8.encode(hwVersion!).length; + data.addAll(utf8.encode(hwVersion!)); + data = getFixedLengthList(data, 20 - hwVersionLength); + + //FwVersion 20 + int fwVersionLength = utf8.encode(fwVersion!).length; + data.addAll(utf8.encode(fwVersion!)); + data = getFixedLengthList(data, 20 - fwVersionLength); + + //fwSize 4 + ByteData bytes = ByteData(4); // 创建一个长度为4的字节数据 + bytes.setInt32(0, fwSize!); + List byteList = bytes.buffer.asUint8List(); + data.addAll(byteList); + + //fwMD5 16 + int fwMD5Length = utf8.encode(fwMD5!).length; + data.addAll(utf8.encode(fwMD5!)); + data = getFixedLengthList(data, 16 - fwMD5Length); + + // token 长度4 首次请求 Token 填 0,如果锁需要鉴权 操作者身份,则会分配动态口令并在应答消息中返回,二次请求时带上。 当token失效或者第一次发送的时候token为0 + data.addAll(token!); + + if (needAuthor == 0) { + //AuthCodeLen 1 + data.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!); + + // 把KeyID、authUserID、时间戳、公钥通过md5加密之后就是authCode + var authCode = crypto.md5.convert(authCodeData); + + data.add(authCode.bytes.length); + data.addAll(authCode.bytes); + } + + if ((data.length % 16) != 0) { + int add = (16 - data.length % 16); + for (int i = 0; i < add; i++) { + data.add(0); + } + } + + Get.log("${commandType!.typeName} SM4Data:$data"); + // 拿到数据之后通过LockId进行SM4 ECB加密 key:544d485f633335373034383064613864 + ebcData = SM4.encrypt(data, key: privateKey, mode: SM4CryptoMode.ECB); + return ebcData; + } +} + +class OTAUpgradeReply extends Reply { + OTAUpgradeReply.parseData(CommandType commandType, List dataDetail) + : super.parseData(commandType, dataDetail) { + data = dataDetail; + int status = data[6]; + errorWithStstus(status); + } +} diff --git a/star_lock/lib/blue/io_protocol/io_processOtaUpgrade.dart b/star_lock/lib/blue/io_protocol/io_processOtaUpgrade.dart new file mode 100644 index 00000000..38b52bac --- /dev/null +++ b/star_lock/lib/blue/io_protocol/io_processOtaUpgrade.dart @@ -0,0 +1,74 @@ +import 'dart:convert'; +import 'dart:typed_data'; + +import 'package:get/get.dart'; + +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; + +//oat升级 +class ProcessOtaUpgradeCommand extends SenderProtocol { + int? index; + int? size; + List? data; + + ProcessOtaUpgradeCommand({ + this.index, + this.size, + this.data, + }) : super(CommandType.processOTAUpgrade); + + @override + List messageDetail() { + List data = []; + + // 指令类型 + int type = commandType!.typeValue; + double typeDouble = type / 256; + int type1 = typeDouble.toInt(); + int type2 = type % 256; + data.add(type1); + data.add(type2); + + //index 2 + ByteData indexBytes = ByteData(2); // 创建一个长度为4的字节数据 + indexBytes.setInt16(0, index!); + List indexList = indexBytes.buffer.asUint8List(); + data.addAll(indexList); + + //size 2 + ByteData bytes = ByteData(2); // 创建一个长度为4的字节数据 + bytes.setInt16(0, size!); + List byteList = bytes.buffer.asUint8List(); + data.addAll(byteList); + + data.addAll(this.data!); + + //不加密 + return data; + } +} + +class ProcessOtaUpgradeReply extends Reply { + ProcessOtaUpgradeReply.parseData( + CommandType commandType, List dataDetail) + : super.parseData(commandType, dataDetail) { + data = dataDetail; + int status = data[2]; + errorWithStstus(status); + } +} + +class ConfirmationOTAUpgradeReply extends Reply { + ConfirmationOTAUpgradeReply.parseData( + CommandType commandType, List dataDetail) + : super.parseData(commandType, dataDetail) { + data = dataDetail; + int status = data[2]; + errorWithStstus(status); + } +} diff --git a/star_lock/lib/blue/io_reply.dart b/star_lock/lib/blue/io_reply.dart index d9e7f010..2cf0ea7b 100644 --- a/star_lock/lib/blue/io_reply.dart +++ b/star_lock/lib/blue/io_reply.dart @@ -14,11 +14,11 @@ abstract class Reply{ Reply.parseData(this.commandType, List dataDetail); void errorWithStstus(int status){ - Get.log("errorWithStstus status:$status commandType:$commandType"); + // Get.log("errorWithStstus status:$status commandType:$commandType"); switch(status){ case 0x00: // 成功 - Get.log("$commandType成功"); + // Get.log("$commandType成功"); break; case 0x01: // 包格式错误 @@ -134,4 +134,9 @@ abstract class Reply{ void showErrorMessage(String message){ EasyLoading.showToast(message, duration: 2000.milliseconds); } + + @override + String toString() { + return 'Reply{commandType: $commandType, status: $status, data: $data}'; + } } diff --git a/star_lock/lib/blue/io_sender.dart b/star_lock/lib/blue/io_sender.dart index 286bbcf3..004047d4 100644 --- a/star_lock/lib/blue/io_sender.dart +++ b/star_lock/lib/blue/io_sender.dart @@ -12,11 +12,17 @@ abstract class SenderProtocol extends IOData { // var uint8View1 = Uint8List(300); CommandType? commandType; //指令类型 - final List header = [0XEF, 0X01, 0XEE, 0X02]; //帧头 固定取值 0XEF01EE02,长度 4 字节 - final int ask = 0X01 ; // 包类型:0X01 表示请求包,0X11 表示应答包,长度 1 字节 + final List header = [ + 0XEF, + 0X01, + 0XEE, + 0X02 + ]; //帧头 固定取值 0XEF01EE02,长度 4 字节 + final int ask = 0X01; // 包类型:0X01 表示请求包,0X11 表示应答包,长度 1 字节 int? _commandIndex = 1; //包序号 - int identifier = 0x20; // 高 4 位表示包版本,低 4 位用来指示后面数据的加密类型,长度为 1 字节,加密类型取值说明,0:明文,1:AES128,2:SM4(事先约定密钥),3:SM4(设备指定密钥) + int identifier = + 0x20; // 高 4 位表示包版本,低 4 位用来指示后面数据的加密类型,长度为 1 字节,加密类型取值说明,0:明文,1:AES128,2:SM4(事先约定密钥),3:SM4(设备指定密钥) List? commandData = []; //数据块 // final int? tail = 0xFF; //用来校验包的完整性,采用 CRC 校验方法,长度为 2 个字节 @@ -40,9 +46,9 @@ abstract class SenderProtocol extends IOData { // 包序号 int commandIndexChange = _commandIndex!; - double commandIndexChangeDouble = commandIndexChange/256; + double commandIndexChangeDouble = commandIndexChange / 256; int commandIndexChang1 = commandIndexChangeDouble.toInt(); - int commandIndexChang2 = commandIndexChange%256; + int commandIndexChang2 = commandIndexChange % 256; commandList.add(commandIndexChang1); commandList.add(commandIndexChang2); // print("_commandIndex:$_commandIndex commandIndexChang1$commandIndexChang1 commandIndexChang2:$commandIndexChang2"); @@ -57,11 +63,11 @@ abstract class SenderProtocol extends IOData { // commandList.add(dataLength); // print("dataLen:$dataLen"); // var dataLen = 42; - double dataLength = dataLen/256; + double dataLength = dataLen / 256; commandList.add(dataLength.toInt()); - commandList.add(dataLen%256); + commandList.add(dataLen % 256); commandList.add(dataLength.toInt()); - commandList.add(dataLen%256); + commandList.add(dataLen % 256); // 数据块 commandList.addAll(commandData!); //数据块 @@ -69,46 +75,284 @@ abstract class SenderProtocol extends IOData { // 校验位 var mcrc = crc_16(commandList); - double mcrcDouble = mcrc/256; + double mcrcDouble = mcrc / 256; int mcrcDouble1 = mcrcDouble.toInt(); - int mcrcDouble2 = mcrc%256; + int mcrcDouble2 = mcrc % 256; commandList.add(mcrcDouble1); //帧尾 commandList.add(mcrcDouble2); - // print("mcrc:$mcrc"); - // print("mcrcDouble1:$mcrcDouble1"); - // print("mcrcDouble2:$mcrcDouble2"); return commandList; } //TODO:长度 int dataSourceLength() => commandData!.length; - var crcTable =[ - 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, - 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de, - 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485, 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d, - 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4, 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc, - 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823, 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b, - 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12, 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a, - 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49, - 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70, 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78, - 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f, 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067, - 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256, - 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, - 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c, 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634, - 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab, 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3, - 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92, - 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1, - 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0]; + var crcTable = [ + 0x0000, + 0x1021, + 0x2042, + 0x3063, + 0x4084, + 0x50a5, + 0x60c6, + 0x70e7, + 0x8108, + 0x9129, + 0xa14a, + 0xb16b, + 0xc18c, + 0xd1ad, + 0xe1ce, + 0xf1ef, + 0x1231, + 0x0210, + 0x3273, + 0x2252, + 0x52b5, + 0x4294, + 0x72f7, + 0x62d6, + 0x9339, + 0x8318, + 0xb37b, + 0xa35a, + 0xd3bd, + 0xc39c, + 0xf3ff, + 0xe3de, + 0x2462, + 0x3443, + 0x0420, + 0x1401, + 0x64e6, + 0x74c7, + 0x44a4, + 0x5485, + 0xa56a, + 0xb54b, + 0x8528, + 0x9509, + 0xe5ee, + 0xf5cf, + 0xc5ac, + 0xd58d, + 0x3653, + 0x2672, + 0x1611, + 0x0630, + 0x76d7, + 0x66f6, + 0x5695, + 0x46b4, + 0xb75b, + 0xa77a, + 0x9719, + 0x8738, + 0xf7df, + 0xe7fe, + 0xd79d, + 0xc7bc, + 0x48c4, + 0x58e5, + 0x6886, + 0x78a7, + 0x0840, + 0x1861, + 0x2802, + 0x3823, + 0xc9cc, + 0xd9ed, + 0xe98e, + 0xf9af, + 0x8948, + 0x9969, + 0xa90a, + 0xb92b, + 0x5af5, + 0x4ad4, + 0x7ab7, + 0x6a96, + 0x1a71, + 0x0a50, + 0x3a33, + 0x2a12, + 0xdbfd, + 0xcbdc, + 0xfbbf, + 0xeb9e, + 0x9b79, + 0x8b58, + 0xbb3b, + 0xab1a, + 0x6ca6, + 0x7c87, + 0x4ce4, + 0x5cc5, + 0x2c22, + 0x3c03, + 0x0c60, + 0x1c41, + 0xedae, + 0xfd8f, + 0xcdec, + 0xddcd, + 0xad2a, + 0xbd0b, + 0x8d68, + 0x9d49, + 0x7e97, + 0x6eb6, + 0x5ed5, + 0x4ef4, + 0x3e13, + 0x2e32, + 0x1e51, + 0x0e70, + 0xff9f, + 0xefbe, + 0xdfdd, + 0xcffc, + 0xbf1b, + 0xaf3a, + 0x9f59, + 0x8f78, + 0x9188, + 0x81a9, + 0xb1ca, + 0xa1eb, + 0xd10c, + 0xc12d, + 0xf14e, + 0xe16f, + 0x1080, + 0x00a1, + 0x30c2, + 0x20e3, + 0x5004, + 0x4025, + 0x7046, + 0x6067, + 0x83b9, + 0x9398, + 0xa3fb, + 0xb3da, + 0xc33d, + 0xd31c, + 0xe37f, + 0xf35e, + 0x02b1, + 0x1290, + 0x22f3, + 0x32d2, + 0x4235, + 0x5214, + 0x6277, + 0x7256, + 0xb5ea, + 0xa5cb, + 0x95a8, + 0x8589, + 0xf56e, + 0xe54f, + 0xd52c, + 0xc50d, + 0x34e2, + 0x24c3, + 0x14a0, + 0x0481, + 0x7466, + 0x6447, + 0x5424, + 0x4405, + 0xa7db, + 0xb7fa, + 0x8799, + 0x97b8, + 0xe75f, + 0xf77e, + 0xc71d, + 0xd73c, + 0x26d3, + 0x36f2, + 0x0691, + 0x16b0, + 0x6657, + 0x7676, + 0x4615, + 0x5634, + 0xd94c, + 0xc96d, + 0xf90e, + 0xe92f, + 0x99c8, + 0x89e9, + 0xb98a, + 0xa9ab, + 0x5844, + 0x4865, + 0x7806, + 0x6827, + 0x18c0, + 0x08e1, + 0x3882, + 0x28a3, + 0xcb7d, + 0xdb5c, + 0xeb3f, + 0xfb1e, + 0x8bf9, + 0x9bd8, + 0xabbb, + 0xbb9a, + 0x4a75, + 0x5a54, + 0x6a37, + 0x7a16, + 0x0af1, + 0x1ad0, + 0x2ab3, + 0x3a92, + 0xfd2e, + 0xed0f, + 0xdd6c, + 0xcd4d, + 0xbdaa, + 0xad8b, + 0x9de8, + 0x8dc9, + 0x7c26, + 0x6c07, + 0x5c64, + 0x4c45, + 0x3ca2, + 0x2c83, + 0x1ce0, + 0x0cc1, + 0xef1f, + 0xff3e, + 0xcf5d, + 0xdf7c, + 0xaf9b, + 0xbfba, + 0x8fd9, + 0x9ff8, + 0x6e17, + 0x7e36, + 0x4e55, + 0x5e74, + 0x2e93, + 0x3eb2, + 0x0ed1, + 0x1ef0 + ]; int crc_16(buffer) { var len = buffer.length; - var value_ = 0x0000;//0xa635; //初始值,根据CRC类型设定 + var value_ = 0x0000; //0xa635; //初始值,根据CRC类型设定 var tmp; - for (var i = 0; i < buffer.length; i++) - { + for (var i = 0; i < buffer.length; i++) { tmp = reverse8(buffer[i]); - value_ = ((value_ << 8) ^ crcTable[((value_ >> 8) ^ tmp) & 0xFF]) & 0xFFFF; + value_ = + ((value_ << 8) ^ crcTable[((value_ >> 8) ^ tmp) & 0xFF]) & 0xFFFF; } value_ = reverse16(value_); return value_; @@ -116,22 +360,21 @@ abstract class SenderProtocol extends IOData { int reverse8(data) { var i; - var temp=0; - for(i=0;i<8;i++) { + var temp = 0; + for (i = 0; i < 8; i++) { //字节反转 - temp |= ((data>>i) & 0x01)<<(7-i); + temp |= ((data >> i) & 0x01) << (7 - i); } return temp; } int reverse16(data) { var i; - var temp=0; - for(i=0;i<16;i++) { + var temp = 0; + for (i = 0; i < 16; i++) { //反转 - temp |= ((data>>i) & 0x0001)<<(15-i); + temp |= ((data >> i) & 0x0001) << (15 - i); } return temp; } - -} \ No newline at end of file +} diff --git a/star_lock/lib/blue/io_tool/io_model.dart b/star_lock/lib/blue/io_tool/io_model.dart index 9651fff6..018ce49d 100644 --- a/star_lock/lib/blue/io_tool/io_model.dart +++ b/star_lock/lib/blue/io_tool/io_model.dart @@ -1,15 +1,12 @@ - import 'package:uuid/uuid.dart'; ///发送数据类 -enum DataChannel{ - ble, - udp -} +enum DataChannel { ble, udp } extension Extension on DataChannel { - bool get isBLE => this == DataChannel.ble; - bool get isUDP => this == DataChannel.udp; + bool get isBLE => this == DataChannel.ble; + + bool get isUDP => this == DataChannel.udp; } class EventSendModel { @@ -20,8 +17,16 @@ class EventSendModel { String? deviceId; Uuid? serviceId; Uuid? characteristicId; + bool? allowLongWrite = false; - EventSendModel({required this.data,this.topic,this.sendChannel, this.deviceId, this.serviceId, this.characteristicId}); + EventSendModel( + {required this.data, + this.topic, + this.sendChannel, + this.deviceId, + this.serviceId, + this.characteristicId, + this.allowLongWrite}); } ///接收数据类 @@ -30,26 +35,23 @@ class EventReceiveModel { String? tag = ''; DataChannel? sendChannel; - EventReceiveModel({ - required this.data, - this.sendChannel, - this.tag}); + EventReceiveModel({required this.data, this.sendChannel, this.tag}); } - ///解析数据域 class EventParseModel { int? type; int? commandIndex; dynamic data; + EventParseModel({required this.type, required this.data, this.commandIndex}); } - ///debug info model class StateModel { final String title; final String subTitle; final bool result; - StateModel({this.title= '',this.subTitle = '',this.result = false}); -} \ No newline at end of file + + StateModel({this.title = '', this.subTitle = '', this.result = false}); +} diff --git a/star_lock/lib/blue/io_type.dart b/star_lock/lib/blue/io_type.dart index 4b919584..491bf6d9 100644 --- a/star_lock/lib/blue/io_type.dart +++ b/star_lock/lib/blue/io_type.dart @@ -1,4 +1,3 @@ - //TODO:发送指令类型 enum CommandType { addUser, //增加用户 = 0x3001 @@ -13,6 +12,9 @@ enum CommandType { getLockPrivateKey, // 获取锁私钥 = 0x3091 calibrationTime, // 校时 = 0x30f0 readStarLockStatusInfo, //读星锁状态信息 0x3040 + startOATUpgrade, //OTA升级开始 0x30E0 + confirmationOTAUpgrade, //OTA升级开始 0x30E1 + processOTAUpgrade, //OTA升级过程 0x30E2 generalExtendedCommond, // 通用扩展指令 = 0x3030 gecChangeAdministratorPassword, // 通用扩展指令子命令-修改管理员密码 = 2 @@ -41,11 +43,10 @@ enum CommandType { gecAddFaceConfirmation, // 通用扩展指令子命令-添加人脸确认 = 84 } -extension ExtensionCommandType on CommandType { - - static CommandType getCommandType(int value){ +extension ExtensionCommandType on CommandType { + static CommandType getCommandType(int value) { CommandType type = CommandType.readLockStatusInfo; - switch(value){ + switch (value) { case 0x3001: { type = CommandType.addUser; @@ -111,6 +112,21 @@ extension ExtensionCommandType on CommandType { type = CommandType.readStarLockStatusInfo; } break; + case 0x30E0: + { + type = CommandType.startOATUpgrade; + } + break; + case 0x30E1: + { + type = CommandType.processOTAUpgrade; + } + break; + case 0x30E2: + { + type = CommandType.confirmationOTAUpgrade; + } + break; default: { type = CommandType.readLockStatusInfo; @@ -122,7 +138,7 @@ extension ExtensionCommandType on CommandType { int get typeValue { int type = 0x300A; - switch(this){ + switch (this) { case CommandType.addUser: type = 0x3001; break; @@ -162,6 +178,15 @@ extension ExtensionCommandType on CommandType { case CommandType.readStarLockStatusInfo: type = 0x3040; break; + case CommandType.startOATUpgrade: + type = 0x30E0; + break; + case CommandType.processOTAUpgrade: + type = 0x30E1; + break; + case CommandType.confirmationOTAUpgrade: + type = 0x30E2; + break; default: type = 0x300A; break; @@ -171,10 +196,13 @@ extension ExtensionCommandType on CommandType { return type; } + //加密类型 int get identifierValue { int type = 0x23; - switch(this){ + switch (this) { case CommandType.getLockPublicKey: + case CommandType.processOTAUpgrade: + //不加密 type = 0x20; break; case CommandType.getLockPrivateKey: @@ -187,64 +215,73 @@ extension ExtensionCommandType on CommandType { return type; } - String get typeName { - String t = ''; - switch(typeValue){ + String get typeName { + String t = ''; + switch (typeValue) { case 0x3001: - t = '增加用户'; + t = '增加用户'; break; case 0x3002: - t = '删除用户'; + t = '删除用户'; break; case 0x3003: - t = '修改用户'; + t = '修改用户'; break; case 0x3004: - t = '恢复出厂设置'; + t = '恢复出厂设置'; break; case 0x3005: - t = '开门'; + t = '开门'; break; case 0x300A: - t = '读取锁状态信息'; + t = '读取锁状态信息'; break; case 0x300B: - t = '转移权限'; + t = '转移权限'; break; case 0x3020: - t = '开门记录上报'; + t = '开门记录上报'; break; case 0x3030: - t = '通用扩展指令'; + t = '通用扩展指令'; break; case 0x3090: - t = '获取锁公钥'; + t = '获取锁公钥'; break; case 0x3091: - t = '获取锁私钥'; + t = '获取锁私钥'; break; case 0x30f0: - t = '校时'; + t = '校时'; break; case 0x30f1: - t = '同步位置信息'; + t = '同步位置信息'; break; case 0x30f2: - t = '运维开锁'; + t = '运维开锁'; break; case 0x3016: - t = '写酒店信息'; + t = '写酒店信息'; break; case 0x3017: - t = '读酒店信息'; + t = '读酒店信息'; break; case 0x3040: - t = '读星锁状态信息'; + t = '读星锁状态信息'; + break; + case 0x30E0: + t = 'oat升级'; + break; + case 0x30E2: + t = '确认oat升级'; + break; + case 0x30E1: + t = 'oat升级过程'; break; default: - t = '读星锁状态信息'; + t = '读星锁状态信息'; break; } return t; } -} \ 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 7637dda2..a03e31c7 100644 --- a/star_lock/lib/blue/reciver_data.dart +++ b/star_lock/lib/blue/reciver_data.dart @@ -9,6 +9,8 @@ import 'package:star_lock/blue/io_protocol/io_deletUser.dart'; import 'package:star_lock/blue/io_protocol/io_editUser.dart'; import 'package:star_lock/blue/io_protocol/io_factoryDataReset.dart'; import 'package:star_lock/blue/io_protocol/io_getLockStatu.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_protocol/io_queryingFaceStatus.dart'; import 'package:star_lock/blue/io_protocol/io_readAdminPassword.dart'; import 'package:star_lock/blue/io_protocol/io_readSupportFunctionsNoParameters.dart'; @@ -20,11 +22,14 @@ import 'package:star_lock/blue/io_protocol/io_timing.dart'; import 'package:star_lock/blue/io_protocol/io_transferPermissions.dart'; import '../tools/storage.dart'; + // import 'io_protocol/io_addFingerprint.dart'; import 'io_protocol/io_addFingerprintWithTimeCycleCoercion.dart'; + // import 'io_protocol/io_addICCard.dart'; import 'io_protocol/io_addICCardWithTimeCycleCoercion.dart'; import 'io_protocol/io_addStressFingerprint.dart'; + // import 'io_protocol/io_addStressICCard.dart'; import 'io_protocol/io_addStressPassword.dart'; import 'io_protocol/io_addUser.dart'; @@ -59,7 +64,7 @@ class CommandReciverManager { return; } - Get.log("appDataReceiveData:$data"); // &&(data[4] == 0x11) + // Get.log("appDataReceiveData:$data"); // &&(data[4] == 0x11) if ((data[0] == 0xEF) && (data[1] == 0x01) && (data[2] == 0xEE) && @@ -69,7 +74,7 @@ class CommandReciverManager { var dataLen = data[8] * 256 + data[9]; // 高16位用来指示后面数据块内容的长度 var oriLen = data[10] * 256 + data[11]; // 低16位用来指示数据加密前的原长度 - print("dataLen:$dataLen oriLen:$oriLen"); + // print("dataLen:$dataLen oriLen:$oriLen"); // List dataList = []; List oriDataList = []; switch (tmpType) { @@ -109,11 +114,11 @@ class CommandReciverManager { oriDataList = SM4.decrypt(getDataList, key: getPrivateKeyList, mode: SM4CryptoMode.ECB); oriDataList = oriDataList.sublist(0, oriLen); - print("SM4 oriDataList:$oriDataList"); + // print("SM4 oriDataList:$oriDataList"); break; } parseData(oriDataList).then((value) async { - Get.log("parseData222 data:$value"); + // Get.log("parseData222 data:$value"); EasyLoading.dismiss(); await EventBusManager().eventBusFir(value); }).catchError((error) { @@ -129,7 +134,7 @@ class CommandReciverManager { CommandType commandType = ExtensionCommandType.getCommandType(cmd); await IoManager().increaseCommandIndex(); // data.removeRange(0, 2); - Get.log("parseData cmd:$cmd commandType:$commandType data:$data"); + // Get.log("parseData cmd:$cmd commandType:$commandType data:$data"); var reply; switch (commandType) { case CommandType.getLockPublicKey: @@ -154,7 +159,7 @@ class CommandReciverManager { break; case CommandType.openLock: { - Get.log("openLockReply data:$data"); + // Get.log("openLockReply data:$data"); reply = OpenDoorReply.parseData(commandType, data); } break; @@ -189,6 +194,21 @@ class CommandReciverManager { reply = GetStarLockStatuInfoReply.parseData(commandType, data); } break; + case CommandType.startOATUpgrade: + { + reply = OTAUpgradeReply.parseData(commandType, data); + } + break; + case CommandType.confirmationOTAUpgrade: + { + reply = ConfirmationOTAUpgradeReply.parseData(commandType, data); + } + break; + case CommandType.processOTAUpgrade: + { + reply = ProcessOtaUpgradeReply.parseData(commandType, data); + } + break; case CommandType.generalExtendedCommond: { // 子命令类型 @@ -279,8 +299,9 @@ class CommandReciverManager { case 36: { // 注册指纹开始(带限时、循环、胁迫...) - reply = SenderAddFingerprintWithTimeCycleCoercionReply.parseData( - commandType, data); + reply = + SenderAddFingerprintWithTimeCycleCoercionReply.parseData( + commandType, data); } break; case 40: diff --git a/star_lock/lib/blue/sender_data.dart b/star_lock/lib/blue/sender_data.dart index 90c45722..34c28c53 100644 --- a/star_lock/lib/blue/sender_data.dart +++ b/star_lock/lib/blue/sender_data.dart @@ -1,4 +1,3 @@ - import 'dart:async'; import '../app_settings/app_settings.dart'; @@ -11,22 +10,26 @@ import 'io_tool/manager_event_bus.dart'; import 'sender_beforeDataManage.dart'; typedef CommandSendCallBack = void Function(ErrorType errorType); -class CommandSenderManager { +class CommandSenderManager { static final CommandSenderManager _manager = CommandSenderManager._init(); - factory CommandSenderManager()=>_manager; - static CommandSenderManager getInstance()=>_manager; - CommandSenderManager._init(){ + + factory CommandSenderManager() => _manager; + + static CommandSenderManager getInstance() => _manager; + + CommandSenderManager._init() { init(); } - init(){ + init() { initLockAddUserSucceedEvent(); } // 下级界面修改成功后传递数据 StreamSubscription? _passCurrentLockInformationEvent; List dataBeforeAddTheUser = []; + void initLockAddUserSucceedEvent() { // 蓝牙协议通知传输跟蓝牙之外的数据传输类不一样 eventBus _passCurrentLockInformationEvent = eventBus.on().listen((event) { @@ -55,7 +58,7 @@ class CommandSenderManager { } List value = command.packageData(); - print("CommonDataManage().currentLockUserNo:${CommonDataManage().currentLockUserNo}"); + // print("CommonDataManage().currentLockUserNo:${CommonDataManage().currentLockUserNo}"); if(CommonDataManage().currentLockUserNo == 0){ // 先添加用户 var entity = await SenderBeforeDataManage().getAddUserKeyData(); @@ -63,7 +66,7 @@ class CommandSenderManager { dataBeforeAddTheUser = value; return; }else{ - print("继续发送数据了继续发送数据了继续发送数据了"); + // print("继续发送数据了继续发送数据了继续发送数据了"); _sendNormalData(value); } } @@ -132,4 +135,4 @@ class CommandSenderManager { dispose() { _passCurrentLockInformationEvent?.cancel(); } -} \ 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 95292dba..9f1ee9f5 100644 --- a/star_lock/lib/blue/sender_manage.dart +++ b/star_lock/lib/blue/sender_manage.dart @@ -1,9 +1,12 @@ import 'package:star_lock/blue/io_protocol/io_addFace.dart'; + // import 'package:star_lock/blue/io_protocol/io_addICCard.dart'; // import 'package:star_lock/blue/io_protocol/io_addStressICCard.dart'; import 'package:star_lock/blue/io_protocol/io_changeAdministratorPassword.dart'; import 'package:star_lock/blue/io_protocol/io_deletUser.dart'; import 'package:star_lock/blue/io_protocol/io_getLockStatu.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_protocol/io_queryingFaceStatus.dart'; import 'package:star_lock/blue/io_protocol/io_readAdminPassword.dart'; @@ -359,23 +362,22 @@ class IoSenderManage { //todo:添加指纹开始(带限时、循环、胁迫...) static void senderAddFingerprintWithTimeCycleCoercionCommand( - { - required String? keyID, - required String? userID, - required int? fingerNo, - required int? useCountLimit, - required int? isForce, - required List? token, - required int? isRound, - required int? weekRound, - required int? startDate, - required int? endDate, - required String? startTime, - required String? endTime, - required int? needAuthor, - required List? signKey, - required List? privateKey, - CommandSendCallBack? callBack}) { + {required String? keyID, + required String? userID, + required int? fingerNo, + required int? useCountLimit, + required int? isForce, + required List? token, + required int? isRound, + required int? weekRound, + required int? startDate, + required int? endDate, + required String? startTime, + required String? endTime, + required int? needAuthor, + required List? signKey, + required List? privateKey, + CommandSendCallBack? callBack}) { CommandSenderManager().managerSendData( command: SenderAddFingerprintWithTimeCycleCoercionCommand( keyID: keyID, @@ -428,23 +430,22 @@ class IoSenderManage { //todo:添加卡开始(带限时、循环、胁迫...) static void senderAddCardWithTimeCycleCoercionCommand( - { - required String? keyID, - required String? userID, - required int? cardNo, - required int? useCountLimit, - required int? isForce, - required List? token, - required int? isRound, - required int? weekRound, - required int? startDate, - required int? endDate, - required String? startTime, - required String? endTime, - required int? needAuthor, - required List? signKey, - required List? privateKey, - CommandSendCallBack? callBack}) { + {required String? keyID, + required String? userID, + required int? cardNo, + required int? useCountLimit, + required int? isForce, + required List? token, + required int? isRound, + required int? weekRound, + required int? startDate, + required int? endDate, + required String? startTime, + required String? endTime, + required int? needAuthor, + required List? signKey, + required List? privateKey, + CommandSendCallBack? callBack}) { CommandSenderManager().managerSendData( command: SenderAddICCardWithTimeCycleCoercionCommand( keyID: keyID, @@ -469,20 +470,20 @@ class IoSenderManage { //todo:添加人脸开始 static void senderAddFaceCommand( {required String? keyID, - required String? userID, - required int? faceNo, - required int? useCountLimit, - required int? isForce, - required List? token, - required int? isRound, - required int? weekRound, - required int? startDate, - required int? endDate, - required String? startTime, - required String? endTime, - required int? needAuthor, - required List? signKey, - required List? privateKey, + required String? userID, + required int? faceNo, + required int? useCountLimit, + required int? isForce, + required List? token, + required int? isRound, + required int? weekRound, + required int? startDate, + required int? endDate, + required String? startTime, + required String? endTime, + required int? needAuthor, + required List? signKey, + required List? privateKey, CommandSendCallBack? callBack}) { CommandSenderManager().managerSendData( command: SenderAddFaceCommand( @@ -709,12 +710,12 @@ class IoSenderManage { //todo:wifi列表 static void getWifiListCommand( {required String? keyID, - required String? userID, - required List? token, - required int? needAuthor, - required List? publicKey, - required List? privateKey, - CommandSendCallBack? callBack}) { + required String? userID, + required List? token, + required int? needAuthor, + required List? publicKey, + required List? privateKey, + CommandSendCallBack? callBack}) { CommandSenderManager().managerSendData( command: SenderGetWifiCommand( keyID: keyID, @@ -977,4 +978,54 @@ class IoSenderManage { ), callBack: callBack); } + + //开始ota 升级 + static void senderOTAUpgradeCommand( + {required String? lockID, + required String? userID, + required String? keyID, + required int? platform, + required int? product, + required String? hwVersion, + required String? fwVersion, + required int? fwSize, + required String? fwMD5, + required int? needAuthor, + required List? token, + required List? publicKey, + required List? privateKey, + CommandSendCallBack? callBack}) { + CommandSenderManager().managerSendData( + command: OTAUpgradeCommand( + lockID: lockID, + userID: userID, + keyID: keyID, + platform: platform, + product: product, + hwVersion: hwVersion, + fwVersion: fwVersion, + fwSize: fwSize, + fwMD5: fwMD5, + token: token, + needAuthor: needAuthor, + publicKey: publicKey, + privateKey: privateKey, + ), + callBack: callBack); + } + + //ota 升级过程 + static void senderProcessOtaUpgradeCommand( + {required int? index, + required int? size, + required List? data, + CommandSendCallBack? callBack}) { + CommandSenderManager().managerSendData( + command: ProcessOtaUpgradeCommand( + index: index, + size: size, + data: data, + ), + callBack: callBack); + } } diff --git a/star_lock/lib/main/lockDetail/lockDetail/lockDetail_logic.dart b/star_lock/lib/main/lockDetail/lockDetail/lockDetail_logic.dart index 99bce8e2..a97048bb 100644 --- a/star_lock/lib/main/lockDetail/lockDetail/lockDetail_logic.dart +++ b/star_lock/lib/main/lockDetail/lockDetail/lockDetail_logic.dart @@ -34,7 +34,7 @@ class LockDetailLogic extends BaseGetXController { // 监听设备返回的数据 void initReplySubscription() { state.replySubscription = EventBusManager().eventBus!.on().listen((reply) async { - Get.log("锁详情收到了蓝牙解析消息 reply:${reply.commandType}"); + // Get.log("锁详情收到了蓝牙解析消息 reply:${reply.commandType}"); // 开门 if (reply is OpenDoorReply && state.ifCurrentScreen.value == true) { _replyOpenLock(reply); diff --git a/star_lock/lib/main/lockDetail/lockSet/lockEscalation/lockEscalation_logic.dart b/star_lock/lib/main/lockDetail/lockSet/lockEscalation/lockEscalation_logic.dart index 9c5cfb7e..69eb2bac 100644 --- a/star_lock/lib/main/lockDetail/lockSet/lockEscalation/lockEscalation_logic.dart +++ b/star_lock/lib/main/lockDetail/lockSet/lockEscalation/lockEscalation_logic.dart @@ -1,14 +1,41 @@ +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/advancedCalendar/src/datetime_util.dart'; import 'package:star_lock/tools/baseGetXController.dart'; +import 'package:star_lock/tools/commonDataManage.dart'; +import 'package:star_lock/tools/pickers/time_picker/time_utils.dart'; +import 'package:star_lock/tools/storage.dart'; import 'lockEscalation_state.dart'; -class LockEscalationLogic extends BaseGetXController{ +class LockEscalationLogic extends BaseGetXController { LockEscalationState state = LockEscalationState(); + StreamSubscription? _replySubscription; + + int otaCount = 0; + int otaIndex = 0; + Uint8List? otaBin; + int startSecond = 0; // 锁升级 - Future setLockSetGeneralSetting() async{ + Future setLockSetGeneralSetting() async { // var entity = await ApiRepository.to.getLockVersionInfoData( // lockId: state.getKeyInfosData.value.lockId.toString(), // ); @@ -17,24 +44,193 @@ class LockEscalationLogic extends BaseGetXController{ // } } + //手动升级 + Future otaUpdate() async { + var status = await PermissionDialog.request( + Permission.storage, '需要访问读写权限才能使用手动升级固件'); + 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(); + Map? headJson = await getHeadFile(data); + if (headJson is! Map) { + return; + } + otaBin = await checkFile(data, headJson); + if (otaBin == null) { + return; + } + startOTAData(); + blueOTAUpgrade(headJson); + } + + //蓝牙操作 ota 升级 + void blueOTAUpgrade(Map data) { + BlueManage().bludSendData(BlueManage().connectDeviceName, + (BluetoothConnectionState deviceConnectionState) async { + if (deviceConnectionState == BluetoothConnectionState.connected) { + var privateKey = await Storage.getStringList(saveBluePrivateKey); + List getPrivateKeyList = changeStringListToIntList(privateKey!); + var token = await Storage.getStringList(saveBlueToken); + List getTokenList = changeStringListToIntList(token!); + var publicKey = await Storage.getStringList(saveBluePublicKey); + List getPublicKeyList = changeStringListToIntList(publicKey!); + String lockID = CommonDataManage.shareManager() + ?.currentLockSetInfoData + .lockId + ?.toString() ?? + ''; + String keyID = + CommonDataManage.shareManager()?.currentKeyInfo.keyId?.toString() ?? + ''; + BlueManage().writeCharacteristicWithResponse(OTAUpgradeCommand( + lockID: lockID, + userID: await Storage.getUid(), + keyID: keyID, + 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: getTokenList, + publicKey: getPublicKeyList, + 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; + } + if (otaCount <= otaIndex) { + int now = DateTime.now().millisecondsSinceEpoch ~/ 1000; + String msg = '传输完成 时间:${now - startSecond}秒'; + closeOTADAta(); + print(msg); + showToast(msg); + return; + } + int star = otaIndex * 240; + int end = (otaIndex + 1) * 240; + if (end > length) { + end = length; + } + List data = otaBin!.sublist(star, end); + state.otaProgress.value = otaIndex / otaCount; + await BlueManage().writeCharacteristicWithResponse( + ProcessOtaUpgradeCommand(index: otaIndex, size: length, 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 { + // 检查文件头 + String header = utf8.decode(data.sublist(0, 12)); + if (header != 'SYD-BIN-DATA') { + showToast('非SYD固件,请选择正确的文件'); + return null; + } + // 解析元数据长度 + Uint8List metaLenList = data.sublist(12, 16); + int metaLen = ByteData.sublistView(metaLenList).getUint32(0); + if (metaLen < 2 || metaLen > 10240) { + showToast('元数据长度错误'); + return null; + } + // 读取和解析元数据 + Uint8List metaStrList = data.sublist(16, 16 + metaLen); + String metaStr = utf8.decode(metaStrList); + print(metaStr); + var meta = jsonDecode(metaStr); + 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(); + // if (md5Str != meta['fwMd5']) { + // showToast('固件MD5校验失败'); + // return false; + // } + if (bin.length != meta['fwSize']) { + showToast('固件校验失败'); + return null; + } + return bin; + } + @override void onReady() { - // TODO: implement onReady super.onReady(); - print("onReady()"); setLockSetGeneralSetting(); } @override void onInit() { - // TODO: implement onInit super.onInit(); - print("onInit()"); + _replySubscription = + EventBusManager().eventBus!.on().listen((reply) { + if (reply is OTAUpgradeReply && reply.status == 0x00) { + //验证通过,开始发送数据包 + processOtaUpgrade(); + } else if (reply is ProcessOtaUpgradeReply && reply.status == 0x00) { + otaIndex++; + processOtaUpgrade(); + } else if (reply is ConfirmationOTAUpgradeReply && reply.status == 0x00) { + closeOTADAta(); + showToast('固件升级完成'); + } + }); } @override void onClose() { - // TODO: implement onClose + _replySubscription?.cancel(); } - } diff --git a/star_lock/lib/main/lockDetail/lockSet/lockEscalation/lockEscalation_page.dart b/star_lock/lib/main/lockDetail/lockSet/lockEscalation/lockEscalation_page.dart index 5826a4f7..dde24faa 100644 --- a/star_lock/lib/main/lockDetail/lockSet/lockEscalation/lockEscalation_page.dart +++ b/star_lock/lib/main/lockDetail/lockSet/lockEscalation/lockEscalation_page.dart @@ -16,66 +16,152 @@ class LockEscalationPage extends StatefulWidget { } class _LockEscalationPageState extends State { - final logic = Get.put(LockEscalationLogic()); - final state = Get.find().state; - @override Widget build(BuildContext context) { - return Scaffold( - backgroundColor: Colors.white, - appBar: TitleAppBar( - barTitle: TranslationLoader.lanKeys!.lockEscalation!.tr, - haveBack: true, - backgroundColor: AppColors.mainColor), - body: Container( - padding: EdgeInsets.all(30.w), - child: Column( - children: [ - SizedBox( - height: 60.h, + return GetBuilder( + init: LockEscalationLogic(), + builder: (LockEscalationLogic logic) { + return Scaffold( + backgroundColor: Colors.white, + appBar: TitleAppBar( + barTitle: TranslationLoader.lanKeys!.lockEscalation!.tr, + haveBack: true, + backgroundColor: AppColors.mainColor, + backAction: logic.getBack, ), - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Image.asset( - 'images/main/icon_main_lockSet_lockEscalation.png', - width: 36.w, - height: 36.w, - ), - SizedBox( - width: 10.w, - ), - Text( - TranslationLoader.lanKeys!.haveNewVersion!.tr, - style: - TextStyle(fontSize: 24.sp, fontWeight: FontWeight.w600), - ) - ], - ), - SizedBox( - height: 30.h, - ), - Text( - "${TranslationLoader.lanKeys!.currentVersion!.tr}:1.0.0", - style: TextStyle( - fontSize: 18.sp, color: AppColors.darkGrayTextColor), - ), - SizedBox( - height: 10.h, - ), - Text( - // "${TranslationLoader.lanKeys!.newVersion!.tr}:1.0.1", - "未发现新版本", - style: TextStyle(color: AppColors.mainColor, fontSize: 18.sp), - ), - SizedBox( - height: 40.h, - ), - SubmitBtn( - btnName: TranslationLoader.lanKeys!.upgrade!.tr, - onClick: () {}), - ], - ), - )); + body: Container( + padding: EdgeInsets.all(30.w), + child: Column( + children: [ + Obx(() { + return logic.state.otaUpdateIng.value + ? PopScope( + canPop: false, + onPopInvoked: (didPop) async { + if (logic.state.otaUpdateIng.value) { + logic.closeOTADAta(); + } + }, + child: SizedBox(), + ) + : SizedBox(); + }), + SizedBox( + height: 60.h, + ), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Image.asset( + 'images/main/icon_main_lockSet_lockEscalation.png', + width: 36.w, + height: 36.w, + ), + SizedBox( + width: 10.w, + ), + Text( + TranslationLoader.lanKeys!.haveNewVersion!.tr, + style: TextStyle( + fontSize: 24.sp, fontWeight: FontWeight.w600), + ) + ], + ), + SizedBox( + height: 30.h, + ), + Text( + "${TranslationLoader.lanKeys!.currentVersion!.tr}:1.0.0", + style: TextStyle( + fontSize: 18.sp, color: AppColors.darkGrayTextColor), + ), + SizedBox( + height: 10.h, + ), + Obx(() { + return !logic.state.otaUpdateIng.value + ? Stack( + children: [ + Container( + margin: EdgeInsets.only(top: 8, bottom: 8), + width: Get.width, + child: Center( + child: Text( + // "${TranslationLoader.lanKeys!.newVersion!.tr}:1.0.1", + "未发现新版本", + style: TextStyle( + color: AppColors.mainColor, + fontSize: 18.sp), + ), + ), + ), + Positioned( + right: 80.w, + child: GestureDetector( + onTap: () { + logic.otaUpdate(); + }, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Text( + '手动升级', + style: TextStyle( + color: AppColors.mainColor, + fontSize: 18.sp, + fontWeight: FontWeight.w400), + ), + ), + ), + ) + ], + ) + : Padding( + padding: EdgeInsets.symmetric( + horizontal: 50.w, vertical: 15.h), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Text( + '固件传输中', + style: TextStyle( + color: AppColors.mainColor, + fontSize: 18.sp, + fontWeight: FontWeight.w400), + ), + SizedBox( + width: 10.w, + ), + Expanded( + child: ClipRRect( + borderRadius: BorderRadius.all( + Radius.circular(10.r)), + child: LinearProgressIndicator( + value: logic + .state.otaProgress.value, // 50% 进度 + backgroundColor: Colors.grey[200], + valueColor: + AlwaysStoppedAnimation( + AppColors.mainColor), + ), + ), + ), + ], + ), + ); + }), + SizedBox( + height: 40.h, + ), + Obx(() { + return !logic.state.otaUpdateIng.value + ? SubmitBtn( + btnName: TranslationLoader.lanKeys!.upgrade!.tr, + onClick: () {}) + : SizedBox(); + }), + ], + ), + )); + }); } } diff --git a/star_lock/lib/main/lockDetail/lockSet/lockEscalation/lockEscalation_state.dart b/star_lock/lib/main/lockDetail/lockSet/lockEscalation/lockEscalation_state.dart index 3a0b472d..a53bd383 100644 --- a/star_lock/lib/main/lockDetail/lockSet/lockEscalation/lockEscalation_state.dart +++ b/star_lock/lib/main/lockDetail/lockSet/lockEscalation/lockEscalation_state.dart @@ -1,4 +1,6 @@ +import 'package:get/get.dart'; -class LockEscalationState{ - +class LockEscalationState { + var otaUpdateIng = false.obs; + var otaProgress = 0.00.obs; } diff --git a/star_lock/lib/permission/permission_dialog.dart b/star_lock/lib/permission/permission_dialog.dart index 891ba9d3..ce50bc24 100644 --- a/star_lock/lib/permission/permission_dialog.dart +++ b/star_lock/lib/permission/permission_dialog.dart @@ -84,7 +84,7 @@ class PermissionDialog { } //显示权限判断申请框 - static Future request(Permission permission) async { + static Future request(Permission permission, [String? content]) async { if (Get.context == null) { return false; } @@ -99,7 +99,7 @@ class PermissionDialog { canPop: false, child: CupertinoAlertDialog( title: Text('${'申请'.tr}${titles[permission] ?? ''}${'权限'.tr}'), - content: Text(contents[permission] ?? ''), + content: Text(content ?? contents[permission] ?? ''), actions: [ CupertinoDialogAction( child: Text('不允许'.tr), diff --git a/star_lock/pubspec.yaml b/star_lock/pubspec.yaml index 826617e3..e4fb4ea6 100644 --- a/star_lock/pubspec.yaml +++ b/star_lock/pubspec.yaml @@ -94,7 +94,7 @@ dependencies: #跳转到外部 url_launcher: ^6.1.10 #蓝牙 -# flutter_reactive_ble: ^5.1.1 + # flutter_reactive_ble: ^5.1.1 flutter_blue_plus: ^1.31.16 # event_bus: ^2.0.0 @@ -123,7 +123,7 @@ dependencies: # 谷歌地图 google_maps_flutter: ^2.2.5 -# geocoding: ^2.1.0 + # geocoding: ^2.1.0 # 允许App发现网络的相关信息并且进行相应的配置 network_info_plus: ^4.0.2 @@ -144,12 +144,12 @@ dependencies: image_gallery_saver: ^2.0.3 convert: ^3.1.1 just_audio: ^0.9.36 - # flutter_sound: ^9.2.13 -# ffmpeg_kit_flutter: 5.1.0-LTS + # flutter_sound: ^9.2.13 + # ffmpeg_kit_flutter: 5.1.0-LTS fast_gbk: ^1.0.0 flutter_pcm_sound: ^1.1.0 intl: ^0.18.0 -# flutter_audio_capture: <1.1.5 + # flutter_audio_capture: <1.1.5 flutter_voice_processor: ^1.1.1 #监听网络连接状态 @@ -165,6 +165,7 @@ dependencies: system_settings: ^2.0.0 expandable: ^5.0.1 colorfilter_generator: ^0.0.8 + file_picker: ^5.3.1 dev_dependencies: From 02ad8cd2e84a4be7d203270d0bf98c0f35abbc8f 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, 24 Apr 2024 17:01:59 +0800 Subject: [PATCH 4/4] =?UTF-8?q?1=E3=80=81=E4=BF=AE=E5=A4=8D=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E5=8D=A1=E8=BD=BB=E5=BE=AE=E5=B7=A6=E5=8F=B3=E6=BB=91?= =?UTF-8?q?=E5=8A=A8=E6=B7=BB=E5=8A=A0=E5=8D=A1=E7=B1=BB=E5=9E=8B=E4=B8=8D?= =?UTF-8?q?=E5=90=8C=E9=97=AE=E9=A2=98=E3=80=822=E3=80=81=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E6=A0=B9=E6=8D=AE=E9=91=AB=E9=94=81=E8=B7=9F=E9=94=81?= =?UTF-8?q?=E9=80=9A=E9=80=9A=E7=AE=97=E6=B3=95=E4=B8=8D=E5=90=8C=20APP?= =?UTF-8?q?=E5=8C=BA=E5=88=86=E7=94=9F=E6=88=90=E7=A6=BB=E7=BA=BF=E5=AF=86?= =?UTF-8?q?=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- star_lock/lib/appRouters.dart | 11 +- star_lock/lib/blue/io_modelVendor.dart | 13 + .../addCardTypeManage_tabbar.dart | 5 +- .../card/addCardType/addCardType_logic.dart | 23 +- .../card/addCardType/addCardType_page.dart | 260 +++++++++++------- .../card/addCardType/addCardType_state.dart | 20 +- .../card/cardList/cardList_page.dart | 2 +- .../checkingInAddStaff_page.dart | 2 +- .../lockDetail/lockDetail_logic.dart | 2 +- .../lockDetail/lockNetToken_entity.dart | 2 +- .../passwordKey_perpetual_logic.dart | 32 ++- .../passwordKey_perpetual_page.dart | 24 +- 12 files changed, 252 insertions(+), 144 deletions(-) create mode 100644 star_lock/lib/blue/io_modelVendor.dart diff --git a/star_lock/lib/appRouters.dart b/star_lock/lib/appRouters.dart index 9b54cce3..af486893 100644 --- a/star_lock/lib/appRouters.dart +++ b/star_lock/lib/appRouters.dart @@ -57,6 +57,7 @@ import 'login/login/starLock_login_page.dart'; import 'login/register/starLock_register_page.dart'; import 'login/selectCountryRegion/selectCountryRegion_page.dart'; import 'main/lockDetail/card/addCardType/addCardManage/addCardTypeManage_page.dart'; +import 'main/lockDetail/card/addCardType/addCardType_page.dart'; import 'main/lockDetail/card/addICCard/addICCard_page.dart'; import 'main/lockDetail/card/cardDetail/cardDetail_page.dart'; import 'main/lockDetail/card/cardList/cardList_page.dart'; @@ -416,7 +417,8 @@ abstract class Routers { '/AddRemoteControlManagePage'; // 添加遥控 static const cardListPage = '/CardListPage'; // 卡列表 - static const addCardTypeManagePage = '/AddCardTypeManagePage'; // 添加卡 + // static const addCardTypeManagePage = '/AddCardTypeManagePage'; // 添加卡 + static const addCardPage = '/AddCardPage'; // 添加卡 static const cardDetailPage = '/CardDetailPage'; // 卡详情 static const fingerprintListPage = '/FingerprintListPage'; // 指纹列表 static const addFingerprintTypeManagePage = @@ -1009,9 +1011,12 @@ abstract class AppRouters { name: Routers.addRemoteControlManagePage, page: () => const AddRemoteControlManagePage()), GetPage(name: Routers.cardListPage, page: () => const CardListPage()), + // GetPage( + // name: Routers.addCardTypeManagePage, + // page: () => const AddCardTypeManagePage()), GetPage( - name: Routers.addCardTypeManagePage, - page: () => const AddCardTypeManagePage()), + name: Routers.addCardPage, + page: () => const AddCardPage()), GetPage(name: Routers.cardDetailPage, page: () => const CardDetailPage()), GetPage( name: Routers.fingerprintListPage, diff --git a/star_lock/lib/blue/io_modelVendor.dart b/star_lock/lib/blue/io_modelVendor.dart new file mode 100644 index 00000000..268b206b --- /dev/null +++ b/star_lock/lib/blue/io_modelVendor.dart @@ -0,0 +1,13 @@ + +// ignore_for_file: non_constant_identifier_names + +class IoModelVendor { + + static String vendor_XHJ = 'XHJ'; + static String model_XHJ_SYD = 'SYD-BLE-01'; + static String model_XHJ_JL = 'JL-BLE-01'; + + static String vendor_XL = 'XL'; + static String model_XL_BLE = 'JL-BLE-01'; + static String model_XL_WIFI = 'JL-WIFI-01'; +} diff --git a/star_lock/lib/main/lockDetail/card/addCardType/addCardManage/addCardTypeManage_tabbar.dart b/star_lock/lib/main/lockDetail/card/addCardType/addCardManage/addCardTypeManage_tabbar.dart index db9c485d..12d283e2 100644 --- a/star_lock/lib/main/lockDetail/card/addCardType/addCardManage/addCardTypeManage_tabbar.dart +++ b/star_lock/lib/main/lockDetail/card/addCardType/addCardManage/addCardTypeManage_tabbar.dart @@ -50,6 +50,7 @@ class _AddCardManageTabbarState extends State length: widget.fromType == 1 ? _itemTabs.length : _fromCheckInTypeItemTabs.length, initialIndex: widget.initialIndex); _tabController.addListener(() { + print("_tabController.indexIsChanging:${_tabController.indexIsChanging} _tabController.index:${_tabController.index}"); if (_tabController.animation!.value == _tabController.index) { FocusScope.of(context).requestFocus(FocusNode()); } @@ -107,8 +108,8 @@ class _AddCardManageTabbarState extends State controller: _tabController, children: widget.fromType == 1 - ? _itemTabs.map((ItemView item) => AddCardPage(selectType: item.selectType, lockId: widget.lockId, fromType: widget.fromType, fromTypeTwoStaffName: widget.fromTypeTwoStaffName)).toList() - : _fromCheckInTypeItemTabs.map((ItemView item) => AddCardPage(selectType: item.selectType, lockId: widget.lockId, fromType: widget.fromType, fromTypeTwoStaffName: widget.fromTypeTwoStaffName)).toList(), + ? _itemTabs.map((ItemView item) => AddCardPage()).toList() + : _fromCheckInTypeItemTabs.map((ItemView item) => AddCardPage()).toList(), ), ); } diff --git a/star_lock/lib/main/lockDetail/card/addCardType/addCardType_logic.dart b/star_lock/lib/main/lockDetail/card/addCardType/addCardType_logic.dart index ad989d33..ab7f5561 100644 --- a/star_lock/lib/main/lockDetail/card/addCardType/addCardType_logic.dart +++ b/star_lock/lib/main/lockDetail/card/addCardType/addCardType_logic.dart @@ -12,21 +12,23 @@ class AddCardTypeLogic extends BaseGetXController{ // 添加卡数据 void addCardData() async { - var fingerprintType = 0; // 永久:1;限时2,单次3,循环:4 + var carType = 0; // 永久:1;限时2,单次3,循环:4 var startDate = ""; var endDate = ""; var startTime = ""; var endTime = ""; if (state.selectType.value == "0") { - fingerprintType = 1; + print("永久卡永久卡永久卡"); + carType = 1; startDate = "0"; endDate = "0"; startTime = "0"; endTime = "0"; } else if (state.selectType.value == "1") { - fingerprintType = 2; - startDate = DateTool().dateToTimestamp(state.beginTime.value, 1).toString(); - endDate = DateTool().dateToTimestamp(state.endTime.value, 1).toString(); + print("限时卡限时卡限时卡"); + carType = 2; + startDate = DateTool().dateToTimestamp(state.timeLimitBeginTime.value, 1).toString(); + endDate = DateTool().dateToTimestamp(state.timeLimitEndTime.value, 1).toString(); startTime = "0"; endTime = "0"; @@ -49,15 +51,16 @@ class AddCardTypeLogic extends BaseGetXController{ return; } } else if (state.selectType.value == "2") { - if (state.beginTime.value.isEmpty) { + print("循环卡循环卡循环卡"); + if (state.cycleBeginTime.value.isEmpty) { showToast("请选择有效期".tr); return; } - startDate = DateTool().dateToTimestamp(state.beginTime.value, 1).toString(); - endDate = DateTool().dateToTimestamp(state.endTime.value, 1).toString(); + startDate = DateTool().dateToTimestamp(state.cycleBeginTime.value, 1).toString(); + endDate = DateTool().dateToTimestamp(state.cycleEndTime.value, 1).toString(); startTime = DateTool().dateToTimestamp(state.effectiveDateTime.value, 0).toString(); endTime = DateTool().dateToTimestamp(state.failureDateTime.value, 0).toString(); - fingerprintType = 4; + carType = 4; } // var isCoerced = state.isStressFingerprint.value == false ? "1" : "2"; // 1:非胁迫卡 2:胁迫卡 @@ -67,7 +70,7 @@ class AddCardTypeLogic extends BaseGetXController{ "addType": "1", "cardName": state.nameController.text, "cardNumber": "123456", - "cardType": fingerprintType.toString(), + "cardType": carType.toString(), "isCoerced": state.isStressFingerprint.value == false ? "1" : "2", "startDate": startDate, "weekDay": state.weekdaysList.value, diff --git a/star_lock/lib/main/lockDetail/card/addCardType/addCardType_page.dart b/star_lock/lib/main/lockDetail/card/addCardType/addCardType_page.dart index a773a8df..feba7075 100644 --- a/star_lock/lib/main/lockDetail/card/addCardType/addCardType_page.dart +++ b/star_lock/lib/main/lockDetail/card/addCardType/addCardType_page.dart @@ -1,3 +1,4 @@ + import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; @@ -8,110 +9,113 @@ import 'package:star_lock/tools/pickers/time_picker/model/date_mode.dart'; import '../../../../appRouters.dart'; import '../../../../app_settings/app_colors.dart'; +import '../../../../tools/CustomUnderlineTabIndicator.dart'; import '../../../../tools/commonItem.dart'; import '../../../../tools/dateTool.dart'; import '../../../../tools/storage.dart'; import '../../../../tools/submitBtn.dart'; +import '../../../../tools/titleAppBar.dart'; import '../../../../translations/trans_lib.dart'; import 'addCardType_logic.dart'; class AddCardPage extends StatefulWidget { - final String selectType; // 永久限时循环下标 - final int lockId; - final int fromType; // // 1从添加钥匙列表进入 2从考勤添加员工入口进入 - final String fromTypeTwoStaffName; // 从添加员工进入 传入员工名字 - - const AddCardPage( - {Key? key, - required this.selectType, - required this.lockId, - required this.fromType, - required this.fromTypeTwoStaffName}) - : super(key: key); + const AddCardPage({Key? key}) : super(key: key); @override State createState() => _AddCardPageState(); } -class _AddCardPageState extends State { +class _AddCardPageState extends State with SingleTickerProviderStateMixin { final logic = Get.put(AddCardTypeLogic()); final state = Get.find().state; - @override - Widget build(BuildContext context) { - state.selectType.value = widget.selectType; - state.lockId.value = widget.lockId; - if (widget.fromTypeTwoStaffName.isNotEmpty) { - state.nameController.text = widget.fromTypeTwoStaffName; - } - state.fromType.value = widget.fromType; - - return SingleChildScrollView( - child: indexChangeWidget() - ); - } - @override void initState() { // TODO: implement initState super.initState(); - WidgetsBinding.instance.addPostFrameCallback((_) { - if (state.selectType.value == "1") { - state.beginTime.value = DateTool().dateToYMDHNString( - DateTime.now().millisecondsSinceEpoch.toString()); //默认为当前时间 - state.endTime.value = DateTool().dateToYMDHNString( - DateTime.now().millisecondsSinceEpoch.toString()); //默认为当前时间 - } else { - state.beginTime.value = ""; //默认为当前时间 - state.endTime.value = ""; //默认为当前时间 + state.tabController = TabController( + vsync: this, + length: state.fromType.value == 1 ? _itemTabs.length : _fromCheckInTypeItemTabs.length, + initialIndex: 0); + state.tabController.addListener(() { + WidgetsBinding.instance.addPostFrameCallback((_) { + state.selectType.value = state.tabController.index.toString(); + }); + + if (state.tabController.animation!.value == state.tabController.index) { + FocusScope.of(context).requestFocus(FocusNode()); } }); } + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: AppColors.mainBackgroundColor, + appBar: TitleAppBar( + barTitle: + "${TranslationLoader.lanKeys!.addTip!.tr}${TranslationLoader.lanKeys!.card!.tr}", + haveBack: true, + backgroundColor: AppColors.mainColor), + body: Column( + children: [ + _tabBar(), + _pageWidget(), + ], + ), + ); + } Widget indexChangeWidget() { - switch (int.parse(widget.selectType)) { + switch (int.parse(state.selectType.value)) { case 0: { // 永久 - return Column( - children: [ - perpetualKeyWidget( - TranslationLoader.lanKeys!.name!.tr, - TranslationLoader.lanKeys!.pleaseEnter!.tr, - state.nameController), - keyBottomWidget() - ], + return SingleChildScrollView( + child: Column( + children: [ + perpetualKeyWidget( + TranslationLoader.lanKeys!.name!.tr, + TranslationLoader.lanKeys!.pleaseEnter!.tr, + state.nameController), + keyBottomWidget() + ], + ), ); } case 1: { // 限时 - return Column( - children: [ - perpetualKeyWidget( - TranslationLoader.lanKeys!.name!.tr, - TranslationLoader.lanKeys!.pleaseEnter!.tr, - state.nameController), - keyTimeLimitWidget(), - // SizedBox(height: 10.h), - keyBottomWidget() - ], + return SingleChildScrollView( + child: Column( + children: [ + perpetualKeyWidget( + TranslationLoader.lanKeys!.name!.tr, + TranslationLoader.lanKeys!.pleaseEnter!.tr, + state.nameController), + keyTimeLimitWidget(), + // SizedBox(height: 10.h), + keyBottomWidget() + ], + ), ); } case 2: { // 循环 - return Column( - children: [ - perpetualKeyWidget( - TranslationLoader.lanKeys!.name!.tr, - TranslationLoader.lanKeys!.pleaseEnter!.tr, - state.nameController), - keyCyclicDate(), - SizedBox(height: 10.h), - keyBottomWidget() - ], + return SingleChildScrollView( + child: Column( + children: [ + perpetualKeyWidget( + TranslationLoader.lanKeys!.name!.tr, + TranslationLoader.lanKeys!.pleaseEnter!.tr, + state.nameController), + keyCyclicDate(), + SizedBox(height: 10.h), + keyBottomWidget() + ], + ), ); } default: @@ -140,23 +144,23 @@ class _AddCardPageState extends State { children: [ Obx(() => CommonItem( leftTitel: TranslationLoader.lanKeys!.effectiveTime!.tr, - rightTitle: state.beginTime.value, + rightTitle: state.timeLimitBeginTime.value, isHaveLine: true, isHaveDirection: true, action: () async { Pickers.showDatePicker(context, mode: DateMode.YMDHM, onConfirm: (p) { - state.beginTime.value = DateTool().getYMDHNDateString(p, 1); + state.timeLimitBeginTime.value = DateTool().getYMDHNDateString(p, 1); }); })), Obx(() => CommonItem( leftTitel: TranslationLoader.lanKeys!.failureTime!.tr, - rightTitle: state.endTime.value, + rightTitle: state.timeLimitEndTime.value, isHaveDirection: true, action: () { Pickers.showDatePicker(context, mode: DateMode.YMDHM, onConfirm: (p) { - state.endTime.value = DateTool().getYMDHNDateString(p, 1); + state.timeLimitEndTime.value = DateTool().getYMDHNDateString(p, 1); }); })), Container(height: 10.h), @@ -170,21 +174,21 @@ class _AddCardPageState extends State { children: [ Obx(() => CommonItem( leftTitel: TranslationLoader.lanKeys!.periodValidity!.tr, - rightTitle: "${state.beginTime.value}\n${state.endTime.value}", + rightTitle:"${state.cycleBeginTime.value}\n${state.cycleEndTime.value}", isHaveDirection: true, isHaveLine: true, action: () async { var result = await Get.toNamed(Routers.seletKeyCyclicDatePage, arguments: { 'validityValue': state.weekdaysList.value, - 'starDate': state.beginTime.value, - 'endDate': state.endTime.value, + 'starDate': state.cycleBeginTime.value, + 'endDate': state.cycleEndTime.value, 'starTime': state.effectiveDateTime.value, 'endTime': state.failureDateTime.value }); if (result != null && result.isNotEmpty) { state.weekdaysList.value = result['validityValue']; - state.beginTime.value = result['starDate']; - state.endTime.value = result['endDate']; + state.cycleBeginTime.value = result['starDate']; + state.cycleEndTime.value = result['endDate']; state.effectiveDateTime.value = result['starTime']; state.failureDateTime.value = result['endTime']; } @@ -197,18 +201,17 @@ class _AddCardPageState extends State { isHaveDirection: true, isHaveLine: true, action: () async { - var result = await Get.toNamed(Routers.seletKeyCyclicDatePage, - arguments: { - 'validityValue': state.weekdaysList.value, - 'starDate': state.beginTime.value, - 'endDate': state.endTime.value, - 'starTime': state.effectiveDateTime.value, - 'endTime': state.failureDateTime.value - }); + var result = await Get.toNamed(Routers.seletKeyCyclicDatePage, arguments: { + 'validityValue': state.weekdaysList.value, + 'starDate': state.cycleBeginTime.value, + 'endDate': state.cycleEndTime.value, + 'starTime': state.effectiveDateTime.value, + 'endTime': state.failureDateTime.value + }); if (result != null && result.isNotEmpty) { state.weekdaysList.value = result['validityValue']; - state.beginTime.value = result['starDate']; - state.endTime.value = result['endDate']; + state.cycleBeginTime.value = result['starDate']; + state.cycleEndTime.value = result['endDate']; state.effectiveDateTime.value = result['starTime']; state.failureDateTime.value = result['endTime']; } @@ -217,25 +220,22 @@ class _AddCardPageState extends State { visible: state.effectiveDateTime.value.isNotEmpty, child: CommonItem( leftTitel: "有效时间".tr, - rightTitle: - "${state.effectiveDateTime.value}-${state.failureDateTime.value}", + rightTitle: "${state.effectiveDateTime.value}-${state.failureDateTime.value}", isHaveDirection: true, action: () async { - var result = await Get.toNamed(Routers.seletKeyCyclicDatePage, - arguments: { - 'validityValue': state.weekdaysList.value, - 'starDate': state.beginTime.value, - 'endDate': state.endTime.value, - 'starTime': state.effectiveDateTime.value, - 'endTime': state.failureDateTime.value - }); + var result = await Get.toNamed(Routers.seletKeyCyclicDatePage, arguments: { + 'validityValue': state.weekdaysList.value, + 'starDate': state.cycleBeginTime.value, + 'endDate': state.cycleEndTime.value, + 'starTime': state.effectiveDateTime.value, + 'endTime': state.failureDateTime.value + }); if (result != null && result.isNotEmpty) { state.weekdaysList.value = result['validityValue']; - state.beginTime.value = result['starDate']; - state.endTime.value = result['endDate']; + state.cycleBeginTime.value = result['starDate']; + state.cycleEndTime.value = result['endDate']; state.effectiveDateTime.value = result['starTime']; state.failureDateTime.value = result['endTime']; - Get.back(result: result); } }))), ], @@ -368,4 +368,70 @@ class _AddCardPageState extends State { }, ); } + + final List _itemTabs = [ + ItemView(title: TranslationLoader.lanKeys!.permanent!.tr, selectType: "0"), + ItemView(title: TranslationLoader.lanKeys!.timeLimit!.tr, selectType: "1"), + ItemView(title: TranslationLoader.lanKeys!.circulation!.tr, selectType: "2"), + ]; + + final List _fromCheckInTypeItemTabs = [ + ItemView(title: TranslationLoader.lanKeys!.permanent!.tr, selectType: "0"), + ItemView(title: TranslationLoader.lanKeys!.timeLimit!.tr, selectType: "1"), + ]; + + TabBar _tabBar() { + return TabBar( + controller: state.tabController, + onTap: (index) { + FocusScope.of(context).requestFocus(FocusNode()); + }, + tabs: state.fromType.value == 1 ? _itemTabs.map((ItemView item) => _tab(item)).toList() : _fromCheckInTypeItemTabs.map((ItemView item) => _tab(item)).toList(), + isScrollable: true, + indicatorColor: Colors.red, + unselectedLabelColor: Colors.black, + unselectedLabelStyle: TextStyle( + color: AppColors.mainColor, + fontSize: 24.sp, + ), + automaticIndicatorColorAdjustment: true, + labelColor: AppColors.mainColor, + labelStyle: TextStyle( + color: AppColors.mainColor, + fontSize: 24.sp, + fontWeight: FontWeight.w600), + indicator: CustomUnderlineTabIndicator( + borderSide: BorderSide(color: AppColors.mainColor, width: 4.w), + strokeCap: StrokeCap.round, + width: 30.w), + ); + } + + Tab _tab(ItemView item) { + return Tab( + child: SizedBox( + width: 1.sw / 5, + child: Text(item.title, textAlign: TextAlign.center))); + } + + Widget _pageWidget() { + return Expanded( + child: TabBarView( + controller: state.tabController, + children: + state.fromType.value == 1 + ? _itemTabs.map((ItemView item) => Obx(() => indexChangeWidget())).toList() + : _fromCheckInTypeItemTabs.map((ItemView item) => Obx(() => indexChangeWidget())).toList(), + ), + ); + } + } + +class ItemView { + const ItemView({required this.title, required this.selectType}); + + final String title; + final String selectType; +} + diff --git a/star_lock/lib/main/lockDetail/card/addCardType/addCardType_state.dart b/star_lock/lib/main/lockDetail/card/addCardType/addCardType_state.dart index 411be2e8..1c234082 100644 --- a/star_lock/lib/main/lockDetail/card/addCardType/addCardType_state.dart +++ b/star_lock/lib/main/lockDetail/card/addCardType/addCardType_state.dart @@ -2,6 +2,8 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; +import '../../../../tools/dateTool.dart'; + class AddCardTypeState{ final lockId = 0.obs; @@ -10,16 +12,24 @@ class AddCardTypeState{ final isStressFingerprint = false.obs; final isAdministrator = false.obs;// 是否是管理员 - var beginTime = "".obs;// 开始时间 - var endTime = "".obs;// 结束时间 + var timeLimitBeginTime = DateTool().dateToYMDHNString(DateTime.now().millisecondsSinceEpoch.toString()).obs;// 限时开始时间 + var timeLimitEndTime = DateTool().dateToYMDHNString(DateTime.now().millisecondsSinceEpoch.toString()).obs;// 限时结束时间 + var cycleBeginTime = "".obs;// 循环开始时间 + var cycleEndTime = "".obs;// 循环结束时间 var effectiveDateTime = "".obs;// 生效时间 var failureDateTime = "".obs;// 失效时间 var weekdaysList = [].obs; + var fromTypeTwoStaffName = "".obs; // 从添加员工进入 传入员工名字 final TextEditingController nameController = TextEditingController(); + late TabController tabController; AddCardTypeState() { - // Map map = Get.arguments; - // lockId.value = map["lockId"]; - // fromType.value = map["fromType"]; + Map map = Get.arguments; + lockId.value = map["lockId"]; + fromType.value = map["fromType"]; + // 1从添加钥匙列表进入 2从考勤添加员工入口进入 + if(fromType.value == 2){ + fromTypeTwoStaffName.value = map["fromTypeTwoStaffName"]; // 从添加员工进入 传入员工名字 + } } } diff --git a/star_lock/lib/main/lockDetail/card/cardList/cardList_page.dart b/star_lock/lib/main/lockDetail/card/cardList/cardList_page.dart index 4e1c399c..47508f6c 100644 --- a/star_lock/lib/main/lockDetail/card/cardList/cardList_page.dart +++ b/star_lock/lib/main/lockDetail/card/cardList/cardList_page.dart @@ -104,7 +104,7 @@ class _CardListPageState extends State with RouteAware { AddBottomWhiteBtn( btnName: '${TranslationLoader.lanKeys!.add!.tr}${TranslationLoader.lanKeys!.card!.tr}', onClick: () async { - var data = await Get.toNamed(Routers.addCardTypeManagePage, arguments: { + var data = await Get.toNamed(Routers.addCardPage, arguments: { "lockId": state.lockId.value, "fromType": 1 // 1从添加钥匙列表进入 2从考勤添加员工入口进入 }); diff --git a/star_lock/lib/main/lockDetail/checkingIn/checkingInStaff/checkingInSetAddStaff/checkingInAddStaff_page.dart b/star_lock/lib/main/lockDetail/checkingIn/checkingInStaff/checkingInSetAddStaff/checkingInAddStaff_page.dart index ba974948..385570d5 100644 --- a/star_lock/lib/main/lockDetail/checkingIn/checkingInStaff/checkingInSetAddStaff/checkingInAddStaff_page.dart +++ b/star_lock/lib/main/lockDetail/checkingIn/checkingInStaff/checkingInSetAddStaff/checkingInAddStaff_page.dart @@ -151,7 +151,7 @@ class _CheckingInAddStaffPageState extends State { } var data = await Get.toNamed( - Routers.addCardTypeManagePage, + Routers.addCardPage, arguments: { "lockId": state.getKeyInfosData.value.lockId, "fromType": 2, // 1从添加钥匙列表进入 2从考勤添加员工入口进入 diff --git a/star_lock/lib/main/lockDetail/lockDetail/lockDetail_logic.dart b/star_lock/lib/main/lockDetail/lockDetail/lockDetail_logic.dart index 99bce8e2..07ae34bb 100644 --- a/star_lock/lib/main/lockDetail/lockDetail/lockDetail_logic.dart +++ b/star_lock/lib/main/lockDetail/lockDetail/lockDetail_logic.dart @@ -496,7 +496,7 @@ class LockDetailLogic extends BaseGetXController { void getLockNetToken() async { LockNetTokenEntity entity = await ApiRepository.to.getLockNetToken(lockId: state.keyInfos.value.lockId.toString()); if (entity.errorCode!.codeIsSuccessful) { - state.lockNetToken = entity.data!.token!; + state.lockNetToken = entity.data!.token!.toString(); Get.log("state.lockNetToken:${state.lockNetToken}"); openDoorAction(); }else{ diff --git a/star_lock/lib/main/lockDetail/lockDetail/lockNetToken_entity.dart b/star_lock/lib/main/lockDetail/lockDetail/lockNetToken_entity.dart index fc74063a..b1be8d76 100644 --- a/star_lock/lib/main/lockDetail/lockDetail/lockNetToken_entity.dart +++ b/star_lock/lib/main/lockDetail/lockDetail/lockNetToken_entity.dart @@ -27,7 +27,7 @@ class LockNetTokenEntity { } class Data { - String? token; + int? token; Data({this.token}); 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 index 3e595dad..80294890 100644 --- 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 @@ -10,6 +10,7 @@ import 'package:star_lock/network/api_repository.dart'; import 'package:star_lock/tools/eventBusEventManage.dart'; import '../../../../blue/blue_manage.dart'; +import '../../../../blue/io_modelVendor.dart'; import '../../../../blue/io_reply.dart'; import '../../../../blue/io_protocol/io_senderCustomPasswords.dart'; import '../../../../blue/io_tool/io_tool.dart'; @@ -57,8 +58,16 @@ class PasswordKeyPerpetualLogic extends BaseGetXController { getKeyType = '2'; } else if (state.widgetType.value == 1) { //限时 - if(CommonDataManage().currentKeyInfo.vendor == "XL"){ - // 鑫鸿佳 + // 鑫鸿佳不需要生效时间 + if(CommonDataManage().currentKeyInfo.vendor == IoModelVendor.vendor_XHJ && (CommonDataManage().currentKeyInfo.model == IoModelVendor.model_XHJ_SYD || CommonDataManage().currentKeyInfo.model == IoModelVendor.model_XHJ_JL)){ + if (endDate <= DateTool().dateToTimestamp(DateTool().getNowDateWithType(3), 1)) { + showToast("失效时间要大于当前时间".tr); + return; + } + } + + // 芯连需要生效时间 + if(CommonDataManage().currentKeyInfo.vendor == IoModelVendor.vendor_XL && (CommonDataManage().currentKeyInfo.model == IoModelVendor.model_XL_BLE || CommonDataManage().currentKeyInfo.model == IoModelVendor.model_XL_WIFI)){ //限时 if (startDate < DateTool().dateToTimestamp(DateTool().getNowDateWithType(3), 1)) { showToast("生效时间不能小于当前时间".tr); @@ -69,12 +78,6 @@ class PasswordKeyPerpetualLogic extends BaseGetXController { showToast("失效时间要大于生效时间".tr); return; } - }else{ - if (endDate <= DateTool().dateToTimestamp(DateTool().getNowDateWithType(3), 1)) { - showToast("生效时间要大于当前时间".tr); - return; - } - // startDate = 0; } getKeyType = '3'; } else if (state.widgetType.value == 2) { @@ -84,13 +87,16 @@ class PasswordKeyPerpetualLogic extends BaseGetXController { //自定义 } else if (state.widgetType.value == 4) { //循环 - if (startDate < DateTool().dateToTimestamp(DateTool().getNowDateWithType(3), 1)) { - showToast("生效时间不能小于当前时间".tr); - return; + // 芯连需要结束时间 + if(CommonDataManage().currentKeyInfo.vendor == IoModelVendor.vendor_XL && (CommonDataManage().currentKeyInfo.model == IoModelVendor.model_XL_BLE || CommonDataManage().currentKeyInfo.model == IoModelVendor.model_XL_WIFI)){ + if (endDate < DateTool().dateToTimestamp(DateTool().getNowDateWithType(3), 1)) { + showToast("结束时间不能小于当前时间".tr); + return; + } } - if (endDate < DateTool().dateToTimestamp(DateTool().getNowDateWithType(3), 1)) { - showToast("结束时间不能小于当前时间".tr); + if (state.loopStartHours.value >= state.loopEndHours.value) { + showToast("失效时间要大于生效时间".tr); return; } diff --git a/star_lock/lib/main/lockDetail/passwordKey/passwordKey_perpetual/passwordKey_perpetual_page.dart b/star_lock/lib/main/lockDetail/passwordKey/passwordKey_perpetual/passwordKey_perpetual_page.dart index ac718ede..3f10ff8e 100644 --- a/star_lock/lib/main/lockDetail/passwordKey/passwordKey_perpetual/passwordKey_perpetual_page.dart +++ b/star_lock/lib/main/lockDetail/passwordKey/passwordKey_perpetual/passwordKey_perpetual_page.dart @@ -15,6 +15,7 @@ import 'package:star_lock/tools/storage.dart'; import '../../../../appRouters.dart'; import '../../../../blue/blue_manage.dart'; +import '../../../../blue/io_modelVendor.dart'; import '../../../../tools/NativeInteractionTool.dart'; import '../../../../tools/appRouteObserver.dart'; import '../../../../tools/commonItem.dart'; @@ -290,16 +291,19 @@ class _PasswordKeyPerpetualPageState extends State wit ]; showPickerView(context, pickerDataList); }), - CommonItem( - leftTitel: '结束日期', - rightTitle: state.endTime.value, - isHaveLine: true, - isHaveDirection: true, - action: () { - Pickers.showDatePicker(context, mode: DateMode.YMDH, onConfirm: (p) { - state.endTime.value = DateTool().getYMDHNDateString(p, 4); - }); - }), + Visibility( + visible: (CommonDataManage().currentKeyInfo.vendor == IoModelVendor.vendor_XL && (CommonDataManage().currentKeyInfo.model == IoModelVendor.model_XL_BLE || CommonDataManage().currentKeyInfo.model == IoModelVendor.model_XL_WIFI)) ? true : false, + child: CommonItem( + leftTitel: '结束日期', + rightTitle: state.endTime.value, + isHaveLine: true, + isHaveDirection: true, + action: () { + Pickers.showDatePicker(context, mode: DateMode.YMDH, onConfirm: (p) { + state.endTime.value = DateTool().getYMDHNDateString(p, 4); + }); + }), + ), CommonItem( leftTitel: TranslationLoader.lanKeys!.effectiveTime!.tr, rightTitle: state.loopEffectiveDate.value,