From 323c99b27eefbfc4acc63067fa39581c72788323 Mon Sep 17 00:00:00 2001 From: liyi Date: Thu, 9 Jan 2025 14:10:10 +0800 Subject: [PATCH] =?UTF-8?q?fix:=E5=AE=8C=E5=96=84=E5=AF=B9=E8=AE=B2?= =?UTF-8?q?=E6=B5=81=E7=A8=8B=E3=80=81=E5=A2=9E=E5=8A=A0=E7=9B=91=E6=8E=A7?= =?UTF-8?q?=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../io_gateway_configuringWifi.dart | 20 +- .../lockDetail/device_network_info.dart | 64 +++++ .../lockDetail/lockDetail_page.dart | 32 ++- .../configuringWifi_logic.dart | 242 ++++++++---------- .../configuringWifi_state.dart | 2 +- .../wifiList/wifiList_logic.dart | 72 ++---- .../wifiList/wifiList_page.dart | 65 ++--- .../videoLog/videoLog/videoLog_logic.dart | 26 ++ .../videoLog/videoLog/videoLog_page.dart | 35 ++- .../videoLog/videoLog/videoLog_state.dart | 3 + lib/network/api.dart | 5 +- lib/network/api_provider.dart | 32 +++ lib/network/api_repository.dart | 27 ++ lib/talk/startChart/constant/talk_status.dart | 3 +- .../impl/udp_ble_passthrough_handler.dart | 7 +- .../handle/impl/udp_talk_data_handler.dart | 2 +- .../handle/impl/udp_talk_expect_handler.dart | 13 + .../handle/impl/udp_talk_hangup_handler.dart | 14 +- .../handle/impl/udp_talk_reject_handler.dart | 12 +- .../handle/impl/udp_talk_request_handler.dart | 31 ++- .../talke_data_over_time_timer_manager.dart | 8 +- ...talke_request_over_time_timer_manager.dart | 3 +- lib/talk/startChart/start_chart_manage.dart | 52 +++- .../status/start_chart_talk_status.dart | 3 +- .../views/talkView/talk_view_logic.dart | 2 +- .../views/talkView/talk_view_page.dart | 17 +- lib/tools/storage.dart | 18 ++ pubspec.yaml | 2 + 28 files changed, 528 insertions(+), 284 deletions(-) create mode 100644 lib/main/lockDetail/lockDetail/device_network_info.dart diff --git a/lib/blue/io_gateway/io_gateway_configuringWifi.dart b/lib/blue/io_gateway/io_gateway_configuringWifi.dart index 7d6a5ede..c66236a0 100644 --- a/lib/blue/io_gateway/io_gateway_configuringWifi.dart +++ b/lib/blue/io_gateway/io_gateway_configuringWifi.dart @@ -1,5 +1,6 @@ // 网关配网 import 'dart:convert'; +import 'dart:typed_data'; import 'package:star_lock/app_settings/app_settings.dart'; @@ -49,12 +50,19 @@ class GatewayConfiguringWifiCommand extends SenderProtocol { //gatewayConfigurationStr final int clientIdLength = utf8.encode(gatewayConfigurationStr!).length; - final double clientIdLengthDouble = clientIdLength / 256; - final int clientIdLengthDoubleType1 = clientIdLengthDouble.toInt(); - final int clientIdLengthDoubleType2 = clientIdLength % 256; - // AppLog.log('gatewayConfigurationStr!:$gatewayConfigurationStr! clientIdLength:$clientIdLength clientIdLengthDouble:$clientIdLengthDouble clientIdLengthDoubleType1:$clientIdLengthDoubleType1 clientIdLengthDoubleType2:$clientIdLengthDoubleType2'); - data.add(clientIdLengthDoubleType1); - data.add(clientIdLengthDoubleType2); + Uint8List lengthBytes = Uint8List(2); + ByteData byteData = ByteData.view(lengthBytes.buffer); + byteData.setUint16(0, clientIdLength, Endian.little); // 使用大端序(big-endian) + + // 将两个字节添加到 subData + subData.addAll(lengthBytes); + // subData.add(clientIdLength); + // final double clientIdLengthDouble = clientIdLength / 256; + // final int clientIdLengthDoubleType1 = clientIdLengthDouble.toInt(); + // final int clientIdLengthDoubleType2 = clientIdLength % 256; + // // AppLog.log('gatewayConfigurationStr!:$gatewayConfigurationStr! clientIdLength:$clientIdLength clientIdLengthDouble:$clientIdLengthDouble clientIdLengthDoubleType1:$clientIdLengthDoubleType1 clientIdLengthDoubleType2:$clientIdLengthDoubleType2'); + // data.add(clientIdLengthDoubleType1); + // data.add(clientIdLengthDoubleType2); subData.addAll(utf8.encode(gatewayConfigurationStr!)); // subData = getFixedLengthList(subData, 20 - clientIdLength); diff --git a/lib/main/lockDetail/lockDetail/device_network_info.dart b/lib/main/lockDetail/lockDetail/device_network_info.dart new file mode 100644 index 00000000..e797962c --- /dev/null +++ b/lib/main/lockDetail/lockDetail/device_network_info.dart @@ -0,0 +1,64 @@ + + +class DeviceNetwork { + DeviceNetwork({ + this.description, + this.errorCode, + this.data, + this.errorMsg,}); + + DeviceNetwork.fromJson(dynamic json) { + description = json['description']; + errorCode = json['errorCode']; + data = json['data'] != null ? DeviceNetworkInfo.fromJson(json['data']) : null; + errorMsg = json['errorMsg']; + } + String? description; + int? errorCode; + DeviceNetworkInfo? data; + String? errorMsg; + + Map toJson() { + final map = {}; + map['description'] = description; + map['errorCode'] = errorCode; + if (data != null) { + map['data'] = data!.toJson(); + } + map['errorMsg'] = errorMsg; + return map; + } + +} + + + +class DeviceNetworkInfo { + DeviceNetworkInfo({ + this.wifiName, + this.networkMac, + this.secretKey, + this.peerId, + }); + + DeviceNetworkInfo.fromJson(dynamic json) { + wifiName = json['wifiName']; + networkMac = json['networkMac']; + secretKey = json['secretKey']; + peerId = json['peerId']; + } + + String? wifiName; + String? networkMac; + String? secretKey; + String? peerId; + + Map toJson() { + final map = {}; + map['wifiName'] = wifiName; + map['networkMac'] = networkMac; + map['secretKey'] = secretKey; + map['peerId'] = peerId; + return map; + } +} diff --git a/lib/main/lockDetail/lockDetail/lockDetail_page.dart b/lib/main/lockDetail/lockDetail/lockDetail_page.dart index 6009bfeb..45ef4e18 100755 --- a/lib/main/lockDetail/lockDetail/lockDetail_page.dart +++ b/lib/main/lockDetail/lockDetail/lockDetail_page.dart @@ -7,12 +7,19 @@ import 'package:get/get.dart'; import 'package:intl/intl.dart' as intl; import 'package:star_lock/app_settings/app_colors.dart'; import 'package:star_lock/flavors.dart'; +import 'package:star_lock/main/lockDetail/lockDetail/device_network_info.dart'; import 'package:star_lock/main/lockDetail/lockDetail/lockDetail_state.dart'; +import 'package:star_lock/main/lockDetail/lockSet/lockSet/lockSetInfo_entity.dart'; import 'package:star_lock/main/lockMian/lockMain/lockMain_logic.dart'; +import 'package:star_lock/mine/gateway/addGateway/gatewayConfigurationWifi/getGatewayConfiguration_entity.dart'; +import 'package:star_lock/network/api_repository.dart'; +import 'package:star_lock/talk/startChart/start_chart_manage.dart'; import 'package:star_lock/tools/aliyunRealNameAuth/aliyunRealNameAuthHandle.dart'; +import 'package:star_lock/tools/baseGetXController.dart'; import 'package:star_lock/tools/bugly/bugly_tool.dart'; import 'package:star_lock/tools/showCupertinoAlertView.dart'; import 'package:star_lock/tools/showTipView.dart'; +import 'package:star_lock/tools/storage.dart'; import 'package:star_lock/widget/flavors_img.dart'; import '../../../appRouters.dart'; @@ -1154,11 +1161,26 @@ class _LockDetailPageState extends State if (state.keyInfos.value.lockFeature!.videoIntercom == 1) { showWidgetArr.add( bottomItem('images/main/icon_catEyes.png', '监控'.tr, - state.bottomBtnisEable.value, () { - Get.toNamed(Routers.realTimePicturePage, arguments: { - 'lockName': state.keyInfos.value.lockName, - 'isMonitoring': true - }); + state.bottomBtnisEable.value, () async { + final lockId = state.keyInfos.value.lockId; + final LockSetInfoEntity entity = + await ApiRepository.to.getLockSettingInfoData( + lockId: lockId.toString(), + ); + if (entity.errorCode!.codeIsSuccessful) { + final LockSetInfoData data = entity.data!; + final mac = data.lockBasicInfo?.mac; + if (mac != null && mac.isNotEmpty) { + final DeviceNetwork deviceNetworkInfo = await ApiRepository.to + .getDeviceNetwork(deviceType: 2, deviceMac: mac); + final peerId = deviceNetworkInfo?.data?.peerId; + if (peerId == null || peerId.isEmpty) { + throw Exception('设备peerId为空'); + } + StartChartManage() + .startCallRequestMessageTimer(ToPeerId: peerId ?? ''); + } + } }), ); } diff --git a/lib/main/lockDetail/lockSet/configuringWifi/configuringWifi/configuringWifi_logic.dart b/lib/main/lockDetail/lockSet/configuringWifi/configuringWifi/configuringWifi_logic.dart index 7635bbe4..d2fdf866 100755 --- a/lib/main/lockDetail/lockSet/configuringWifi/configuringWifi/configuringWifi_logic.dart +++ b/lib/main/lockDetail/lockSet/configuringWifi/configuringWifi/configuringWifi_logic.dart @@ -1,13 +1,19 @@ import 'dart:async'; +import 'dart:convert'; import 'dart:io'; +import 'dart:typed_data'; import 'package:flutter_blue_plus/flutter_blue_plus.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/app_settings/app_settings.dart'; +import 'package:star_lock/blue/io_gateway/io_gateway_configuringWifi.dart'; import 'package:star_lock/login/login/entity/LoginEntity.dart'; import 'package:star_lock/main/lockDetail/lockSet/configuringWifi/configuringWifi/configuringWifiEntity.dart'; +import 'package:star_lock/mine/gateway/addGateway/gatewayConfigurationWifi/getGatewayConfiguration_entity.dart'; import 'package:star_lock/talk/startChart/entity/star_chart_register_node_entity.dart'; +import 'package:star_lock/talk/startChart/start_chart_manage.dart'; import 'package:star_lock/tools/baseGetXController.dart'; import '../../../../../blue/blue_manage.dart'; @@ -32,10 +38,20 @@ class ConfiguringWifiLogic extends BaseGetXController { } } - Future updateNetworkInfo() async { - final LoginEntity entity = await ApiRepository.to.updateNetworkInfo( - lockId: state.lockSetInfoData.value.lockId!, - network: state.wifiNameController.text, + Future updateNetworkInfo({ + required String peerId, + required String wifiName, + required String secretKey, + required String deviceMac, + required String networkMac, + }) async { + final LoginEntity entity = await ApiRepository.to.settingDeviceNetwork( + deviceType: 2, + deviceMac: deviceMac, + wifiName: wifiName, + networkMac: networkMac, + secretKey: secretKey, + peerId: peerId, ); if (entity.errorCode!.codeIsSuccessful) { showToast('配网成功'.tr, something: () { @@ -53,92 +69,64 @@ class ConfiguringWifiLogic extends BaseGetXController { _replySubscription = EventBusManager().eventBus!.on().listen((Reply reply) async { // WIFI配网结果 - if (reply is SenderConfiguringWifiReply) { - _replySenderConfiguringWifi(reply); + if (reply is GatewayConfiguringWifiResultReply) { + _replySenderConfiguringWifiResult(reply); } }); } // WIFI配网结果 - Future _replySenderConfiguringWifi(Reply reply) async { - final int status = reply.data[5]; - + Future _replySenderConfiguringWifiResult(Reply reply) async { + final int status = reply.data[2]; + state.sureBtnState.value = 0; switch (status) { case 0x00: //成功 - state.sureBtnState.value = 0; cancelBlueConnetctToastTimer(); dismissEasyLoading(); - updateNetworkInfo(); - break; - case 0x06: - //无权限 - final List? privateKey = - await Storage.getStringList(saveBluePrivateKey); - final List getPrivateKeyList = - changeStringListToIntList(privateKey!); + final int secretKeyJsonLength = (reply.data[4] << 8) + reply.data[3]; - final List? publicKey = - await Storage.getStringList(saveBluePublicKey); - final List publicKeyDataList = - changeStringListToIntList(publicKey!); + final List secretKeyList = + reply.data.sublist(5, 5 + secretKeyJsonLength); + String result = utf8String(secretKeyList); + // 解析 JSON 字符串为 Map + Map jsonMap = json.decode(result); - final List tokenData = reply.data.sublist(7, 10); - final List saveStrList = changeIntListToStringList(tokenData); - Storage.setStringList(saveBlueToken, saveStrList); + // 提取 peerId + String? peerId = jsonMap['peerId']; + String? wifiName = jsonMap['wifiName']; + String? secretKey = jsonMap['secretKey']; + String? deviceMac = jsonMap['deviceMac']; + String? networkMac = jsonMap['networkMac']; - final List serversList = []; - for (int i = 0; - i < state.configuringWifiEntity.value.data!.serviceList!.length; - i++) { - final ServiceList item = - state.configuringWifiEntity.value.data!.serviceList![i]; - final List itemList = item.serviceIp!.split('.'); - for (String element in itemList) { - serversList.add(int.parse(element)); - } + /// 配网成功后,赋值锁的peerId + StartChartManage().lockPeerId = peerId ?? ''; - final double typeDouble = int.parse(item.port!) / 256; - final int type1 = typeDouble.toInt(); - final int type2 = int.parse(item.port!) % 256; - serversList.add(type1); - serversList.add(type2); - } - - // 判断是否登录账户 - final loginData = await Storage.getLoginData(); - - // 获取app用户的peerId - String appPeerId = loginData?.starchart?.starchartId ?? ''; - - final List uidList = [Storage.getUid().toString()]; - IoSenderManage.senderConfiguringWifiCommand( - keyID: state.lockSetInfoData.value.lockBasicInfo!.keyId.toString(), - userID: await Storage.getUid(), - ssid: state.wifiNameController.text, - password: state.wifiPWDController.text, - numberOfServers: state.configuringWifiEntity.value.data!.serviceNum, - listOfServers: serversList, - numberOfPhone: uidList.length, - listOfPhone: uidList, - token: tokenData, - needAuthor: 1, - publicKey: publicKeyDataList, - privateKey: getPrivateKeyList, - peerId: appPeerId, - ); - - break; - case 0xff: - //成功 - showToast('配网失败'.tr); + // 保存到缓存 + await Storage.saveLockNetWorkInfo(jsonMap); + // 上报服务器 + updateNetworkInfo( + peerId: peerId ?? '', + wifiName: wifiName ?? '', + secretKey: secretKey ?? '', + deviceMac: deviceMac ?? '', + networkMac: networkMac ?? ''); break; default: //失败 + dismissEasyLoading(); + cancelBlueConnetctToastTimer(); + showToast('配网失败'.tr); break; } } +// 辅助函数:美化 JSON 输出 + String prettyPrintJson(String jsonString) { + var jsonObject = json.decode(jsonString); + return JsonEncoder.withIndent(' ').convert(jsonObject); + } + // 点击配置wifi Future senderConfiguringWifiAction() async { if (state.wifiNameController.text.isEmpty) { @@ -146,6 +134,10 @@ class ConfiguringWifiLogic extends BaseGetXController { return; } + if (state.wifiPWDController.text.isEmpty) { + showToast('请输入WiFi密码'.tr); + return; + } if (state.sureBtnState.value == 1) { return; } @@ -156,71 +148,61 @@ class ConfiguringWifiLogic extends BaseGetXController { dismissEasyLoading(); state.sureBtnState.value = 0; }); + + final GetGatewayConfigurationEntity entity = + await ApiRepository.to.getGatewayConfiguration(timeout: 60); + if (entity.errorCode!.codeIsSuccessful) { + state.getGatewayConfigurationStr = entity.data ?? ''; + } + + // 判断是否登录账户 + final loginData = await Storage.getLoginData(); + + // 获取app用户的peerId + String appPeerId = loginData?.starchart?.starchartId ?? ''; + // 如果已有值,则追加 + 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\"}"; + } + // 追加新的 JSON 字符串 + // if (state.getGatewayConfigurationStr.isNotEmpty) { + // // 如果已有值,则追加 + // state.getGatewayConfigurationStr = + // state.getGatewayConfigurationStr.replaceAll( + // RegExp(r'}\s*$'), + // ',\n{\"userPeerld\": \"$appPeerId\"}', + // ); + // } else { + // // 如果为空,则直接赋值 + // state.getGatewayConfigurationStr = "{\"userPeerld\": \"$appPeerId\"}"; + // } BlueManage().blueSendData(BlueManage().connectDeviceName, (BluetoothConnectionState connectionState) async { if (connectionState == BluetoothConnectionState.connected) { - final List? privateKey = - await Storage.getStringList(saveBluePrivateKey); - final List getPrivateKeyList = - changeStringListToIntList(privateKey!); - - final List? publicKey = - await Storage.getStringList(saveBluePublicKey); - final List publicKeyDataList = - changeStringListToIntList(publicKey!); - - final List? token = await Storage.getStringList(saveBlueToken); - final List getTokenList = changeStringListToIntList(token!); - - final List serversList = []; - for (int i = 0; - i < state.configuringWifiEntity.value.data!.serviceList!.length; - i++) { - final ServiceList item = - state.configuringWifiEntity.value.data!.serviceList![i]; - if (item.serviceIp!.contains('192')) { - final List itemList = item.serviceIp!.split('.'); - for (String element in itemList) { - serversList.add(int.parse(element)); - } - } else { - final List addresses = - await InternetAddress.lookup(item.serviceIp!); - final List itemList = addresses.first.address.split('.'); - for (String element in itemList) { - serversList.add(int.parse(element)); - } - } - - final double typeDouble = int.parse(item.port!) / 256; - final int type1 = typeDouble.toInt(); - final int type2 = int.parse(item.port!) % 256; - serversList.add(type1); - serversList.add(type2); - } - - final String? uidStr = await Storage.getUid(); - final List uidList = [uidStr.toString()]; - - // 判断是否登录账户 - final loginData = await Storage.getLoginData(); - - // 获取app用户的peerId - String appPeerId = loginData?.starchart?.starchartId ?? ''; - IoSenderManage.senderConfiguringWifiCommand( - keyID: state.lockSetInfoData.value.lockBasicInfo!.keyId.toString(), - userID: await Storage.getUid(), + IoSenderManage.gatewayConfiguringWifiCommand( ssid: state.wifiNameController.text, password: state.wifiPWDController.text, - peerId: appPeerId, - numberOfServers: state.configuringWifiEntity.value.data!.serviceNum, - listOfServers: serversList, - numberOfPhone: uidList.length, - listOfPhone: uidList, - token: getTokenList, - needAuthor: 1, - publicKey: publicKeyDataList, - privateKey: getPrivateKeyList, + gatewayConfigurationStr: state.getGatewayConfigurationStr, ); } else if (connectionState == BluetoothConnectionState.disconnected) { dismissEasyLoading(); @@ -230,7 +212,7 @@ class ConfiguringWifiLogic extends BaseGetXController { showBlueConnetctToast(); } } - }); + }, isAddEquipment: true); } final NetworkInfo _networkInfo = NetworkInfo(); diff --git a/lib/main/lockDetail/lockSet/configuringWifi/configuringWifi/configuringWifi_state.dart b/lib/main/lockDetail/lockSet/configuringWifi/configuringWifi/configuringWifi_state.dart index 04a748a4..1fc13548 100755 --- a/lib/main/lockDetail/lockSet/configuringWifi/configuringWifi/configuringWifi_state.dart +++ b/lib/main/lockDetail/lockSet/configuringWifi/configuringWifi/configuringWifi_state.dart @@ -25,5 +25,5 @@ class ConfiguringWifiState{ TextEditingController wifiNameController = TextEditingController(); TextEditingController wifiPWDController = TextEditingController(); - + String getGatewayConfigurationStr = ''; } \ No newline at end of file diff --git a/lib/main/lockDetail/lockSet/configuringWifi/wifiList/wifiList_logic.dart b/lib/main/lockDetail/lockSet/configuringWifi/wifiList/wifiList_logic.dart index d9c00155..2804b678 100755 --- a/lib/main/lockDetail/lockSet/configuringWifi/wifiList/wifiList_logic.dart +++ b/lib/main/lockDetail/lockSet/configuringWifi/wifiList/wifiList_logic.dart @@ -1,9 +1,10 @@ - import 'dart:async'; import 'package:flutter_blue_plus/flutter_blue_plus.dart'; import 'package:get/get.dart'; +import 'package:star_lock/blue/io_gateway/io_gateway_getWifiList.dart'; import 'package:star_lock/blue/io_protocol/io_getWifiList.dart'; +import 'package:star_lock/talk/startChart/start_chart_manage.dart'; import 'package:star_lock/tools/baseGetXController.dart'; import '../../../../../blue/blue_manage.dart'; @@ -19,13 +20,15 @@ class WifiListLogic extends BaseGetXController { // 获取解析后的数据 late StreamSubscription _replySubscription; + void _initReplySubscription() { - _replySubscription = EventBusManager().eventBus!.on().listen((Reply reply) { - if(reply is SenderGetWifiReply) { + _replySubscription = + EventBusManager().eventBus!.on().listen((Reply reply) { + if (reply is GatewayGetWifiReply) { _replySendGetWifiParameters(reply); } - if(reply is SenderGetWifiListReply) { + if (reply is GatewayGetWifiListReply) { _replyGetWifiListParameters(reply); } }); @@ -34,7 +37,7 @@ class WifiListLogic extends BaseGetXController { // 发送获取wifi列表数据解析 Future _replySendGetWifiParameters(Reply reply) async { final int status = reply.data[2]; - switch(status){ + switch (status) { case 0x00: //成功 showEasyLoading(); @@ -43,42 +46,24 @@ class WifiListLogic extends BaseGetXController { break; case 0x06: // 需要鉴权 - - // var token = await Storage.getStringList(saveBlueToken); - // List getTokenList = changeStringListToIntList(token!); - // - // var privateKey = await Storage.getStringList(saveBluePrivateKey); - // List getPrivateKeyList = changeStringListToIntList(privateKey!); - // - // var publicKey = await Storage.getStringList(saveBluePublicKey); - // List publicKeyDataList = changeStringListToIntList(publicKey!); - // - // IoSenderManage.getWifiListCommand( - // keyID: state.lockSetInfoData.value.lockBasicInfo!.keyId.toString(), - // userID: await Storage.getUid(), - // token: getTokenList, - // needAuthor: 1, - // publicKey: publicKeyDataList, - // privateKey: getPrivateKeyList, - // ); break; default: break; } } - // 设置自动落锁数据解析 + // 获取WiFi数据解析 Future _replyGetWifiListParameters(Reply reply) async { final int status = reply.data[2]; - switch(status){ + switch (status) { case 0x00: //成功 // showEasyLoading(); dismissEasyLoading(); state.sureBtnState.value = 0; - if (reply.data[6] > 0) { - reply.data.removeRange(0, 7); + if (reply.data[3] > 0) { + reply.data.removeRange(0, 4); // 把得到的数据按33位分割成数组 然后塞进一个新的数组里面 final List> getList = splitList(reply.data, 33); final List> uploadList = >[]; @@ -92,7 +77,6 @@ class WifiListLogic extends BaseGetXController { state.wifiNameDataList.value = uploadList; } } - break; default: break; @@ -101,44 +85,31 @@ class WifiListLogic extends BaseGetXController { // 获取wifi列表 Future senderGetWifiListWifiAction() async { - if(state.sureBtnState.value == 1){ + if (state.sureBtnState.value == 1) { return; } state.sureBtnState.value = 1; showEasyLoading(); - showBlueConnetctToastTimer(action: (){ + showBlueConnetctToastTimer(action: () { dismissEasyLoading(); state.sureBtnState.value = 0; }); - BlueManage().blueSendData(BlueManage().connectDeviceName, (BluetoothConnectionState connectionState) async { - if (connectionState == BluetoothConnectionState.connected){ - final List? token = await Storage.getStringList(saveBlueToken); - final List getTokenList = changeStringListToIntList(token!); - - final List? privateKey = await Storage.getStringList(saveBluePrivateKey); - final List getPrivateKeyList = changeStringListToIntList(privateKey!); - - final List? publicKey = await Storage.getStringList(saveBluePublicKey); - final List publicKeyDataList = changeStringListToIntList(publicKey!); - - IoSenderManage.getWifiListCommand( - keyID: state.lockSetInfoData.value.lockBasicInfo!.keyId.toString(), + BlueManage().blueSendData(BlueManage().connectDeviceName, + (BluetoothConnectionState connectionState) async { + if (connectionState == BluetoothConnectionState.connected) { + IoSenderManage.gatewayGetWifiCommand( userID: await Storage.getUid(), - token: getTokenList, - needAuthor: 1, - publicKey: publicKeyDataList, - privateKey: getPrivateKeyList, ); } else if (connectionState == BluetoothConnectionState.disconnected) { dismissEasyLoading(); state.sureBtnState.value = 0; cancelBlueConnetctToastTimer(); - if(state.ifCurrentScreen.value == true){ + if (state.ifCurrentScreen.value == true) { showBlueConnetctToast(); } } - }); + }, isAddEquipment: true); } @override @@ -160,5 +131,4 @@ class WifiListLogic extends BaseGetXController { super.onClose(); _replySubscription.cancel(); } - -} \ No newline at end of file +} diff --git a/lib/main/lockDetail/lockSet/configuringWifi/wifiList/wifiList_page.dart b/lib/main/lockDetail/lockSet/configuringWifi/wifiList/wifiList_page.dart index f750d0d5..937c2e8a 100755 --- a/lib/main/lockDetail/lockSet/configuringWifi/wifiList/wifiList_page.dart +++ b/lib/main/lockDetail/lockSet/configuringWifi/wifiList/wifiList_page.dart @@ -1,4 +1,3 @@ - import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:get/get.dart'; @@ -28,31 +27,39 @@ class _WifiListPageState extends State { return Scaffold( backgroundColor: Colors.white, appBar: TitleAppBar( - barTitle: 'WIFI列表'.tr, - haveBack: true, - actionsList: [ - TextButton( - child: Text( - '刷新'.tr, style: TextStyle(color: Colors.white, fontSize: 24.sp), - ), - onPressed: logic.senderGetWifiListWifiAction, - ), - ], - backgroundColor: AppColors.mainColor), + barTitle: 'WIFI列表'.tr, + haveBack: true, + actionsList: [ + TextButton( + child: Text( + '刷新'.tr, + style: TextStyle(color: Colors.white, fontSize: 24.sp), + ), + onPressed: logic.senderGetWifiListWifiAction, + ), + ], + backgroundColor: AppColors.mainColor), body: Column( children: [ Expanded( - child: Obx(() => state.wifiNameDataList.value.isNotEmpty ? ListView.builder( - itemCount: state.wifiNameDataList.value.length, - itemBuilder: (BuildContext c, int index) { - Map wifiNameStr = state.wifiNameDataList.value[index]; - return _messageListItem(wifiNameStr['wifiName'], wifiNameStr['rssi'], () { - Get.toNamed(Routers.configuringWifiPage, arguments: { - 'lockSetInfoData': state.lockSetInfoData.value, - 'wifiName': wifiNameStr['wifiName'], - }); - }); - }) : NoData(noDataHeight: 1.sh - ScreenUtil().statusBarHeight - ScreenUtil().bottomBarHeight - 64.h)), + child: Obx(() => state.wifiNameDataList.value.isNotEmpty + ? ListView.builder( + itemCount: state.wifiNameDataList.value.length, + itemBuilder: (BuildContext c, int index) { + Map wifiNameStr = state.wifiNameDataList.value[index]; + return _messageListItem( + wifiNameStr['wifiName'], wifiNameStr['rssi'], () { + Get.toNamed(Routers.configuringWifiPage, arguments: { + 'lockSetInfoData': state.lockSetInfoData.value, + 'wifiName': wifiNameStr['wifiName'], + }); + }); + }) + : NoData( + noDataHeight: 1.sh - + ScreenUtil().statusBarHeight - + ScreenUtil().bottomBarHeight - + 64.h)), ), SubmitBtn( btnName: '手动配网'.tr, @@ -60,16 +67,16 @@ class _WifiListPageState extends State { borderRadius: 20.w, padding: EdgeInsets.only(top: 25.w, bottom: 25.w), onClick: () { - Get.toNamed(Routers.configuringWifiPage, arguments: { - 'lockSetInfoData': state.lockSetInfoData.value - }); + Get.toNamed(Routers.configuringWifiPage, + arguments: { + 'lockSetInfoData': state.lockSetInfoData.value + }); }), SizedBox( height: 64.h, ) ], - ) - ); + )); } Widget _messageListItem(String wifiName, String rssi, Function() action) { @@ -91,7 +98,7 @@ class _WifiListPageState extends State { children: [ SizedBox( height: 79.h, - width: 1.sw - 20.w*2, + width: 1.sw - 20.w * 2, child: Row( // mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ diff --git a/lib/main/lockDetail/videoLog/videoLog/videoLog_logic.dart b/lib/main/lockDetail/videoLog/videoLog/videoLog_logic.dart index 0d717537..2409d16e 100755 --- a/lib/main/lockDetail/videoLog/videoLog/videoLog_logic.dart +++ b/lib/main/lockDetail/videoLog/videoLog/videoLog_logic.dart @@ -1,5 +1,8 @@ +import 'dart:typed_data'; + import 'package:star_lock/network/api_repository.dart'; import 'package:star_lock/tools/baseGetXController.dart'; +import 'package:video_thumbnail/video_thumbnail.dart'; import 'videoLog_state.dart'; class VideoLogLogic extends BaseGetXController { @@ -11,10 +14,33 @@ class VideoLogLogic extends BaseGetXController { ); if (entity.errorCode!.codeIsSuccessful) { state.videoLogList.value = entity.data!; + state.videoLogList.refresh(); + // state.videoLogList.forEach((element) { + // final recordList = element.recordList; + // if (recordList != null && recordList.isNotEmpty) { + // recordList.forEach((item) { + // if (item.videoUrl != null && item.videoUrl!.isNotEmpty) { + // final coverImage = aw handleVideoCoverImage(item.videoUrl); + // state.videoCoverList.add(coverImage); + // } + // }); + // } + // }); } } + Future handleVideoCoverImage(videoUrl) async { + final uint8list = await VideoThumbnail.thumbnailData( + video: videoUrl, + imageFormat: ImageFormat.JPEG, + maxWidth: 128, + // specify the width of the thumbnail, let the height auto-scaled to keep the source aspect ratio + quality: 25, + ); + return uint8list; + } + @override onReady() { super.onReady(); diff --git a/lib/main/lockDetail/videoLog/videoLog/videoLog_page.dart b/lib/main/lockDetail/videoLog/videoLog/videoLog_page.dart index 5a23d226..4a587e82 100755 --- a/lib/main/lockDetail/videoLog/videoLog/videoLog_page.dart +++ b/lib/main/lockDetail/videoLog/videoLog/videoLog_page.dart @@ -1,4 +1,3 @@ - import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:get/get.dart'; @@ -11,7 +10,7 @@ import 'package:star_lock/tools/noData.dart'; import '../../../../app_settings/app_colors.dart'; import '../../../../tools/titleAppBar.dart'; -import 'videoLog_logic.dart'; +import 'videoLog_logic.dart';import 'package:video_thumbnail/video_thumbnail.dart'; class VideoLogPage extends StatefulWidget { const VideoLogPage({Key? key}) : super(key: key); @@ -293,11 +292,7 @@ class _VideoLogPageState extends State { color: Colors.white, child: ClipRRect( borderRadius: BorderRadius.circular(10.w), - child: Image( - fit: BoxFit.cover, - image: Image.network(recordData.imagesUrl ?? - 'images/icon_video_placeholder.jpg') - .image), + child: _buildImageOrVideoItem(recordData), ), ), SizedBox(height: 5.h), @@ -310,4 +305,30 @@ class _VideoLogPageState extends State { ), ); } + + _buildImageOrVideoItem(RecordListData recordData) { + if (recordData.videoUrl != null && recordData.videoUrl!.isNotEmpty) { + return _buildVideoItem(recordData); + } else { + return _buildImageItem(recordData); + } + } + + _buildVideoItem(RecordListData recordData) async { + final uint8list = await VideoThumbnail.thumbnailData( + video: recordData.videoUrl!, + imageFormat: ImageFormat.JPEG, + maxWidth: 128, + // specify the width of the thumbnail, let the height auto-scaled to keep the source aspect ratio + quality: 25, + ); + return Image.memory(uint8list!); + } + + _buildImageItem(RecordListData recordData) { + return Image.network( + recordData.imagesUrl!, + fit: BoxFit.cover, + ); + } } diff --git a/lib/main/lockDetail/videoLog/videoLog/videoLog_state.dart b/lib/main/lockDetail/videoLog/videoLog/videoLog_state.dart index ac9f2358..b703686b 100755 --- a/lib/main/lockDetail/videoLog/videoLog/videoLog_state.dart +++ b/lib/main/lockDetail/videoLog/videoLog/videoLog_state.dart @@ -1,3 +1,5 @@ +import 'dart:typed_data'; + import 'package:get/get.dart'; import 'package:star_lock/main/lockDetail/videoLog/videoLog/videoLog_entity.dart'; @@ -6,6 +8,7 @@ class VideoLogState { var localList = []; var getLockId = 0.obs; var videoLogList = [].obs; + var videoCoverList = [].obs; VideoLogState() { Map map = Get.arguments; diff --git a/lib/network/api.dart b/lib/network/api.dart index 016aff20..c51b05f6 100755 --- a/lib/network/api.dart +++ b/lib/network/api.dart @@ -67,7 +67,10 @@ abstract class Api { final String getWifiServiceIpURL = '/wifiLock/getWifiServiceIp'; // 获取Wifi锁服务器 final String updateLockSettingUrl = '/v2/lockSetting/updateLockSetting'; // 锁设置里面所有的设置 - + final String deviceNetworkConfiguration = + '/deviceNetwork/setting'; // 设备网络配置 + final String getDeviceNetworkConfiguration = + '/deviceNetwork/getNetworkInfo'; // 设备网络配置 final String roomQueryDateUrl = '/room/queryDate'; // 获取网关时间 final String lockDiagnoseUrl = '/room/uploadLockInfo'; // 锁诊断 final String getServerDatetimeUrl = '/check/getServerDatetime'; // 获取服务器当前时间 diff --git a/lib/network/api_provider.dart b/lib/network/api_provider.dart index 5051d461..6366aeee 100755 --- a/lib/network/api_provider.dart +++ b/lib/network/api_provider.dart @@ -2714,6 +2714,38 @@ class ApiProvider extends BaseProvider { }), isUnShowLoading: true, isShowNetworkErrorMsg: false); + + /// 更新网络信息 配网之后把网络信息提交到服务器保存 + Future settingDeviceNetwork( + int deviceType, + String deviceMac, + String wifiName, + String networkMac, + String secretKey, + String peerId, + ) => + post( + deviceNetworkConfiguration.toUrl, + jsonEncode({ + 'deviceType': deviceType, + 'deviceMac': deviceMac, + 'wifiName': wifiName, + 'networkMac': networkMac, + 'secretKey': secretKey, + 'peerId': peerId, + })); + + /// 获取设备配网信息 + Future getDeviceNetwork( + int deviceType, + String deviceMac, + ) => + post( + getDeviceNetworkConfiguration.toUrl, + jsonEncode({ + 'deviceType': deviceType, + 'deviceMac': deviceMac, + })); } extension ExtensionString on String { diff --git a/lib/network/api_repository.dart b/lib/network/api_repository.dart index e83fcb59..39c8e9e7 100755 --- a/lib/network/api_repository.dart +++ b/lib/network/api_repository.dart @@ -12,6 +12,7 @@ import 'package:star_lock/main/lockDetail/electronicKey/massSendElectronicKey/ma import 'package:star_lock/main/lockDetail/electronicKey/sendEmailNotification/sendEmailNotification_entity.dart'; import 'package:star_lock/main/lockDetail/face/addFace/addFace_entity.dart'; import 'package:star_lock/main/lockDetail/fingerprint/fingerprintList/fingerprint_entity.dart'; +import 'package:star_lock/main/lockDetail/lockDetail/device_network_info.dart'; import 'package:star_lock/main/lockDetail/lockSet/basicInformation/basicInformation/KeyDetailEntity.dart'; import 'package:star_lock/main/lockDetail/lockSet/lockEscalation/updateLockInfo_entity.dart'; import 'package:star_lock/main/lockDetail/lockSet/lockEscalation/version_entity.dart'; @@ -2712,4 +2713,30 @@ class ApiRepository { return LoginEntity.fromJson(res.body); } + + // 设置设备配网信息 + Future settingDeviceNetwork({ + required int deviceType, + required String deviceMac, + required String wifiName, + required String networkMac, + required String secretKey, + required String peerId, + }) async { + final res = await apiProvider.settingDeviceNetwork( + deviceType, deviceMac, wifiName, networkMac, secretKey, peerId); + return LoginEntity.fromJson(res.body); + } + + // 获取设备配网信息 + Future getDeviceNetwork({ + required int deviceType, + required String deviceMac, + }) async { + final res = await apiProvider.getDeviceNetwork( + deviceType, + deviceMac, + ); + return DeviceNetwork.fromJson(res.body); + } } diff --git a/lib/talk/startChart/constant/talk_status.dart b/lib/talk/startChart/constant/talk_status.dart index 3f7300b2..c75b03a3 100644 --- a/lib/talk/startChart/constant/talk_status.dart +++ b/lib/talk/startChart/constant/talk_status.dart @@ -1,6 +1,7 @@ enum TalkStatus { none, // 无状态 - waitingAnswer, // 等待接听 + proactivelyCallWaitingAnswer, // 主动呼叫等待接听 + passiveCallWaitingAnswer, // 被动呼叫等待接听 answeredSuccessfully, // 接听成功 waitingData, // 等待数据 hangingUpDuring, // 通话中挂断 diff --git a/lib/talk/startChart/handle/impl/udp_ble_passthrough_handler.dart b/lib/talk/startChart/handle/impl/udp_ble_passthrough_handler.dart index 6e14815b..cf62e15f 100644 --- a/lib/talk/startChart/handle/impl/udp_ble_passthrough_handler.dart +++ b/lib/talk/startChart/handle/impl/udp_ble_passthrough_handler.dart @@ -5,6 +5,7 @@ import 'package:flutter_easyloading/flutter_easyloading.dart'; import 'package:get/get.dart'; import 'package:star_lock/appRouters.dart'; import 'package:star_lock/app_settings/app_settings.dart'; +import 'package:star_lock/blue/reciver_data.dart'; import 'package:star_lock/talk/startChart/constant/message_type_constant.dart'; import 'package:star_lock/talk/startChart/entity/scp_message.dart'; import 'package:star_lock/talk/startChart/handle/scp_message_base_handle.dart'; @@ -25,10 +26,8 @@ class UdpBlePassThroughHandler extends ScpMessageBaseHandle @override void handleResp(ScpMessage scpMessage) { final BleResp bleResp = scpMessage.Payload; - // 如果回复成功 - // if (bleResp.status == BleResp_StatusE.SUCCESS) { - AppLog.log('收到蓝牙消息回复:${bleResp.structData}'); - // } + AppLog.log('收到蓝牙消息回复:${bleResp.structData}'); + final data = CommandReciverManager.parseData(bleResp.structData); } @override diff --git a/lib/talk/startChart/handle/impl/udp_talk_data_handler.dart b/lib/talk/startChart/handle/impl/udp_talk_data_handler.dart index ab6e1d73..b8551fcf 100644 --- a/lib/talk/startChart/handle/impl/udp_talk_data_handler.dart +++ b/lib/talk/startChart/handle/impl/udp_talk_data_handler.dart @@ -32,7 +32,7 @@ class UdpTalkDataHandler extends ScpMessageBaseHandle @override void handleRealTimeData(ScpMessage scpMessage) { // 收到数据后调用更新,防止定时器超时 - // talkDataOverTimeTimerManager.renew(); + talkDataOverTimeTimerManager.renew(); if (scpMessage.Payload != null) { final TalkData talkData = scpMessage.Payload; // 处理音视频数据 diff --git a/lib/talk/startChart/handle/impl/udp_talk_expect_handler.dart b/lib/talk/startChart/handle/impl/udp_talk_expect_handler.dart index f6ec6c8a..f1a6007a 100644 --- a/lib/talk/startChart/handle/impl/udp_talk_expect_handler.dart +++ b/lib/talk/startChart/handle/impl/udp_talk_expect_handler.dart @@ -5,6 +5,7 @@ import 'package:flutter/services.dart'; import 'package:flutter_easyloading/flutter_easyloading.dart'; import 'package:get/get.dart'; import 'package:star_lock/talk/startChart/constant/message_type_constant.dart'; +import 'package:star_lock/talk/startChart/constant/talk_status.dart'; import 'package:star_lock/talk/startChart/entity/scp_message.dart'; import 'package:star_lock/talk/startChart/handle/scp_message_base_handle.dart'; import 'package:star_lock/talk/startChart/handle/scp_message_handle.dart'; @@ -37,10 +38,22 @@ class UdpTalkExpectHandler extends ScpMessageBaseHandle // print('收到预期音视频数据回复,scpMessage:$scpMessage'); // 停止发送预期数据的定时器 startChartManage.stopTalkExpectMessageTimer(); + // 停止发送对讲请求 + startChartManage.stopCallRequestMessageTimer(); talkViewState.rotateAngle.value = talkExpectResp.rotate ?? 0; // 收到预期数据的应答后,代表建立了连接,启动通话保持的监听 // 启动通话保持监听定时器(用来判断如果x秒内没有收到通话保持则执行的操作); talkePingOverTimeTimerManager.start(); + // 启动通话数据监听 + talkDataOverTimeTimerManager.start(); + if (talkStatus.status == TalkStatus.proactivelyCallWaitingAnswer) { + // 停止播放铃声 + stopRingtone(); + // 设置为接听成功 + talkStatus.setAnsweredSuccessfully(); + // 主动呼叫时需要启动ping + startChartManage.startTalkPingMessageTimer(); + } } } diff --git a/lib/talk/startChart/handle/impl/udp_talk_hangup_handler.dart b/lib/talk/startChart/handle/impl/udp_talk_hangup_handler.dart index d0355198..d4124e53 100644 --- a/lib/talk/startChart/handle/impl/udp_talk_hangup_handler.dart +++ b/lib/talk/startChart/handle/impl/udp_talk_hangup_handler.dart @@ -24,20 +24,26 @@ class UdpTalkHangUpHandler extends ScpMessageBaseHandle replySuccessMessage(scpMessage); talkStatus.setHangingUpDuring(); stopRingtone(); - StartChartManage().stopTalkExpectMessageTimer(); - StartChartManage().stopTalkPingMessageTimer(); + startChartManage.stopTalkExpectMessageTimer(); + startChartManage.stopTalkPingMessageTimer(); + // 挂断之后,停止对讲请求超时监听定时器 + + talkeRequestOverTimeTimerManager.cancel(); + talkePingOverTimeTimerManager.cancel(); + talkDataOverTimeTimerManager.cancel(); } @override void handleResp(ScpMessage scpMessage) { talkStatus.setHangingUpDuring(); stopRingtone(); + startChartManage.stopTalkExpectMessageTimer(); + startChartManage.stopTalkPingMessageTimer(); // 挂断之后,停止对讲请求超时监听定时器 - talkeRequestOverTimeTimerManager.renew(); talkeRequestOverTimeTimerManager.cancel(); - talkePingOverTimeTimerManager.renew(); talkePingOverTimeTimerManager.cancel(); + talkDataOverTimeTimerManager.cancel(); } @override diff --git a/lib/talk/startChart/handle/impl/udp_talk_reject_handler.dart b/lib/talk/startChart/handle/impl/udp_talk_reject_handler.dart index bc09b8c4..c292ba8e 100644 --- a/lib/talk/startChart/handle/impl/udp_talk_reject_handler.dart +++ b/lib/talk/startChart/handle/impl/udp_talk_reject_handler.dart @@ -22,10 +22,15 @@ class UdpTalkRejectHandler extends ScpMessageBaseHandle replySuccessMessage(scpMessage); // 停止铃声 stopRingtone(); - StartChartManage().stopTalkExpectMessageTimer(); - StartChartManage().stopTalkPingMessageTimer(); + startChartManage.stopTalkPingMessageTimer(); + startChartManage.stopTalkExpectMessageTimer(); // 收到接听拒绝回复 talkStatus.setRejected(); + // 拒绝接听之后,停止对讲请求超时监听定时器 + + talkeRequestOverTimeTimerManager.cancel(); + talkePingOverTimeTimerManager.cancel(); + talkDataOverTimeTimerManager.cancel(); } @override @@ -35,10 +40,9 @@ class UdpTalkRejectHandler extends ScpMessageBaseHandle stopRingtone(); // 拒绝接听之后,停止对讲请求超时监听定时器 - talkeRequestOverTimeTimerManager.renew(); talkeRequestOverTimeTimerManager.cancel(); - talkePingOverTimeTimerManager.renew(); talkePingOverTimeTimerManager.cancel(); + talkDataOverTimeTimerManager.cancel(); } @override diff --git a/lib/talk/startChart/handle/impl/udp_talk_request_handler.dart b/lib/talk/startChart/handle/impl/udp_talk_request_handler.dart index cc664390..9acc4752 100644 --- a/lib/talk/startChart/handle/impl/udp_talk_request_handler.dart +++ b/lib/talk/startChart/handle/impl/udp_talk_request_handler.dart @@ -24,26 +24,29 @@ class UdpTalkRequestHandler extends ScpMessageBaseHandle replySuccessMessage(scpMessage); // 判断是否登录账户 final loginData = await Storage.getLoginData(); - if (loginData == null || - talkStatus.status == TalkStatus.waitingAnswer || - talkStatus.status == TalkStatus.answeredSuccessfully) { - // 如果已经是等待接听了,就不在处理剩下的请求 - return; + if (loginData != null && + talkStatus.status != TalkStatus.passiveCallWaitingAnswer) { + // 收到对讲请求 + final TalkReq talkReq = scpMessage.Payload; + startChartManage.FromPeerId = scpMessage.ToPeerId!; + startChartManage.ToPeerId = scpMessage.FromPeerId!; + // 处理收到接听请求后的事件 + _talkRequestEvent(talkObjectName: talkReq.callerName); } - // 收到对讲请求 - final TalkReq talkReq = scpMessage.Payload; - startChartManage.FromPeerId = scpMessage.ToPeerId!; - startChartManage.ToPeerId = scpMessage.FromPeerId!; - // 处理收到接听请求后的事件 - _talkRequestEvent(talkObjectName: talkReq.callerName); } @override void handleResp(ScpMessage scpMessage) { // 收到对讲请求回复 final GenericResp genericResp = scpMessage.Payload; - if (genericResp.code == 0) { - print('发送对讲成功,已经收到对方的回复'); + if (checkGenericRespSuccess(genericResp)) { + // 收到对讲请求的应答 + startChartManage.FromPeerId = scpMessage.ToPeerId!; + startChartManage.ToPeerId = scpMessage.FromPeerId!; + // 发送预期数据 + startChartManage.startTalkExpectTimer(); + // 停止发送对讲请求 + startChartManage.stopCallRequestMessageTimer(); } } @@ -62,7 +65,7 @@ class UdpTalkRequestHandler extends ScpMessageBaseHandle // 显示状态栏弹窗 _showTalkRequestNotification(talkObjectName: talkObjectName); // 设置为等待接听状态 - talkStatus.setWaitingAnswer(); + talkStatus.setPassiveCallWaitingAnswer(); // 启动对讲请求超时定时器 talkeRequestOverTimeTimerManager.start(); // 收到呼叫请求,跳转到接听页面 diff --git a/lib/talk/startChart/handle/other/talke_data_over_time_timer_manager.dart b/lib/talk/startChart/handle/other/talke_data_over_time_timer_manager.dart index 4e9921d4..0dcc235f 100644 --- a/lib/talk/startChart/handle/other/talke_data_over_time_timer_manager.dart +++ b/lib/talk/startChart/handle/other/talke_data_over_time_timer_manager.dart @@ -2,12 +2,12 @@ import 'dart:async'; import 'package:flutter_easyloading/flutter_easyloading.dart'; import 'package:get/get.dart'; +import 'package:star_lock/talk/other/audio_player_manager.dart'; import 'package:star_lock/talk/startChart/constant/talk_constant.dart'; import 'package:star_lock/talk/startChart/constant/talk_status.dart'; import 'package:star_lock/talk/startChart/start_chart_manage.dart'; import 'package:star_lock/talk/startChart/status/start_chart_talk_status.dart'; - class TalkDataOverTimeTimerManager { // 单例实例 static final TalkDataOverTimeTimerManager _instance = @@ -29,22 +29,24 @@ class TalkDataOverTimeTimerManager { // 超时处理函数 static void _handleTalkeDataOverTime() { EasyLoading.showToast('通话连接失败', duration: 2000.milliseconds); + // 没有通话数据,发送挂断数据 + StartChartManage().sendTalkHangupMessage(); StartChartManage().stopTalkPingMessageTimer(); StartChartManage().stopTalkExpectMessageTimer(); talkStatus.setNotTalkData(); talkStatus.setEnd(); + AudioPlayerManager().stopRingtone(); } // 启动定时器 void start() { - _timer = Timer(timeout, onTimeout); + _timer ??= Timer(timeout, onTimeout); } // 续签定时器 void renew() { _timer?.cancel(); _timer = null; - start(); } // 取消定时器 diff --git a/lib/talk/startChart/handle/other/talke_request_over_time_timer_manager.dart b/lib/talk/startChart/handle/other/talke_request_over_time_timer_manager.dart index 6db54119..687d87fe 100644 --- a/lib/talk/startChart/handle/other/talke_request_over_time_timer_manager.dart +++ b/lib/talk/startChart/handle/other/talke_request_over_time_timer_manager.dart @@ -27,7 +27,8 @@ class TalkeRequestOverTimeTimerManager { // 超时处理函数 static void _handleTalkeRequestOverTime() { - if (talkStatus.status == TalkStatus.waitingAnswer) { + if (talkStatus.status == TalkStatus.passiveCallWaitingAnswer || + talkStatus.status == TalkStatus.proactivelyCallWaitingAnswer) { EasyLoading.showToast('通话未接通,以挂断', duration: 2000.milliseconds); // 超时未接听,发送挂断请求 StartChartManage().sendTalkRejectMessage(); diff --git a/lib/talk/startChart/start_chart_manage.dart b/lib/talk/startChart/start_chart_manage.dart index 1d6b366e..78c23aa5 100644 --- a/lib/talk/startChart/start_chart_manage.dart +++ b/lib/talk/startChart/start_chart_manage.dart @@ -1,6 +1,9 @@ import 'dart:async'; -import 'package:fixnum/fixnum.dart'; import 'dart:io'; + +import 'package:fixnum/fixnum.dart'; +import 'package:get/get.dart'; +import 'package:star_lock/appRouters.dart'; import 'package:star_lock/app_settings/app_settings.dart'; import 'package:star_lock/flavors.dart'; import 'package:star_lock/login/login/entity/LoginData.dart'; @@ -69,6 +72,7 @@ class StartChartManage { String ToPeerId = ''; // 对端ID String FromPeerId = ''; // 我的ID + String lockPeerId = ''; // echo测试peer对端 final String echoPeerId = '3phX8Ng2cZHz5NtP8xAf6nYy2z1BYytoejgjoHrWMGhH'; @@ -82,6 +86,8 @@ class StartChartManage { int _defaultIntervalTime = 1; // 默认定时发送间隔(s) Timer? talkDataTimer; // 发送通话数据消息定时器 Timer? rbcuInfoTimer; // p2p地址交换定时器 + Timer? talkRequestTimer; // 对讲请求定时器 + final int maxAttempts = 15; // 最大执行次数 final int _maxPayloadSize = 8 * 1024; // 分包大小 @@ -300,12 +306,35 @@ class StartChartManage { await _sendMessage(message: message); } + /// 启动持续发送对讲请求 + void startCallRequestMessageTimer({required String ToPeerId}) async { + // 如果已经处于等待接听状态就不发送 + if (talkStatus.status != TalkStatus.proactivelyCallWaitingAnswer) { + // 停止播放铃声 + AudioPlayerManager().playRingtone(); + Get.toNamed( + Routers.starChartTalkView, + ); + } + talkRequestTimer ??= Timer.periodic( + Duration( + seconds: _defaultIntervalTime, + ), + (Timer timer) async { + await sendCallRequestMessage(ToPeerId: ToPeerId); + }, + ); + talkStatus.setProactivelyCallWaitingAnswer(); + } + + /// 停止持续发送对讲请求 + void stopCallRequestMessageTimer() async { + talkRequestTimer?.cancel(); + talkRequestTimer = null; + } + // 发送对讲请求消息 Future sendCallRequestMessage({required String ToPeerId}) async { - if (talkStatus.status == TalkStatus.answeredSuccessfully) { - _log(text: '已经在通话中,请勿重复发送对讲请求'); - return; - } // 组装上线消息 final message = MessageCommand.talkRequestMessage( FromPeerId: FromPeerId, @@ -432,10 +461,6 @@ class StartChartManage { // 发送拒绝接听消息 void sendTalkRejectMessage() async { - if (talkStatus.status != TalkStatus.waitingAnswer) { - _log(text: '当前未处于等待接听状态, 无法发送拒绝接听消息'); - return; - } final message = MessageCommand.talkRejectMessage( ToPeerId: ToPeerId, FromPeerId: FromPeerId, @@ -450,8 +475,11 @@ class StartChartManage { // 停止发送通话保持消息、通话预期数据请求 stopTalkExpectMessageTimer(); stopTalkPingMessageTimer(); + stopCallRequestMessageTimer(); // 取消定时器 + talkePingOverTimeTimerManager.cancel(); + talkDataOverTimeTimerManager.cancel(); } // 发送期望接受消息 @@ -508,10 +536,6 @@ class StartChartManage { // 发送通话中挂断消息 Future sendTalkHangupMessage() async { - if (talkStatus.status != TalkStatus.answeredSuccessfully) { - _log(text: '当前未处于接听状态, 无法发送通话中挂断消息'); - return; - } final message = MessageCommand.talkHangupMessage( ToPeerId: ToPeerId, FromPeerId: FromPeerId, @@ -526,8 +550,10 @@ class StartChartManage { // 停止发送通话保持消息、通话预期数据请求 stopTalkExpectMessageTimer(); stopTalkPingMessageTimer(); + stopCallRequestMessageTimer(); // 取消定时器 talkePingOverTimeTimerManager.cancel(); + talkDataOverTimeTimerManager.cancel(); } // 重新上线 diff --git a/lib/talk/startChart/status/start_chart_talk_status.dart b/lib/talk/startChart/status/start_chart_talk_status.dart index e16532e7..b35ca795 100644 --- a/lib/talk/startChart/status/start_chart_talk_status.dart +++ b/lib/talk/startChart/status/start_chart_talk_status.dart @@ -38,7 +38,8 @@ class StartChartTalkStatus { } // 提供状态设置方法 - void setWaitingAnswer() => _setStatus(TalkStatus.waitingAnswer); + void setPassiveCallWaitingAnswer() => _setStatus(TalkStatus.passiveCallWaitingAnswer); + void setProactivelyCallWaitingAnswer() => _setStatus(TalkStatus.proactivelyCallWaitingAnswer); void setWaitingData() => _setStatus(TalkStatus.waitingData); diff --git a/lib/talk/startChart/views/talkView/talk_view_logic.dart b/lib/talk/startChart/views/talkView/talk_view_logic.dart index e29393d2..d387bcd7 100644 --- a/lib/talk/startChart/views/talkView/talk_view_logic.dart +++ b/lib/talk/startChart/views/talkView/talk_view_logic.dart @@ -40,7 +40,7 @@ import '../../../../tools/baseGetXController.dart'; class TalkViewLogic extends BaseGetXController { final TalkViewState state = TalkViewState(); - final LockDetailState lockDetailState = Get.find().state; + final LockDetailState lockDetailState = Get.put(LockDetailLogic()).state; Timer? _syncTimer; // 音视频播放刷新率定时器 int _startTime = 0; // 开始播放时间戳,用于判断帧数据中的时间戳位置 final int bufferSize = 20; // 缓冲区大小(以帧为单位) diff --git a/lib/talk/startChart/views/talkView/talk_view_page.dart b/lib/talk/startChart/views/talkView/talk_view_page.dart index dad73f75..5f796220 100644 --- a/lib/talk/startChart/views/talkView/talk_view_page.dart +++ b/lib/talk/startChart/views/talkView/talk_view_page.dart @@ -280,7 +280,8 @@ class _TalkViewPageState extends State logic.stopProcessingAudio(); }, onClick: () async { - if (state.talkStatus.value == TalkStatus.waitingAnswer) { + if (state.talkStatus.value == + TalkStatus.passiveCallWaitingAnswer) { // 接听 logic.initiateAnswerCommand(); } @@ -298,12 +299,12 @@ class _TalkViewPageState extends State '开锁', AppColors.mainColor, onClick: () { - if (UDPManage().remoteUnlock == 1) { + // if (UDPManage().remoteUnlock == 1) { logic.udpOpenDoorAction(); // showDeletPasswordAlertDialog(context); - } else { - logic.showToast('请在锁设置中开启远程开锁'.tr); - } + // } else { + // logic.showToast('请在锁设置中开启远程开锁'.tr); + // } }, ) ]); @@ -311,9 +312,10 @@ class _TalkViewPageState extends State String getAnswerBtnImg() { switch (state.talkStatus.value) { - case TalkStatus.waitingAnswer: + case TalkStatus.passiveCallWaitingAnswer: return 'images/main/icon_lockDetail_monitoringAnswerCalls.png'; case TalkStatus.answeredSuccessfully: + case TalkStatus.proactivelyCallWaitingAnswer: return 'images/main/icon_lockDetail_monitoringUnTalkback.png'; default: return 'images/main/icon_lockDetail_monitoringAnswerCalls.png'; @@ -322,8 +324,9 @@ class _TalkViewPageState extends State String getAnswerBtnName() { switch (state.talkStatus.value) { - case TalkStatus.waitingAnswer: + case TalkStatus.passiveCallWaitingAnswer: return '接听'.tr; + case TalkStatus.proactivelyCallWaitingAnswer: case TalkStatus.answeredSuccessfully: return '长按说话'.tr; default: diff --git a/lib/tools/storage.dart b/lib/tools/storage.dart index 41589252..236e8d0f 100755 --- a/lib/tools/storage.dart +++ b/lib/tools/storage.dart @@ -33,6 +33,7 @@ const String automaticLockOffTime = 'automaticLockOffTime'; //自动关锁时间 const String associationUrl = 'associationUrl'; //ios跳转微信的 url const String starChartRegisterNodeInfo = 'starChartRegisterNodeInfo'; //星图注册信息 const String relayInfo = 'relayInfo'; //星图中继服务器信息 +const String lockNetWorkInfo = 'lockNetWorkInfo'; //锁板配网信息 class Storage { factory Storage() => _instance; @@ -273,6 +274,23 @@ class Storage { await Storage.setString(relayInfo, jsonEncode(relayInfoEntity)); } + // 保存锁板的配网信息 + static Future saveLockNetWorkInfo(Map info) async { + await Storage.setString(lockNetWorkInfo, json.encode(info)); + } + + // 获取锁板的配网信息 + static Future?> getLockNetWorkInfo() async { + Map? info = null; + final String? data = await Storage.getString(lockNetWorkInfo); + if (data == null || data.isEmpty) { + return null; + } + // 解析 JSON 字符串为 Map + info = json.decode(data); + return info; + } + // 获取星图注册节点信息 static Future getRelayInfo() async { RelayInfoEntity? relayInfoEntity; diff --git a/pubspec.yaml b/pubspec.yaml index 46f69f29..bda21c4f 100755 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -261,6 +261,8 @@ dependencies: #图库保存 gallery_saver: ^2.3.2 fixnum: ^1.1.1 + # 获取视频封面 + video_thumbnail: ^0.5.3