import 'dart:async'; import 'dart:convert'; import 'dart:io'; import 'dart:typed_data'; import 'package:flutter_blue_plus/flutter_blue_plus.dart'; import 'package:flutter_easyloading/flutter_easyloading.dart'; import 'package:get/get.dart'; import 'package:network_info_plus/network_info_plus.dart'; import 'package:permission_handler/permission_handler.dart'; import 'package:star_lock/appRouters.dart'; import 'package:star_lock/app_settings/app_settings.dart'; import 'package:star_lock/blue/io_gateway/io_gateway_configuringWifi.dart'; import 'package:star_lock/blue/io_gateway/io_gateway_getStatus.dart'; import 'package:star_lock/blue/io_protocol/io_updataLockSet.dart'; import 'package:star_lock/login/login/entity/LoginEntity.dart'; import 'package:star_lock/main/lockDetail/lockDetail/device_network_info.dart'; import 'package:star_lock/main/lockDetail/lockSet/configuringWifi/configuringWifi/configuringWifiEntity.dart'; import 'package:star_lock/mine/gateway/addGateway/gatewayConfigurationWifi/gatewayConfigurationWifi_page.dart'; import 'package:star_lock/mine/gateway/addGateway/gatewayConfigurationWifi/getGatewayConfiguration_entity.dart'; import 'package:star_lock/mine/gateway/addGateway/selectGateway/getGatewayInfo_model.dart'; import 'package:star_lock/talk/starChart/entity/star_chart_register_node_entity.dart'; import 'package:star_lock/talk/starChart/star_chart_manage.dart'; import 'package:star_lock/tools/baseGetXController.dart'; import 'package:star_lock/tools/commonDataManage.dart'; import '../../../../../blue/blue_manage.dart'; import '../../../../../blue/io_protocol/io_configuringWifi.dart'; import '../../../../../blue/io_reply.dart'; import '../../../../../blue/io_tool/io_tool.dart'; import '../../../../../blue/io_tool/manager_event_bus.dart'; import '../../../../../blue/sender_manage.dart'; import '../../../../../network/api_repository.dart'; import '../../../../../tools/eventBusEventManage.dart'; import '../../../../../tools/storage.dart'; import 'configuringWifi_state.dart'; class ConfiguringWifiLogic extends BaseGetXController { final ConfiguringWifiState state = ConfiguringWifiState(); final int _configurationTimeout = 60; // 配网超时时间(秒) /// 获取WiFi锁服务IP和端口 Future getWifiLockServiceIpAndPort() async { try { final ConfiguringWifiEntity entity = await ApiRepository.to.getWifiLockServiceIpAndPort(); if (entity.errorCode! == 0) { state.configuringWifiEntity.value = entity; } else { AppLog.log('获取WiFi锁服务IP和端口失败:${entity.errorCode}'); } } catch (e) { AppLog.log('获取WiFi锁服务IP和端口异常:$e'); } } /// 更新网络信息到服务器 void updateNetworkInfo({ required String peerId, required String wifiName, required String secretKey, required String deviceMac, required String networkMac, }) async { try { final LoginEntity entity = await ApiRepository.to.settingDeviceNetwork( deviceType: 2, deviceMac: deviceMac, wifiName: wifiName, networkMac: networkMac, secretKey: secretKey, peerId: peerId, ); if (entity.errorCode!.codeIsSuccessful) { // 设置锁的peerID StartChartManage().lockNetworkInfo = DeviceNetworkInfo( wifiName: wifiName, networkMac: networkMac, secretKey: secretKey, peerId: peerId, ); await _getUploadLockSet(); } else { dismissEasyLoading(); showToast('网络配置失败,请重试'.tr); state.sureBtnState.value = 0; } } catch (e) { dismissEasyLoading(); showToast('网络配置异常:${e.toString()}'.tr); state.sureBtnState.value = 0; AppLog.log('网络配置异常:$e'); } } // 监听设备返回的数据 late StreamSubscription _replySubscription; void _initReplySubscription() { _replySubscription = EventBusManager().eventBus!.on().listen((Reply reply) async { // WIFI配网结果 if (reply is GatewayConfiguringWifiResultReply) { _replySenderConfiguringWifiResult(reply); } // wifi配网命令应答结果 if (reply is GatewayConfiguringWifiReply) { _replySenderConfiguringWifi(reply); } if (reply is GatewayGetStatusReply) { _replyGatewayGetStatusReply(reply); } // 上传数据获取锁设置 if (reply is UpdataLockSetReply) { _replyUpdataLockSetReply(reply); } }); } // WIFI配网操作结果处理 Future _replySenderConfiguringWifi(Reply reply) async { final int status = reply.data[2]; switch (status) { case 0x00: AppLog.log('wifi配网命令回复结果:成功'); break; default: //失败 dismissEasyLoading(); // 关闭loading showToast('配网失败'.tr); state.isLoading.value = false; break; } } // WIFI配网结果处理 Future _replySenderConfiguringWifiResult(Reply reply) async { final int status = reply.data[2]; // 收到响应后,取消蓝牙超时计时器 cancelBlueConnetctToastTimer(); switch (status) { case 0x00: // 配网成功 - 不关闭loading,保持状态直到全部完成 await Storage.removeLockNetWorkInfoCache(); try { final int secretKeyJsonLength = (reply.data[4] << 8) + reply.data[3]; final List secretKeyList = reply.data.sublist(5, 5 + secretKeyJsonLength); String result = utf8String(secretKeyList); AppLog.log('解析配网信息: $result'); // 解析 JSON 字符串为 Map Map jsonMap = json.decode(result); // 提取网络信息 String? peerId = jsonMap['peerId']; String? wifiName = jsonMap['wifiName']; String? secretKey = jsonMap['secretKey']; String? deviceMac = jsonMap['deviceMac']; String? networkMac = jsonMap['networkMac']; // 验证关键字段 if (peerId == null || peerId.isEmpty || secretKey == null || secretKey.isEmpty) { throw Exception('Missing required network information'); } /// 配网成功后,赋值锁的peerId StartChartManage().lockPeerId = peerId; // 保存到缓存 await Storage.saveLockNetWorkInfo(jsonMap); // 上报服务器 - 注意: sureBtnState 状态将在 updateNetworkInfo 方法中或其回调中完成重置 updateNetworkInfo( peerId: peerId, wifiName: wifiName ?? '', secretKey: secretKey, deviceMac: deviceMac ?? '', networkMac: networkMac ?? ''); } catch (e) { if (EasyLoading.isShow) { dismissEasyLoading(); } showToast('解析配网信息失败,请重试'.tr); state.sureBtnState.value = 0; // 确保重置状态 AppLog.log('解析配网信息失败: $e'); return; // 添加return阻止后续流程 } break; case 0x01: // WiFi密码错误 if (EasyLoading.isShow) { dismissEasyLoading(); } showToast('WiFi密码错误,请重新输入'.tr); state.sureBtnState.value = 0; // 确保重置状态 break; case 0x02: // 找不到WiFi if (EasyLoading.isShow) { dismissEasyLoading(); } showToast('找不到该WiFi网络,请确认WiFi名称正确'.tr); state.sureBtnState.value = 0; // 确保重置状态 break; case 0x03: // 网络连接超时 if (EasyLoading.isShow) { dismissEasyLoading(); } showToast('连接WiFi超时,请确保网络信号良好'.tr); state.sureBtnState.value = 0; // 确保重置状态 break; default: // 其他错误 if (EasyLoading.isShow) { dismissEasyLoading(); } showToast('配网失败 (错误码: $status),请重试'.tr); state.sureBtnState.value = 0; // 确保重置状态 break; } } // 辅助函数:美化 JSON 输出 String prettyPrintJson(String jsonString) { var jsonObject = json.decode(jsonString); return JsonEncoder.withIndent(' ').convert(jsonObject); } // 点击配置wifi Future senderConfiguringWifiAction() async { AppLog.log('开始配网${EasyLoading.isShow}'); if (state.sureBtnState.value == 1) { AppLog.log('正在配网中请勿重复点击'); return; } // 获取网关配置信息 try { final GetGatewayConfigurationEntity entity = await ApiRepository.to .getGatewayConfigurationNotLoading(timeout: _configurationTimeout); if (entity.errorCode!.codeIsSuccessful) { state.getGatewayConfigurationStr = entity.data ?? ''; } else { // showToast('获取网关配置失败,请重试'.tr); AppLog.log('获取网关配置失败,请重试'); return; } // 判断是否登录账户 final loginData = await Storage.getLoginData(); if (loginData == null) { AppLog.log('未检测到登录信息,请重新登录'.tr); return; } // 获取app用户的peerId String appPeerId = loginData.starchart?.starchartId ?? ''; if (appPeerId.isEmpty) { AppLog.log('用户ID获取失败,请重新登录'.tr); return; } // 处理配置字符串 if (state.getGatewayConfigurationStr.isNotEmpty) { // 解析 JSON 字符串为 Map Map jsonMap = json.decode(state.getGatewayConfigurationStr); // 移除指定的键 jsonMap.remove("starCloudUrl"); jsonMap.remove("starLockPeerId"); // 追加新的键值对 jsonMap['userPeerld'] = appPeerId; // 将 Map 转换回 JSON 字符串 state.getGatewayConfigurationStr = json.encode(jsonMap).replaceAll(',', ',\n'); // 确保格式化输出 state.getGatewayConfigurationStr = prettyPrintJson(state.getGatewayConfigurationStr); } else { // 如果为空,则直接赋值 state.getGatewayConfigurationStr = "{\"userPeerld\": \"$appPeerId\"}"; } } catch (e) { AppLog.log('网关配置准备失败:${e.toString()}'.tr); return; } // 先设置sureBtnState状态,以禁用按钮 state.sureBtnState.value = 1; // 显示loading,如果已经显示则不再重复显示 if (!EasyLoading.isShow) { showEasyLoading(); } // 设置蓝牙操作超时处理 showBlueConnetctToastTimer(action: () { if (EasyLoading.isShow) { dismissEasyLoading(); } state.sureBtnState.value = 0; // 连接超时时重置状态 }); // 发送配网指令 BlueManage().blueSendData( BlueManage().connectDeviceName, (BluetoothConnectionState connectionState) async { if (connectionState == BluetoothConnectionState.connected) { try { IoSenderManage.gatewayConfiguringWifiCommand( ssid: state.wifiNameController.text, password: state.wifiPWDController.text, gatewayConfigurationStr: state.getGatewayConfigurationStr, ); // 注意:此处不要重置sureBtnState状态,等待配网结果回调 } catch (e) { if (EasyLoading.isShow) { dismissEasyLoading(); } cancelBlueConnetctToastTimer(); state.sureBtnState.value = 0; // 发送命令失败时重置状态 showToast('发送配网指令失败:${e.toString()}'.tr); } } else if (connectionState == BluetoothConnectionState.disconnected) { if (EasyLoading.isShow) { dismissEasyLoading(); } cancelBlueConnetctToastTimer(); state.sureBtnState.value = 0; // 蓝牙断开时重置状态 if (state.ifCurrentScreen.value == true) { showBlueConnetctToast(); } } }, isAddEquipment: false, ); } // 获取设备状态 Future getDevicesStatusAction() async { showEasyLoading(); showBlueConnetctToastTimer(action: () { dismissEasyLoading(); }); BlueManage().blueSendData(BlueManage().connectDeviceName, (BluetoothConnectionState connectionState) async { if (connectionState == BluetoothConnectionState.connected) { IoSenderManage.gatewayGetStatusCommand( lockID: BlueManage().connectDeviceName, userID: await Storage.getUid(), ); } else if (connectionState == BluetoothConnectionState.disconnected) { dismissEasyLoading(); cancelBlueConnetctToastTimer(); if (state.ifCurrentScreen.value == true) { showBlueConnetctToast(); } } }, isAddEquipment: true); } final NetworkInfo _networkInfo = NetworkInfo(); Future getWifiName() async { try { String? ssid = await _networkInfo.getWifiName(); ssid = ssid ?? ''; ssid = ssid.replaceAll(r'"', ''); return ssid; } catch (e) { AppLog.log('获取WiFi名称失败: $e'); return ''; } } ///定位权限 Future checkLocationPermission() async { final PermissionStatus value = await locationPermission(); final bool allow = value != PermissionStatus.permanentlyDenied && value != PermissionStatus.denied; return allow; } Future locationPermission() async => Permission.location.request(); @override void onReady() { super.onReady(); if (state.wifiName.value.isEmpty) { getWifiName().then((String value) { state.wifiNameController.text = value; }); } getWifiLockServiceIpAndPort(); _initReplySubscription(); } @override void onClose() { _replySubscription.cancel(); cancelBlueConnetctToastTimer(); // 确保取消蓝牙超时计时器 super.onClose(); } void _replyGatewayGetStatusReply(GatewayGetStatusReply reply) { final int status = reply.data[2]; //成功 dismissEasyLoading(); cancelBlueConnetctToastTimer(); switch (status) { case 0x00: //成功 final GetGatewayInfoModel gatewayModel = GetGatewayInfoModel(); // 网关MAC地址 int index = 3; final List macList = reply.data.sublist(index, index + 20); final String macStr = utf8String(macList); // lockInfo['mac'] = macStr; gatewayModel.mac = macStr; index = index + 20; AppLog.log('MAC地址 macList:$macList macStr:$macStr'); // 网关序列号 final List serialNum = reply.data.sublist(index, index + 20); final String serialNumStr = utf8String(serialNum); // lockInfo['serialNum'] = serialNumStr; gatewayModel.serialNum = serialNumStr; index = index + 20; AppLog.log('序列号 serialNum:$serialNum serialNumStr:$serialNumStr'); // 网关版本 final List gatewayVersion = reply.data.sublist(index, index + 20); final String gatewayVersionStr = utf8String(gatewayVersion); // lockInfo['gatewayVersion'] = gatewayVersionStr; gatewayModel.gatewayVersion = gatewayVersionStr; index = index + 20; // AppLog.log( // '软件版本 gatewayVersion:$gatewayVersion gatewayVersionStr:$gatewayVersionStr'); // wifiMac地址 final List wifiMac = reply.data.sublist(index, index + 20); final String wifiMacStr = utf8String(wifiMac); // lockInfo['wifiMac'] = wifiMacStr; gatewayModel.wifiMac = wifiMacStr; index = index + 20; AppLog.log('wifiMac地址 wifiMac:$wifiMac wifiMacStr:$wifiMacStr'); // gatewayModel.wifiMac = '00:00:00:00:00:00'; break; default: //失败 dismissEasyLoading(); showToast('获取设备状态失败'.tr); break; } } // 上传数据获取设置 Future _getUploadLockSet() async { // 保持已有的loading状态,不再重新显示loading showBlueConnetctToastTimer(action: () { if (EasyLoading.isShow) { dismissEasyLoading(); } state.sureBtnState.value = 0; }); try { final List? token = await Storage.getStringList(saveBlueToken); if (token == null || token.isEmpty) { throw Exception('Token is empty'); } final List getTokenList = changeStringListToIntList(token); await _uploadLockSet(getTokenList); } catch (e) { if (EasyLoading.isShow) { dismissEasyLoading(); } cancelBlueConnetctToastTimer(); showToast('获取设置失败:${e.toString()}'.tr); state.sureBtnState.value = 0; } } // 公共的上传锁设置 Future _uploadLockSet(List token) async { try { final List? privateKey = await Storage.getStringList(saveBluePrivateKey); if (privateKey == null || privateKey.isEmpty) { throw Exception('Private key is empty'); } final List getPrivateKeyList = changeStringListToIntList(privateKey); final List? signKey = await Storage.getStringList(saveBlueSignKey); if (signKey == null || signKey.isEmpty) { throw Exception('Sign key is empty'); } final List signKeyDataList = changeStringListToIntList(signKey); IoSenderManage.updataLockSetCommand( lockID: BlueManage().connectDeviceName, userID: await Storage.getUid(), token: token, needAuthor: 1, signKey: signKeyDataList, privateKey: getPrivateKeyList); } catch (e) { if (EasyLoading.isShow) { dismissEasyLoading(); } cancelBlueConnetctToastTimer(); showToast('上传设置失败:${e.toString()}'.tr); state.sureBtnState.value = 0; } } // 上传数据获取锁设置解析 Future _replyUpdataLockSetReply(Reply reply) async { final int status = reply.data[2]; // 保持loading状态直到整个过程完成 cancelBlueConnetctToastTimer(); switch (status) { case 0x00: await _lockDataUpload( uploadType: 1, recordType: 0, records: reply.data.sublist(7, reply.data.length)); break; case 0x06: //无权限,尝试重新获取token try { final List token = reply.data.sublist(3, 7); final List saveStrList = changeIntListToStringList(token); await Storage.setStringList(saveBlueToken, saveStrList); _uploadLockSet(token); } catch (e) { if (EasyLoading.isShow) { dismissEasyLoading(); // 错误时关闭loading } showToast('获取设置权限失败:${e.toString()}'.tr); state.sureBtnState.value = 0; // 确保重置状态 } break; default: if (EasyLoading.isShow) { dismissEasyLoading(); // 错误时关闭loading } showToast('获取锁设置失败 (错误码: $status)'.tr); state.sureBtnState.value = 0; // 确保重置状态 break; } } // 锁数据上传服务器 Future _lockDataUpload( {required int uploadType, required int recordType, required List records}) async { try { final LoginEntity entity = await ApiRepository.to.lockDataUpload( lockId: state.lockBasicInfo.value.lockId ?? -1, uploadType: uploadType, recordType: recordType, records: records, isUnShowLoading: true); if (entity.errorCode!.codeIsSuccessful) { if (EasyLoading.isShow) { dismissEasyLoading(); } showToast('配网成功'.tr, something: () { state.sureBtnState.value = 0; // 确保重置状态 if (state.pageName.value == 'lockSet') { Get.close(2); } else { Get.offAllNamed(Routers.starLockMain); } eventBus.fire( PassCurrentLockInformationEvent(state.lockSetInfoData.value)); eventBus.fire(SuccessfulDistributionNetwork()); }); } else { if (EasyLoading.isShow) { dismissEasyLoading(); } showToast('数据上传失败:${entity.errorCode}'.tr); state.sureBtnState.value = 0; // 确保重置状态 } } catch (e) { if (EasyLoading.isShow) { dismissEasyLoading(); } showToast('数据上传异常:${e.toString()}'.tr); state.sureBtnState.value = 0; // 确保重置状态 } } }