diff --git a/lib/blue/blue_manage.dart b/lib/blue/blue_manage.dart index 520e4f02..b14dc064 100755 --- a/lib/blue/blue_manage.dart +++ b/lib/blue/blue_manage.dart @@ -813,6 +813,16 @@ 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) { diff --git a/lib/blue/io_protocol/io_readRegisterKey.dart b/lib/blue/io_protocol/io_readRegisterKey.dart new file mode 100644 index 00000000..964adc72 --- /dev/null +++ b/lib/blue/io_protocol/io_readRegisterKey.dart @@ -0,0 +1,74 @@ +import 'dart:convert'; + +import '../io_tool/io_tool.dart'; +import '../sm4Encipher/sm4.dart'; +import '../io_reply.dart'; +import '../io_sender.dart'; +import '../io_type.dart'; +import 'package:crypto/crypto.dart' as crypto; + +/// 读取注册密钥 +class SenderReadRegisterKeyCommand extends SenderProtocol { + SenderReadRegisterKeyCommand({ + this.lockID, + this.token, + this.needAuthor, + this.publicKey, + this.privateKey, + }) : super(CommandType.readRegisterKey); + + String? lockID; + + List? token; + int? needAuthor; + List? publicKey; + List? privateKey; + + @override + String toString() { + return 'SenderReadRegisterKeyCommand{ lockID: $lockID, token: $token, ' + 'needAuthor: $needAuthor, publicKey: $publicKey, ' + 'privateKey: $privateKey}'; + } + + @override + List messageDetail() { + List data = []; + List ebcData = []; + + // 指令类型 + final int type = commandType!.typeValue; + final double typeDouble = type / 256; + final int type1 = typeDouble.toInt(); + final int type2 = type % 256; + data.add(type1); + data.add(type2); + + // 锁id 40 + final int lockIDLength = utf8.encode(lockID!).length; + data.addAll(utf8.encode(lockID!)); + data = getFixedLengthList(data, 40 - lockIDLength); + + if ((data.length % 16) != 0) { + final int add = 16 - data.length % 16; + for (int i = 0; i < add; i++) { + data.add(0); + } + } + + printLog(data); + + ebcData = SM4.encrypt(data, key: privateKey, mode: SM4CryptoMode.ECB); + return ebcData; + } +} + +class SenderReadRegisterKeyCommandReply extends Reply { + SenderReadRegisterKeyCommandReply.parseData(CommandType commandType, List dataDetail) + : super.parseData(commandType, dataDetail) { + data = dataDetail; + + final int status = data[6]; + errorWithStstus(status); + } +} diff --git a/lib/blue/io_protocol/io_sendAuthorizationCode.dart b/lib/blue/io_protocol/io_sendAuthorizationCode.dart new file mode 100644 index 00000000..ed81ef46 --- /dev/null +++ b/lib/blue/io_protocol/io_sendAuthorizationCode.dart @@ -0,0 +1,106 @@ +import 'dart:convert'; + +import '../io_tool/io_tool.dart'; +import '../sm4Encipher/sm4.dart'; +import '../io_reply.dart'; +import '../io_sender.dart'; +import '../io_type.dart'; +import 'package:crypto/crypto.dart' as crypto; + +/// 发送授权码 +class SenderAuthorizationCodeCommand extends SenderProtocol { + SenderAuthorizationCodeCommand({ + this.lockID, + this.uuid, + this.key, + this.mac, + this.platform, + this.utcTimeStamp, + this.token, + this.needAuthor, + this.publicKey, + this.privateKey, + }) : super(CommandType.sendAuthorizationCode); + + String? lockID; + String? uuid; + String? key; + String? mac; + int? platform; //0:锁通通;1:涂鸦智能 + int? utcTimeStamp; + + List? token; + int? needAuthor; + List? publicKey; + List? privateKey; + + @override + String toString() { + return 'SenderAuthorizationCodeCommand{ lockID: $lockID, token: $token, ' + 'needAuthor: $needAuthor, publicKey: $publicKey, ' + 'privateKey: $privateKey}'; + } + + @override + List messageDetail() { + List data = []; + List ebcData = []; + + // 指令类型 + final int type = commandType!.typeValue; + final double typeDouble = type / 256; + final int type1 = typeDouble.toInt(); + final int type2 = type % 256; + data.add(type1); + data.add(type2); + + // 锁id 40 + final int lockIDLength = utf8.encode(lockID!).length; + data.addAll(utf8.encode(lockID!)); + data = getFixedLengthList(data, 40 - lockIDLength); + + // uuid 40 + final int uuidLength = utf8.encode(uuid!).length; + data.addAll(utf8.encode(uuid!)); + data = getFixedLengthList(data, 40 - uuidLength); + + // key 40 + final int keyLength = utf8.encode(key!).length; + data.addAll(utf8.encode(key!)); + data = getFixedLengthList(data, 40 - keyLength); + + // mac 40 + final int macLength = utf8.encode(mac!).length; + data.addAll(utf8.encode(mac!)); + data = getFixedLengthList(data, 40 - macLength); + + data.add(platform!); + + data.add((utcTimeStamp! & 0xff000000) >> 24); + data.add((utcTimeStamp! & 0xff0000) >> 16); + data.add((utcTimeStamp! & 0xff00) >> 8); + data.add(utcTimeStamp! & 0xff); + + if ((data.length % 16) != 0) { + final int add = 16 - data.length % 16; + for (int i = 0; i < add; i++) { + data.add(0); + } + } + + printLog(data); + + ebcData = SM4.encrypt(data, key: privateKey, mode: SM4CryptoMode.ECB); + return ebcData; + } +} + +class SenderAuthorizationCodeCommandReply extends Reply { + SenderAuthorizationCodeCommandReply.parseData(CommandType commandType, List dataDetail) + : super.parseData(commandType, dataDetail) { + data = dataDetail; + + final int status = data[6]; + errorWithStstus(status); + } +} diff --git a/lib/blue/io_type.dart b/lib/blue/io_type.dart index 33364400..4302c907 100755 --- a/lib/blue/io_type.dart +++ b/lib/blue/io_type.dart @@ -9,10 +9,10 @@ List getDeviceType(DeviceType deviceType) { List t = ['758824']; switch (deviceType) { case DeviceType.blue: - t = ['758824', '75', '768824', '76','24']; + t = ['758824', '75', '768824', '76', '24']; break; case DeviceType.gateway: - t = ['758825','25']; + t = ['758825', '25']; break; } return t; @@ -53,6 +53,8 @@ enum CommandType { gatewayGetWifiList, //网关获取附近的wifi列表 0x30F6 gatewayGetWifiListResult, //网关获取附近的wifi列表结果 0x30F7 gatewayGetStatus, //获取网关状态 0x30F8 + readRegisterKey, //读取注册密钥 0x30A7 + sendAuthorizationCode, //发送授权码 0x30A6 generalExtendedCommond, // 通用扩展指令 = 0x3030 gecChangeAdministratorPassword, // 通用扩展指令子命令-修改管理员密码 = 2 @@ -245,6 +247,16 @@ extension ExtensionCommandType on CommandType { type = CommandType.gatewayGetStatus; } break; + case 0x30A6: + { + type = CommandType.sendAuthorizationCode; + } + break; + case 0x30A7: + { + type = CommandType.readRegisterKey; + } + break; default: { type = CommandType.readStarLockStatusInfo; @@ -353,6 +365,12 @@ extension ExtensionCommandType on CommandType { case CommandType.setLockCurrentVoicePacket: type = 0x30A5; break; + case CommandType.sendAuthorizationCode: + type = 0x30A6; + break; + case CommandType.readRegisterKey: + type = 0x30A7; + break; default: type = 0x300A; break; @@ -492,6 +510,12 @@ extension ExtensionCommandType on CommandType { case 0x30A5: t = '设置锁当前语音包'; break; + case 0x30A6: + t = '发送授权码'; + break; + case 0x30A7: + t = '读取注册密钥'; + break; default: t = '读星锁状态信息'; break; diff --git a/lib/blue/reciver_data.dart b/lib/blue/reciver_data.dart index a74804ea..6be54c05 100755 --- a/lib/blue/reciver_data.dart +++ b/lib/blue/reciver_data.dart @@ -16,10 +16,12 @@ import 'package:star_lock/blue/io_protocol/io_getDeviceModel.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_readAdminPassword.dart'; +import 'package:star_lock/blue/io_protocol/io_readRegisterKey.dart'; import 'package:star_lock/blue/io_protocol/io_readSupportFunctionsNoParameters.dart'; import 'package:star_lock/blue/io_protocol/io_readSupportFunctionsWithParameters.dart'; import 'package:star_lock/blue/io_protocol/io_readVoicePackageFinalResult.dart'; import 'package:star_lock/blue/io_protocol/io_referEventRecordTime.dart'; +import 'package:star_lock/blue/io_protocol/io_sendAuthorizationCode.dart'; import 'package:star_lock/blue/io_protocol/io_setSupportFunctionsNoParameters.dart'; import 'package:star_lock/blue/io_protocol/io_setSupportFunctionsWithParameters.dart'; import 'package:star_lock/blue/io_protocol/io_setVoicePackageFinalResult.dart'; @@ -331,6 +333,18 @@ class CommandReciverManager { SetVoicePackageFinalResultReply.parseData(commandType, data); } break; + case CommandType.readRegisterKey: + { + reply = + SenderReadRegisterKeyCommandReply.parseData(commandType, data); + } + break; + case CommandType.sendAuthorizationCode: + { + reply = + SenderAuthorizationCodeCommandReply.parseData(commandType, data); + } + break; case CommandType.generalExtendedCommond: { // 子命令类型 diff --git a/lib/blue/sender_manage.dart b/lib/blue/sender_manage.dart index d9880c73..96701d2d 100755 --- a/lib/blue/sender_manage.dart +++ b/lib/blue/sender_manage.dart @@ -6,6 +6,8 @@ import 'package:star_lock/blue/io_protocol/io_deletUser.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_readAdminPassword.dart'; +import 'package:star_lock/blue/io_protocol/io_readRegisterKey.dart'; +import 'package:star_lock/blue/io_protocol/io_sendAuthorizationCode.dart'; import 'io_gateway/io_gateway_configuringWifi.dart'; import 'io_gateway/io_gateway_getStatus.dart'; @@ -1109,10 +1111,7 @@ class IoSenderManage { //ota 升级过程 static void senderProcessOtaUpgradeCommand( - {required int? index, - required int? size, - required List? data, - CommandSendCallBack? callBack}) { + {required int? index, required int? size, required List? data, CommandSendCallBack? callBack}) { CommandSenderManager().managerSendData( command: ProcessOtaUpgradeCommand( index: index, @@ -1321,8 +1320,7 @@ class IoSenderManage { } // 网关获取wifi列表 - static void gatewayGetWifiCommand( - {required String? userID, CommandSendCallBack? callBack}) { + static void gatewayGetWifiCommand({required String? userID, CommandSendCallBack? callBack}) { CommandSenderManager().managerSendData( command: GatewayGetWifiCommand( userID: userID, @@ -1339,21 +1337,51 @@ class IoSenderManage { CommandSendCallBack? callBack}) { CommandSenderManager().managerSendData( command: GatewayConfiguringWifiCommand( - ssid: ssid, - password: password, - gatewayConfigurationStr: gatewayConfigurationStr), + ssid: ssid, password: password, gatewayConfigurationStr: gatewayConfigurationStr), isBeforeAddUser: true, callBack: callBack); } // 获取网关状态 static void gatewayGetStatusCommand( - {required String? lockID, - required String? userID, - CommandSendCallBack? callBack}) { + {required String? lockID, required String? userID, CommandSendCallBack? callBack}) { CommandSenderManager().managerSendData( - command: GatewayGetStatusCommand(lockID: lockID, userID: userID), - isBeforeAddUser: true, - callBack: callBack); + command: GatewayGetStatusCommand(lockID: lockID, userID: userID), isBeforeAddUser: true, callBack: callBack); + } + + // 读取注册密钥 + static void readRegisterKey({ + required String? lockID, + CommandSendCallBack? callBack, + }) { + CommandSenderManager().managerSendData( + command: SenderReadRegisterKeyCommand(lockID: lockID), + isBeforeAddUser: true, + callBack: callBack, + ); + } + + // 发送授权码 + static void sendAuthorizationCode({ + required String? lockID, + required String? uuid, + required String? key, + required String? mac, + required int? platform, + required int? utcTimeStamp, + CommandSendCallBack? callBack, + }) { + CommandSenderManager().managerSendData( + command: SenderAuthorizationCodeCommand( + lockID: lockID, + uuid: uuid, + key: key, + mac: mac, + platform: platform, + utcTimeStamp: utcTimeStamp, + ), + isBeforeAddUser: true, + callBack: callBack, + ); } } 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 b0dba54f..5ec189b9 100644 --- a/lib/main/lockDetail/lockSet/thirdPartyPlatform/third_party_platform_logic.dart +++ b/lib/main/lockDetail/lockSet/thirdPartyPlatform/third_party_platform_logic.dart @@ -1,40 +1,298 @@ +import 'dart:async'; + +import 'package:flutter_blue_plus/flutter_blue_plus.dart'; import 'package:get/get.dart'; import 'package:star_lock/app_settings/app_settings.dart'; +import 'package:star_lock/blue/blue_manage.dart'; +import 'package:star_lock/blue/io_protocol/io_getStarLockStatusInfo.dart'; +import 'package:star_lock/blue/io_protocol/io_readRegisterKey.dart'; +import 'package:star_lock/blue/io_protocol/io_sendAuthorizationCode.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/lockTime/getServerDatetime_entity.dart'; import 'package:star_lock/main/lockDetail/lockSet/thirdPartyPlatform/third_party_platform_state.dart'; import 'package:star_lock/network/api_repository.dart'; import 'package:star_lock/network/start_company_api.dart'; import 'package:star_lock/tools/baseGetXController.dart'; +import 'package:star_lock/tools/storage.dart'; class ThirdPartyPlatformLogic extends BaseGetXController { ThirdPartyPlatformState state = ThirdPartyPlatformState(); - void savePlatFormSetting() { - // showEasyLoading(); - showToast('功能待开放'.tr); - // dismissEasyLoading(); - } - - /// 查询TPP支持 - void getActivateInfo() async { - final model = state.lockSetInfoData.value.lockBasicInfo?.model; - if (model != null && model != '') { - final response = await StartCompanyApi.to.getActivateInfo(model: model); - if (response.errorCode!.codeIsSuccessful) { - AppLog.log('${response.data}'); - } - } - } + // 监听设备返回的数据 + StreamSubscription? _replySubscription; @override void onReady() async { - // TODO: implement onReady super.onReady(); - getActivateInfo(); + await getActivateInfo(); + _initReplySubscription(); + getServerDatetime(); } @override void dispose() { dismissEasyLoading(); + // 安全地取消订阅 + _replySubscription?.cancel(); + _replySubscription = null; + + // 添加额外的日志来跟踪清理过程 + AppLog.log('ThirdPartyPlatformLogic disposed, subscription cancelled'); + super.dispose(); } + + @override + void onClose() { + super.onClose(); + // 安全地取消订阅 + _replySubscription?.cancel(); + _replySubscription = null; + } + + // 从服务器时间 + Future getServerDatetime() async { + final GetServerDatetimeEntity entity = await ApiRepository.to.getServerDatetimeData(isUnShowLoading: true); + if (entity.errorCode!.codeIsSuccessful) { + state.differentialTime = entity.data!.date! ~/ 1000 - DateTime.now().millisecondsSinceEpoch ~/ 1000; + } + } + + int getUTCNetTime() { + return DateTime.now().millisecondsSinceEpoch ~/ 1000 + state.differentialTime; + } + + void _initReplySubscription() { + // 更严格的检查,避免重复初始化 + if (_replySubscription != null) { + AppLog.log('订阅已存在,避免重复初始化'); + return; + } + _replySubscription = EventBusManager().eventBus!.on().listen((Reply reply) async { + AppLog.log('输出了listen:${_replySubscription.hashCode}'); + if (reply is SenderReadRegisterKeyCommandReply) { + _handleReadRegisterKeyReply(reply); + } + + if (reply is GetStarLockStatuInfoReply) { + _replyGetStarLockStatusInfo(reply); + } + if (reply is SenderAuthorizationCodeCommandReply) { + _handleAuthorizationCodeReply(reply); + } + }); + AppLog.log('创建新订阅:${_replySubscription.hashCode}'); + } + + // 获取星锁状态 + Future _replyGetStarLockStatusInfo(Reply reply) async { + final int status = reply.data[2]; + + switch (status) { + case 0x00: + //成功 + dismissEasyLoading(); + cancelBlueConnetctToastTimer(); + //成功 + // AppLog.log('获取锁状态成功'); + // 厂商名称 + int index = 3; + final List vendor = reply.data.sublist(index, index + 20); + final String vendorStr = utf8String(vendor); + state.lockInfo['vendor'] = vendorStr; + // state.lockInfo["vendor"] = "XL"; + index = index + 20; + // AppLog.log('厂商名称 vendorStr:$vendorStr'); + + // 锁设备类型 + final int product = reply.data[index]; + state.lockInfo['product'] = product; + index = index + 1; + // AppLog.log('锁设备类型 product:$product'); + + // 产品名称 + final List model = reply.data.sublist(index, index + 20); + final String modelStr = utf8String(model); + state.lockInfo['model'] = modelStr; + // state.lockInfo["model"] = "JL-BLE-01"; + index = index + 20; + // AppLog.log('产品名称 mmodelStr:$modelStr'); + + // 软件版本 + final List fwVersion = reply.data.sublist(index, index + 20); + final String fwVersionStr = utf8String(fwVersion); + state.lockInfo['fwVersion'] = fwVersionStr; + index = index + 20; + // AppLog.log('软件版本 fwVersionStr:$fwVersionStr'); + + // 硬件版本 + final List hwVersion = reply.data.sublist(index, index + 20); + final String hwVersionStr = utf8String(hwVersion); + state.lockInfo['hwVersion'] = hwVersionStr; + index = index + 20; + // AppLog.log('硬件版本 hwVersionStr:$hwVersionStr'); + + // 厂商序列号 + final List serialNum0 = reply.data.sublist(index, index + 16); + final String serialNum0Str = utf8String(serialNum0); + state.lockInfo['serialNum0'] = serialNum0Str; + // state.lockInfo["serialNum0"] = "${DateTime.now().millisecondsSinceEpoch ~/ 10}"; + index = index + 16; + // AppLog.log('厂商序列号 serialNum0Str:$serialNum0Str'); + final response = await StartCompanyApi.to.getAuthorizationCode( + registerKey: state.registerKey.value, + model: modelStr, + serialNum0: serialNum0Str, + platform: 1, + ); + if (response.errorCode!.codeIsSuccessful) { + BlueManage().blueSendData( + BlueManage().connectDeviceName, + (BluetoothConnectionState connectionState) async { + if (connectionState == BluetoothConnectionState.connected) { + IoSenderManage.sendAuthorizationCode( + lockID: BlueManage().connectDeviceName, + uuid: response.data?.extraParams?['uuid'], + key: response.data?.authCode, + mac: response.data?.extraParams?['mac'], + platform: 1, + utcTimeStamp: getUTCNetTime(), + ); + } else if (connectionState == BluetoothConnectionState.disconnected) { + dismissEasyLoading(); + cancelBlueConnetctToastTimer(); + } + }, + isAddEquipment: true, + ); + } + break; + case 0x06: + //无权限 + final List? privateKey = await Storage.getStringList(saveBluePrivateKey); + final List getPrivateKeyList = changeStringListToIntList(privateKey!); + IoSenderManage.senderGetStarLockStatuInfo( + lockID: BlueManage().connectDeviceName, + userID: await Storage.getUid(), + utcTimeStamp: 0, + unixTimeStamp: 0, + isBeforeAddUser: false, + privateKey: getPrivateKeyList, + ); + break; + default: + //失败 + break; + } + } + + 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(); + } + }, + ); + } else { + showToast('目前只支持切换至涂鸦智能协议'.tr); + } + } + + /// 查询TPP支持 + Future getActivateInfo() async { + final model = state.lockSetInfoData.value.lockBasicInfo?.model; + if (model != null && model != '') { + final response = await StartCompanyApi.to.getTppSupport(model: model); + if (response.errorCode!.codeIsSuccessful) { + response.data?.forEach((element) { + state.tppSupportList.add(element); + }); + state.tppSupportList.refresh(); + } + } + } + + void _handleReadRegisterKeyReply(SenderReadRegisterKeyCommandReply reply) { + final int status = reply.data[6]; + + switch (status) { + case 0x00: + // 提取 RegisterKey (从第7个字节开始,长度为40) + final List registerKeyBytes = reply.data.sublist(7, 47); + final String registerKey = String.fromCharCodes(registerKeyBytes); + + print('Register Key: $registerKey'); + state.registerKey.value = registerKey; + if (registerKey.isNotEmpty) { + _requestAuthorizationCode(); + } + //成功 + cancelBlueConnetctToastTimer(); + dismissEasyLoading(); + break; + default: + //失败 + dismissEasyLoading(); + cancelBlueConnetctToastTimer(); + break; + } + } + + void _requestAuthorizationCode() async { + showEasyLoading(); + showBlueConnetctToastTimer(action: () { + dismissEasyLoading(); + }); + BlueManage().blueSendData(BlueManage().connectDeviceName, (BluetoothConnectionState deviceConnectionState) async { + if (deviceConnectionState == BluetoothConnectionState.connected) { + final List? privateKey = await Storage.getStringList(saveBluePrivateKey); + final List getPrivateKeyList = changeStringListToIntList(privateKey!); + IoSenderManage.senderGetStarLockStatuInfo( + lockID: BlueManage().connectDeviceName, + userID: await Storage.getUid(), + utcTimeStamp: 0, + unixTimeStamp: 0, + isBeforeAddUser: false, + privateKey: getPrivateKeyList, + ); + } else if (deviceConnectionState == BluetoothConnectionState.disconnected) { + //失败 + dismissEasyLoading(); + cancelBlueConnetctToastTimer(); + } + }); + } + + void _handleAuthorizationCodeReply(SenderAuthorizationCodeCommandReply reply) { + final int status = reply.data[6]; + switch (status) { + case 0x00: + //成功 + cancelBlueConnetctToastTimer(); + dismissEasyLoading(); + showToast('操作成功,请在24小时内用涂鸦APP添加门锁,否则将过期'.tr); + break; + default: + //失败 + dismissEasyLoading(); + cancelBlueConnetctToastTimer(); + + break; + } + } } 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 67ee6d9b..b60076ea 100644 --- a/lib/main/lockDetail/lockSet/thirdPartyPlatform/third_party_platform_page.dart +++ b/lib/main/lockDetail/lockSet/thirdPartyPlatform/third_party_platform_page.dart @@ -45,107 +45,123 @@ class _ThirdPartyPlatformPageState extends State { } Widget _buildBody() { - return Stack( - children: [ - // 1. 背景或空白区域(可选) - Container( + return SingleChildScrollView( + child: Container( + decoration: BoxDecoration( color: Colors.white, - padding: EdgeInsets.all(16.w), ), - // 2. 顶部图标行:使用 Row 并排显示 - Positioned( - top: 80.h, - left: 0, - right: 0, - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, // 均匀分布 - children: [ - Image.asset( - 'images/other/tuya.png', - height: 50.h, - fit: BoxFit.cover, - ), - Image.asset( - 'images/other/2.png', // 中间图标 - height: 80.h, - - fit: BoxFit.cover, - ), - Image.asset( - 'images/other/matter.png', - width: 110.w, - fit: BoxFit.cover, - ), - ], - ), + constraints: BoxConstraints( + minHeight: MediaQuery.of(context).size.height - 100.h, ), - Positioned( - top: 220.h, - left: 20.w, - right: 20.w, - child: Text( - '第三方协议的支持依赖网络授权下载,打开功能开关时请保证手机数据网络的正常连接'.tr, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 20.sp, - color: Colors.grey, - fontWeight: FontWeight.w500, + child: Stack( + children: [ + // 1. 背景或空白区域(可选) + Container( + color: Colors.white, + padding: EdgeInsets.all(16.w), ), - ), - ), - - Positioned( - left: 0, - right: 0, - top: 320.h, - bottom: 0, - child: ListView.builder( - itemCount: state.platFormSet.length, - itemBuilder: (BuildContext context, int index) { - // 判断是否是最后一个元素(索引等于 itemCount - 1) - final isLastItem = index == state.platFormSet.length - 1; - - // 获取当前平台数据(假设 platFormSet 是 RxList) - final platform = state.platFormSet.value[index]; - return CommonItem( - leftTitel: state.platFormSet.value[index], - rightTitle: '', - isHaveLine: !isLastItem, - // 最后一个元素不显示分割线(取反) - 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; - } - }); - } - }, + Positioned( + top: 30.h, + left: 50.w, + child: Image.asset( + 'images/other/tuya.png', + height: 80.h, + fit: BoxFit.cover, + ), + ), + Positioned( + top: 130.h, + left: 150.w, + right: 150.w, + child: Image.asset( + 'images/other/2.png', + height: 220.h, + fit: BoxFit.contain, + ), + ), + // 2. 顶部图标行:使用 Row 并排显示 + Positioned( + top: 400.h, + right: 50.w, + child: Column( + children: [ + Image.asset( + 'images/other/matter.png', + width: 280.w, + fit: BoxFit.contain, + ), + ], + ), + ), + Positioned( + top: 530.h, + left: 20.w, + right: 20.w, + child: Text( + '第三方协议的支持依赖网络授权下载,打开功能开关时请保证手机数据网络的正常连接'.tr, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 20.sp, + color: Colors.grey, + fontWeight: FontWeight.w500, ), - action: () { - setState(() { - state.selectPlatFormIndex.value = index; - }); + ), + ), + + Positioned( + left: 0, + right: 0, + top: 620.h, + bottom: 0, + child: ListView.builder( + itemCount: state.platFormSet.length, + itemBuilder: (BuildContext context, int index) { + // 判断是否是最后一个元素(索引等于 itemCount - 1) + final isLastItem = index == state.platFormSet.length - 1; + + // 获取当前平台数据(假设 platFormSet 是 RxList) + final platform = state.platFormSet.value[index]; + return CommonItem( + leftTitel: state.platFormSet.value[index], + rightTitle: '', + isHaveLine: !isLastItem, + // 最后一个元素不显示分割线(取反) + 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; + } + }); + } + }, + ), + action: () { + setState(() { + state.selectPlatFormIndex.value = index; + }); + }, + ); }, - ); - }, - shrinkWrap: true, - physics: const AlwaysScrollableScrollPhysics(), - ), + shrinkWrap: true, + physics: const AlwaysScrollableScrollPhysics(), + ), + ), + ], ), - ], + ), ); } } 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 184bf445..c688585a 100644 --- a/lib/main/lockDetail/lockSet/thirdPartyPlatform/third_party_platform_state.dart +++ b/lib/main/lockDetail/lockSet/thirdPartyPlatform/third_party_platform_state.dart @@ -1,6 +1,8 @@ import 'dart:ui'; import 'package:get/get.dart'; +import 'package:get/get_rx/get_rx.dart'; +import 'package:star_lock/main/lockDetail/lockDetail/ActivateInfoResponse.dart'; import 'package:star_lock/main/lockDetail/lockSet/lockSet/lockSetInfo_entity.dart'; import 'package:star_lock/translations/app_dept.dart'; @@ -11,15 +13,20 @@ class ThirdPartyPlatformState { } Rx lockSetInfoData = LockSetInfoData().obs; + int differentialTime = 0;// 服务器时间即UTC+0时间 // 响应式字符串集合(自动触发 UI 更新) final RxList platFormSet = List.of({ '锁通通'.tr, '涂鸦智能'.tr, - 'Matter'.tr , + 'Matter'.tr, }).obs; - RxInt selectPlatFormIndex = 0.obs; + // 响应式字符串集合(自动触发 UI 更新) + final RxList tppSupportList = RxList([]); + RxInt selectPlatFormIndex = 1.obs; + RxString registerKey = ''.obs; + Map lockInfo = {}; } diff --git a/lib/network/start_company_api.dart b/lib/network/start_company_api.dart index e5f4c1f2..acca6eaf 100644 --- a/lib/network/start_company_api.dart +++ b/lib/network/start_company_api.dart @@ -10,28 +10,48 @@ import 'package:star_lock/talk/starChart/entity/star_chart_register_node_entity. import 'package:star_lock/tools/storage.dart'; class StartCompanyApi extends BaseProvider { - // 星图url + // 星启url String _startChartHost = 'https://company.skychip.top'; static StartCompanyApi get to => Get.put(StartCompanyApi()); - // 设置星图host + // 设置星启host set startChartHost(String value) { _startChartHost = value; } - // 获取星图host + // 获取星启host String get startChartHost => _startChartHost; // ttp查询 - Future getActivateInfo({ + Future getTppSupport({ required String model, + }) async { + final response = await post( + _startChartHost + getTppSupportURL.toUrl, + jsonEncode({ + 'model': model, + }), + isUnShowLoading: true, + isUserBaseUrl: false, + ); + return TppSupportResponse.fromJson(response.body); + } + + // 获取授权码 + Future getAuthorizationCode({ + required String registerKey, + required String model, + required String serialNum0, + required int platform, }) async { final response = await post( _startChartHost + getActivateInfoURL.toUrl, jsonEncode({ + 'register_key': registerKey, + 'platform': platform, 'model': model, - + 'serial_num0': serialNum0, }), isUnShowLoading: true, isUserBaseUrl: false, diff --git a/pubspec.yaml b/pubspec.yaml index 608005ad..bf10df09 100755 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -322,6 +322,7 @@ flutter: assets: - images/ - images/tabbar/ + - images/other/ - images/guide/ - images/main/ - images/main/addFingerprint/