From e1011688def9599c9d0bc6519fe8a1e7a0d30e68 Mon Sep 17 00:00:00 2001 From: liyi Date: Wed, 22 Oct 2025 09:37:26 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E8=B0=83=E6=95=B4=E7=AC=AC=E4=B8=89?= =?UTF-8?q?=E6=96=B9=E5=B9=B3=E5=8F=B0=E8=AE=BE=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/blue/blue_manage.dart | 25 ++-- .../lockDetail/ActivateInfoResponse.dart | 120 +++++++++++++++--- .../lockDetail/lockDetail_logic.dart | 1 + .../third_party_platform_logic.dart | 77 ++++++----- .../third_party_platform_page.dart | 40 +++--- .../third_party_platform_state.dart | 7 +- lib/network/api.dart | 4 +- 7 files changed, 192 insertions(+), 82 deletions(-) diff --git a/lib/blue/blue_manage.dart b/lib/blue/blue_manage.dart index b14dc064..c04e646c 100755 --- a/lib/blue/blue_manage.dart +++ b/lib/blue/blue_manage.dart @@ -46,7 +46,7 @@ class BlueManage { StreamSubscription? _connectionStateSubscription; StreamSubscription? _mtuSubscription; - int? _mtuSize = 20; + int? _mtuSize = 30; // 当前连接设备的名字 String connectDeviceName = ''; @@ -813,30 +813,33 @@ class BlueManage { /// 写入蓝牙特征值,并等待响应 Future writeCharacteristicWithResponse(List value) async { - // 如果MTU还是默认值,尝试重新请求 - if (_mtuSize == 23 && bluetoothConnectDevice != null) { - try { - if (Platform.isAndroid) { - await bluetoothConnectDevice!.requestMtu(512); - } - } catch (e) { - AppLog.log('重新请求MTU失败: $e'); - } - } final List services = await bluetoothConnectDevice!.discoverServices(); for (final BluetoothService service in services) { if (service.uuid == _serviceIdConnect) { for (final BluetoothCharacteristic characteristic in service.characteristics) { if (characteristic.characteristicUuid == _characteristicIdWrite) { try { + _initGetMtuSubscription(); + // 如果MTU还是默认值,尝试重新请求 + if ((_mtuSize == 23 || _mtuSize == 20) && bluetoothConnectDevice != null) { + try { + if (Platform.isAndroid) { + await bluetoothConnectDevice!.requestMtu(512); + } + } catch (e) { + AppLog.log('重新请求MTU失败: $e'); + } + } // 添加重试机制 int retryCount = 0; const int maxRetries = 3; const int retryDelayMs = 500; final List valueList = value; + AppLog.log('发送数据时当前的mtuSize是:${_mtuSize}'); final List subData = splitList(valueList, _mtuSize!); + for (int i = 0; i < subData.length; i++) { // 对每个数据包都应用重试逻辑 bool packetSent = false; diff --git a/lib/main/lockDetail/lockDetail/ActivateInfoResponse.dart b/lib/main/lockDetail/lockDetail/ActivateInfoResponse.dart index 7c5ce8a1..0f81279b 100644 --- a/lib/main/lockDetail/lockDetail/ActivateInfoResponse.dart +++ b/lib/main/lockDetail/lockDetail/ActivateInfoResponse.dart @@ -1,24 +1,109 @@ +import 'dart:convert'; + class ActivateInfoResponse { ActivateInfoResponse({ this.description, this.errorCode, - this.data, // 现在是一个 List + this.data, // 现在是一个 List this.errorMsg, }); ActivateInfoResponse.fromJson(dynamic json) { description = json['description']; errorCode = json['errorCode']; - // 修改这里:如果 json['data'] 是列表,则解析为 List;否则为空列表 - data = json['data'] != null - ? (json['data'] as List).map((item) => ActivateInfo.fromJson(item)).toList() - : []; + // 修改这里:直接解析为单个 ActivateInfo 对象 + data = json['data'] != null ? ActivateInfo.fromJson(json['data']) : null; errorMsg = json['errorMsg']; } String? description; int? errorCode; - List? data; // 改为 List + ActivateInfo? data; // 改为 List + String? errorMsg; + + Map toJson() { + final map = {}; + map['description'] = description; + map['errorCode'] = errorCode; + if (data != null) { + // 修改这里:将单个 ActivateInfo 对象转换为 JSON + map['data'] = data!.toJson(); + } + map['errorMsg'] = errorMsg; + return map; + } + + @override + String toString() { + return 'ActivateInfoResponse{description: $description, errorCode: $errorCode, data: $data, errorMsg: $errorMsg}'; + } +} + +class ActivateInfo { + String? authCode; + String? activatedAt; + Map? extraParams; // 修改为 Map 类型 + + ActivateInfo({ + this.authCode, + this.activatedAt, + this.extraParams, + }); + + ActivateInfo.fromJson(dynamic json) { + authCode = json['auth_code'] ?? ''; + activatedAt = json['activated_at'] ?? ''; + // 修改这里:将 extraParams 解析为 Map 对象 + if (json['extra_params'] != null) { + if (json['extra_params'] is Map) { + extraParams = json['extra_params']; + } else if (json['extra_params'] is String) { + // 如果是字符串,尝试解析为 JSON 对象 + try { + extraParams = jsonDecode(json['extra_params']); + } catch (e) { + // 解析失败则设为 null 或空 map + extraParams = {}; + } + } + } else { + extraParams = {}; + } + } + + Map toJson() { + final map = {}; + map['authCode'] = authCode; + map['activatedAt'] = activatedAt; + map['extraParams'] = extraParams; + return map; + } + + @override + String toString() { + return 'ActivateInfo{authCode: $authCode, activatedAt: $activatedAt, extraParams: $extraParams}'; + } +} + +class TppSupportResponse { + TppSupportResponse({ + this.description, + this.errorCode, + this.data, // 现在是一个 List + this.errorMsg, + }); + + TppSupportResponse.fromJson(dynamic json) { + description = json['description']; + errorCode = json['errorCode']; + // 修改这里:如果 json['data'] 是列表,则解析为 List;否则为空列表 + data = json['data'] != null ? (json['data'] as List).map((item) => TppSupportInfo.fromJson(item)).toList() : []; + errorMsg = json['errorMsg']; + } + + String? description; + int? errorCode; + List? data; // 改为 List String? errorMsg; Map toJson() { @@ -35,33 +120,28 @@ class ActivateInfoResponse { @override String toString() { - return 'ActivateInfoResponse{description: $description, errorCode: $errorCode, data: $data, errorMsg: $errorMsg}'; + return 'TppSupportResponse{description: $description, errorCode: $errorCode, data: $data, errorMsg: $errorMsg}'; } } -class ActivateInfo { - String? platformName; +class TppSupportInfo { int? platform; + String? platformName; - ActivateInfo({ - this.platformName, + TppSupportInfo({ this.platform, + this.platformName, }); - ActivateInfo.fromJson(dynamic json) { - platformName = json['platformName'] ?? ''; - platform = json['platform'] ?? ''; + TppSupportInfo.fromJson(dynamic json) { + platform = json['platform'] as int? ?? -1; + platformName = json['platform_name'] as String? ?? ''; } Map toJson() { final map = {}; - map['platformName'] = platformName; map['platform'] = platform; + map['platform_name'] = platformName; return map; } - - @override - String toString() { - return 'ActivateInfo{platformName: $platformName, platform: $platform}'; - } } diff --git a/lib/main/lockDetail/lockDetail/lockDetail_logic.dart b/lib/main/lockDetail/lockDetail/lockDetail_logic.dart index 2be53435..432c2052 100755 --- a/lib/main/lockDetail/lockDetail/lockDetail_logic.dart +++ b/lib/main/lockDetail/lockDetail/lockDetail_logic.dart @@ -658,6 +658,7 @@ class LockDetailLogic extends BaseGetXController { if (list.isEmpty) { return; } + AppLog.log('list:${list}'); final KeyOperationRecordEntity entity = await ApiRepository.to.lockRecordUploadData(lockId: state.keyInfos.value.lockId.toString(), records: list); if (entity.errorCode!.codeIsSuccessful) { diff --git a/lib/main/lockDetail/lockSet/thirdPartyPlatform/third_party_platform_logic.dart b/lib/main/lockDetail/lockSet/thirdPartyPlatform/third_party_platform_logic.dart index 5ec189b9..6b45b55c 100644 --- a/lib/main/lockDetail/lockSet/thirdPartyPlatform/third_party_platform_logic.dart +++ b/lib/main/lockDetail/lockSet/thirdPartyPlatform/third_party_platform_logic.dart @@ -29,7 +29,24 @@ class ThirdPartyPlatformLogic extends BaseGetXController { super.onReady(); await getActivateInfo(); _initReplySubscription(); - getServerDatetime(); + await getServerDatetime(); + showEasyLoading(); + showBlueConnetctToastTimer(action: () { + dismissEasyLoading(); + }); + BlueManage().blueSendData( + BlueManage().connectDeviceName, + (BluetoothConnectionState connectionState) async { + if (connectionState == BluetoothConnectionState.connected) { + IoSenderManage.readRegisterKey( + lockID: BlueManage().connectDeviceName, + ); + } else if (connectionState == BluetoothConnectionState.disconnected) { + dismissEasyLoading(); + cancelBlueConnetctToastTimer(); + } + }, + ); } @override @@ -57,6 +74,7 @@ class ThirdPartyPlatformLogic extends BaseGetXController { Future getServerDatetime() async { final GetServerDatetimeEntity entity = await ApiRepository.to.getServerDatetimeData(isUnShowLoading: true); if (entity.errorCode!.codeIsSuccessful) { + state.serverTime = entity.data!.date! ~/ 1000; state.differentialTime = entity.data!.date! ~/ 1000 - DateTime.now().millisecondsSinceEpoch ~/ 1000; } } @@ -72,7 +90,6 @@ class ThirdPartyPlatformLogic extends BaseGetXController { return; } _replySubscription = EventBusManager().eventBus!.on().listen((Reply reply) async { - AppLog.log('输出了listen:${_replySubscription.hashCode}'); if (reply is SenderReadRegisterKeyCommandReply) { _handleReadRegisterKeyReply(reply); } @@ -158,7 +175,7 @@ class ThirdPartyPlatformLogic extends BaseGetXController { uuid: response.data?.extraParams?['uuid'], key: response.data?.authCode, mac: response.data?.extraParams?['mac'], - platform: 1, + platform: state.selectPlatFormIndex.value, utcTimeStamp: getUTCNetTime(), ); } else if (connectionState == BluetoothConnectionState.disconnected) { @@ -191,25 +208,11 @@ class ThirdPartyPlatformLogic extends BaseGetXController { void savePlatFormSetting() { if (state.selectPlatFormIndex.value == 1 || state.selectPlatFormIndex.value == 0) { - showEasyLoading(); - showBlueConnetctToastTimer(action: () { - dismissEasyLoading(); - }); - BlueManage().blueSendData( - BlueManage().connectDeviceName, - (BluetoothConnectionState connectionState) async { - if (connectionState == BluetoothConnectionState.connected) { - IoSenderManage.readRegisterKey( - lockID: BlueManage().connectDeviceName, - ); - } else if (connectionState == BluetoothConnectionState.disconnected) { - dismissEasyLoading(); - cancelBlueConnetctToastTimer(); - } - }, - ); + if (state.registerKey.isNotEmpty) { + _requestAuthorizationCode(); + } } else { - showToast('目前只支持切换至涂鸦智能协议'.tr); + showToast('目前只支持切换至涂鸦智能、锁通通协议'.tr); } } @@ -232,15 +235,14 @@ class ThirdPartyPlatformLogic extends BaseGetXController { switch (status) { case 0x00: + final platform = reply.data[7]; // 提取 RegisterKey (从第7个字节开始,长度为40) - final List registerKeyBytes = reply.data.sublist(7, 47); + final List registerKeyBytes = reply.data.sublist(8, 48); final String registerKey = String.fromCharCodes(registerKeyBytes); - + state.selectPlatFormIndex.value = platform; + print('platform: $platform'); print('Register Key: $registerKey'); state.registerKey.value = registerKey; - if (registerKey.isNotEmpty) { - _requestAuthorizationCode(); - } //成功 cancelBlueConnetctToastTimer(); dismissEasyLoading(); @@ -265,8 +267,8 @@ class ThirdPartyPlatformLogic extends BaseGetXController { IoSenderManage.senderGetStarLockStatuInfo( lockID: BlueManage().connectDeviceName, userID: await Storage.getUid(), - utcTimeStamp: 0, - unixTimeStamp: 0, + utcTimeStamp: state.serverTime, + unixTimeStamp: getLocalTime2(), isBeforeAddUser: false, privateKey: getPrivateKeyList, ); @@ -278,6 +280,18 @@ class ThirdPartyPlatformLogic extends BaseGetXController { }); } + int getLocalTime() { + final DateTime now = DateTime.now(); + final Duration timeZoneOffset = now.timeZoneOffset; + return state.differentialTime + timeZoneOffset.inSeconds; + } + + int getLocalTime2() { + final DateTime now = DateTime.now(); + final Duration timeZoneOffset = now.timeZoneOffset; + return state.serverTime + timeZoneOffset.inSeconds; + } + void _handleAuthorizationCodeReply(SenderAuthorizationCodeCommandReply reply) { final int status = reply.data[6]; switch (status) { @@ -285,7 +299,12 @@ class ThirdPartyPlatformLogic extends BaseGetXController { //成功 cancelBlueConnetctToastTimer(); dismissEasyLoading(); - showToast('操作成功,请在24小时内用涂鸦APP添加门锁,否则将过期'.tr); + if (state.selectPlatFormIndex.value == 1) { + showSuccess('操作成功,请尽快用"涂鸦”APP配置,如不使用请关闭该设置支持'.tr); + } else if (state.selectPlatFormIndex.value == 0) { + showSuccess('操作成功'.tr); + } + break; default: //失败 diff --git a/lib/main/lockDetail/lockSet/thirdPartyPlatform/third_party_platform_page.dart b/lib/main/lockDetail/lockSet/thirdPartyPlatform/third_party_platform_page.dart index b60076ea..4fd2b9e8 100644 --- a/lib/main/lockDetail/lockSet/thirdPartyPlatform/third_party_platform_page.dart +++ b/lib/main/lockDetail/lockSet/thirdPartyPlatform/third_party_platform_page.dart @@ -128,25 +128,27 @@ class _ThirdPartyPlatformPageState extends State { // 最后一个元素不显示分割线(取反) isHaveDirection: false, isHaveRightWidget: true, - rightWidget: Radio( - // Radio 的值:使用平台的唯一标识(如 id) - value: platform, - // 当前选中的值:与 selectPlatFormIndex 关联的 id - groupValue: state.platFormSet.value[state.selectPlatFormIndex.value], - // 选中颜色(可选,默认主题色) - activeColor: AppColors.mainColor, - // 点击 Radio 时回调(更新选中索引) - onChanged: (value) { - if (value != null) { - setState(() { - // 找到当前选中平台的索引(根据 id 匹配) - final newIndex = state.platFormSet.value.indexWhere((p) => p == value); - if (newIndex != -1) { - state.selectPlatFormIndex.value = newIndex; - } - }); - } - }, + rightWidget: Obx( + () => Radio( + // Radio 的值:使用平台的唯一标识(如 id) + value: platform, + // 当前选中的值:与 selectPlatFormIndex 关联的 id + groupValue: state.platFormSet.value[state.selectPlatFormIndex.value], + // 选中颜色(可选,默认主题色) + activeColor: AppColors.mainColor, + // 点击 Radio 时回调(更新选中索引) + onChanged: (value) { + if (value != null) { + setState(() { + // 找到当前选中平台的索引(根据 id 匹配) + final newIndex = state.platFormSet.value.indexWhere((p) => p == value); + if (newIndex != -1) { + state.selectPlatFormIndex.value = newIndex; + } + }); + } + }, + ), ), action: () { setState(() { diff --git a/lib/main/lockDetail/lockSet/thirdPartyPlatform/third_party_platform_state.dart b/lib/main/lockDetail/lockSet/thirdPartyPlatform/third_party_platform_state.dart index c688585a..9bff0027 100644 --- a/lib/main/lockDetail/lockSet/thirdPartyPlatform/third_party_platform_state.dart +++ b/lib/main/lockDetail/lockSet/thirdPartyPlatform/third_party_platform_state.dart @@ -13,7 +13,7 @@ class ThirdPartyPlatformState { } Rx lockSetInfoData = LockSetInfoData().obs; - int differentialTime = 0;// 服务器时间即UTC+0时间 + int differentialTime = 0; // 服务器时间即UTC+0时间 // 响应式字符串集合(自动触发 UI 更新) final RxList platFormSet = List.of({ @@ -25,8 +25,11 @@ class ThirdPartyPlatformState { // 响应式字符串集合(自动触发 UI 更新) final RxList tppSupportList = RxList([]); - RxInt selectPlatFormIndex = 1.obs; + RxInt selectPlatFormIndex = (-1).obs; + RxBool openNumber = false.obs; RxString registerKey = ''.obs; Map lockInfo = {}; + + int serverTime = 0; // 服务器时间即UTC+0时间 } diff --git a/lib/network/api.dart b/lib/network/api.dart index 31354efa..f7442bb2 100755 --- a/lib/network/api.dart +++ b/lib/network/api.dart @@ -305,6 +305,8 @@ abstract class Api { '/lockSetting/updateLockSetting'; // 设置语音包 final String reportBuyRequestURL = '/service/reportBuyRequest'; // 上报增值服务购买请求 - final String getActivateInfoURL = + final String getTppSupportURL = '/api/authCode/getTppSupport'; // 查询ttp + final String getActivateInfoURL = + '/api/authCode/getActivateInfo'; // 查询ttp }