From eb801de7c3f4128a2389b411f68ed0051f4cbd8d Mon Sep 17 00:00:00 2001 From: liyi Date: Tue, 8 Apr 2025 14:33:27 +0800 Subject: [PATCH 01/26] =?UTF-8?q?fix:=E5=A2=9E=E5=8A=A0=E7=AE=A1=E7=90=86?= =?UTF-8?q?=E5=91=98=E5=B7=B2=E6=BB=A1=E6=8F=90=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../fingerprint/addFingerprint/addFingerprint_logic.dart | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lib/main/lockDetail/fingerprint/addFingerprint/addFingerprint_logic.dart b/lib/main/lockDetail/fingerprint/addFingerprint/addFingerprint_logic.dart index c8507a3f..6bd97fb8 100755 --- a/lib/main/lockDetail/fingerprint/addFingerprint/addFingerprint_logic.dart +++ b/lib/main/lockDetail/fingerprint/addFingerprint/addFingerprint_logic.dart @@ -105,6 +105,13 @@ class AddFingerprintLogic extends BaseGetXController { token: token, isBeforeAddUser: false); break; + case 0xFE: + // 管理员已满 + state.ifAddState.value = false; + showToast('管理员已满'.tr, something: () { + Get.back(); + }); + break; default: //失败 state.ifAddState.value = false; From 066aff8fdf834817b93988859c876f7efa539386 Mon Sep 17 00:00:00 2001 From: liyi Date: Tue, 8 Apr 2025 14:33:54 +0800 Subject: [PATCH 02/26] =?UTF-8?q?fix:=E5=AF=B9=E8=AE=B2=E6=97=B6=E8=BF=9B?= =?UTF-8?q?=E5=85=A5=E5=90=8E=E5=8F=B0=E5=85=B3=E9=97=AD=E9=93=BE=E6=8E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../starChart/status/appLifecycle_observer.dart | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/lib/talk/starChart/status/appLifecycle_observer.dart b/lib/talk/starChart/status/appLifecycle_observer.dart index 03a0a37f..37b70152 100644 --- a/lib/talk/starChart/status/appLifecycle_observer.dart +++ b/lib/talk/starChart/status/appLifecycle_observer.dart @@ -28,17 +28,16 @@ class AppLifecycleObserver extends WidgetsBindingObserver { void onAppPaused() { // 处理应用程序进入后台的逻辑 - print('App has entered the background.'); - if (StartChartManage().talkStatus.status == - TalkStatus.passiveCallWaitingAnswer || - StartChartManage().talkStatus.status == - TalkStatus.proactivelyCallWaitingAnswer) { - StartChartManage().startTalkHangupMessageTimer(); - StartChartManage().startTalkRejectMessageTimer(); - // 如果是等待接听时就退出页面 + + final status = StartChartManage().talkStatus.status; + + if (status == TalkStatus.passiveCallWaitingAnswer || + status == TalkStatus.proactivelyCallWaitingAnswer || + status == TalkStatus.answeredSuccessfully || + status == TalkStatus.uninitialized) { + StartChartManage().destruction(); Get.back(); } - StartChartManage().destruction(); } void onAppResumed() async { From 823b268380043b92f97f9d331cd0b00994548364 Mon Sep 17 00:00:00 2001 From: liyi Date: Tue, 8 Apr 2025 14:34:25 +0800 Subject: [PATCH 03/26] =?UTF-8?q?fix:=E9=85=8D=E7=BD=91=E6=97=B6=E8=93=9D?= =?UTF-8?q?=E7=89=99=E8=B6=85=E6=97=B6=E8=BF=9B=E8=A1=8C=E6=8F=90=E7=A4=BA?= =?UTF-8?q?=EF=BC=8C=E8=B0=83=E6=95=B4=E9=85=8D=E7=BD=91=E6=88=90=E5=8A=9F?= =?UTF-8?q?=E5=90=8E=E7=9A=84=E4=B8=8A=E6=8A=A5=E6=B5=81=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../configuringWifi_logic.dart | 25 ++++++++++++------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/lib/main/lockDetail/lockSet/configuringWifi/configuringWifi/configuringWifi_logic.dart b/lib/main/lockDetail/lockSet/configuringWifi/configuringWifi/configuringWifi_logic.dart index f4688019..c38d4761 100755 --- a/lib/main/lockDetail/lockSet/configuringWifi/configuringWifi/configuringWifi_logic.dart +++ b/lib/main/lockDetail/lockSet/configuringWifi/configuringWifi/configuringWifi_logic.dart @@ -62,10 +62,8 @@ class ConfiguringWifiLogic extends BaseGetXController { peerId: peerId, ); if (entity.errorCode!.codeIsSuccessful) { - await _getUploadLockSet(); + showToast('配网成功'.tr, something: () async { - eventBus - .fire(PassCurrentLockInformationEvent(state.lockSetInfoData.value)); // 设置锁的peerID StartChartManage().lockNetworkInfo = DeviceNetworkInfo( wifiName: wifiName, @@ -74,6 +72,7 @@ class ConfiguringWifiLogic extends BaseGetXController { peerId: peerId, ); }); + _getUploadLockSet(); } } @@ -135,7 +134,7 @@ class ConfiguringWifiLogic extends BaseGetXController { // 保存到缓存 await Storage.saveLockNetWorkInfo(jsonMap); // 上报服务器 - updateNetworkInfo( + updateNetworkInfo( peerId: peerId ?? '', wifiName: wifiName ?? '', secretKey: secretKey ?? '', @@ -231,6 +230,13 @@ class ConfiguringWifiLogic extends BaseGetXController { password: state.wifiPWDController.text, gatewayConfigurationStr: state.getGatewayConfigurationStr, ); + } else if (connectionState == BluetoothConnectionState.disconnected) { + dismissEasyLoading(); + cancelBlueConnetctToastTimer(); + state.sureBtnState.value = 0; + if (state.ifCurrentScreen.value == true) { + showBlueConnetctToast(); + } } }, isAddEquipment: true, @@ -391,10 +397,10 @@ class ConfiguringWifiLogic extends BaseGetXController { // 上传数据获取设置 Future _getUploadLockSet() async { - showEasyLoading(); - showBlueConnetctToastTimer(action: () { - dismissEasyLoading(); - }); + // showEasyLoading(); + // showBlueConnetctToastTimer(action: () { + // dismissEasyLoading(); + // }); BlueManage().blueSendData(BlueManage().connectDeviceName, (BluetoothConnectionState connectionState) async { if (connectionState == BluetoothConnectionState.connected) { @@ -476,6 +482,8 @@ class ConfiguringWifiLogic extends BaseGetXController { Get.offAllNamed(Routers.starLockMain); } dismissEasyLoading(); + eventBus + .fire(PassCurrentLockInformationEvent(state.lockSetInfoData.value)); if (state.loadingTimer != null) { state.loadingTimer!.cancel(); state.loadingTimer = null; @@ -493,6 +501,5 @@ class ConfiguringWifiLogic extends BaseGetXController { state.loadingTimer!.cancel(); state.loadingTimer = null; } - } } From 3552d154294ce44d4919f0a273f5856611f24ed8 Mon Sep 17 00:00:00 2001 From: liyi Date: Tue, 8 Apr 2025 14:34:59 +0800 Subject: [PATCH 04/26] =?UTF-8?q?fix:=E5=A2=9E=E5=8A=A0=E5=90=8C=E6=84=8F?= =?UTF-8?q?=E9=9A=90=E7=A7=81=E5=8D=8F=E8=AE=AE=E4=B9=8B=E5=90=8E=E8=BF=9B?= =?UTF-8?q?=E8=A1=8C=E4=B8=80=E9=94=AE=E7=99=BB=E5=BD=95=E5=88=9D=E5=A7=8B?= =?UTF-8?q?=E5=8C=96=E4=BA=8B=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/login/login/starLock_login_logic.dart | 22 ++++++++++++++++------ lib/main.dart | 4 +++- lib/tools/eventBusEventManage.dart | 5 +++++ 3 files changed, 24 insertions(+), 7 deletions(-) diff --git a/lib/login/login/starLock_login_logic.dart b/lib/login/login/starLock_login_logic.dart index d7244068..d0f5d2cd 100755 --- a/lib/login/login/starLock_login_logic.dart +++ b/lib/login/login/starLock_login_logic.dart @@ -1,18 +1,17 @@ -import 'dart:io'; - import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:star_lock/apm/apm_helper.dart'; -import 'package:jverify/jverify.dart'; import 'package:star_lock/appRouters.dart'; import 'package:star_lock/app_settings/app_settings.dart'; import 'package:star_lock/blue/blue_manage.dart'; +import 'package:star_lock/blue/io_tool/manager_event_bus.dart'; import 'package:star_lock/common/XSConstantMacro/XSConstantMacro.dart'; import 'package:star_lock/login/login/entity/LoginEntity.dart'; import 'package:star_lock/mine/mine/starLockMine_state.dart'; import 'package:star_lock/mine/minePersonInfo/minePersonInfoPage/minePersonInfo_entity.dart'; import 'package:star_lock/network/start_chart_api.dart'; import 'package:star_lock/talk/starChart/entity/star_chart_register_node_entity.dart'; +import 'package:star_lock/tools/appFirstEnterHandle.dart'; import 'package:star_lock/tools/baseGetXController.dart'; import '../../main/lockMian/lockMain/lockMain_logic.dart'; @@ -143,7 +142,7 @@ class StarLockLoginLogic extends BaseGetXController { if (entity.errorCode!.codeIsSuccessful) { if (state.countryName != entity.data!.name) { ShowTipView().showSureAlertDialog( - '国家地区的选择将影响数据安全,你当前选择的是'+state.countryName+'请确认后再继续'.tr, + '国家地区的选择将影响数据安全,你当前选择的是' + state.countryName + '请确认后再继续'.tr, tipTitle: '确认国家或地区'.tr, sureStr: '我知道了'.tr); } @@ -175,11 +174,22 @@ class StarLockLoginLogic extends BaseGetXController { state.canNext.value = state.pwdIsOK && state.isEmailOrPhone; } + void _initEventListen() { + eventBus + .on() + .listen((AgreePrivacyAgreement event) async { + await JverifyOneClickLoginManage(); + oneClickLoginAction(); + state.isCheckVerifyEnable.value = + await JverifyOneClickLoginManage().checkVerifyEnable(); + AppLog.log('一键登录初始化认证结果:${state.isCheckVerifyEnable.value}'); + }); + } + @override Future onInit() async { + _initEventListen(); super.onInit(); - - } @override diff --git a/lib/main.dart b/lib/main.dart index 9e20bdd8..9e9f5927 100755 --- a/lib/main.dart +++ b/lib/main.dart @@ -18,6 +18,7 @@ import 'package:star_lock/talk/starChart/handle/impl/debug_Info_model.dart'; import 'package:star_lock/talk/starChart/status/appLifecycle_observer.dart'; import 'package:star_lock/tools/bugly/bugly_tool.dart'; import 'package:star_lock/tools/device_info_service.dart'; +import 'package:star_lock/tools/eventBusEventManage.dart'; import 'package:star_lock/tools/jverify_one_click_login.dart'; import 'package:star_lock/tools/platform_info_services.dart'; import 'package:star_lock/tools/push/notification_service.dart'; @@ -104,8 +105,9 @@ Future privacySDKInitialization() async { // 初始化一键登录服务 final StarLockLoginLogic loginLogic = Get.put(StarLockLoginLogic()); - JverifyOneClickLoginManage(); + await JverifyOneClickLoginManage(); loginLogic.oneClickLoginAction(); loginLogic.state.isCheckVerifyEnable.value = await JverifyOneClickLoginManage().checkVerifyEnable(); + eventBus.fire(AgreePrivacyAgreement()); } diff --git a/lib/tools/eventBusEventManage.dart b/lib/tools/eventBusEventManage.dart index 5d5e7416..a1791c6e 100755 --- a/lib/tools/eventBusEventManage.dart +++ b/lib/tools/eventBusEventManage.dart @@ -195,3 +195,8 @@ class RogerThatLockInfoDataEvent { class GetGatewayListRefreshUI { GetGatewayListRefreshUI(); } +/// 同意隐私协议 +class AgreePrivacyAgreement { + AgreePrivacyAgreement(); +} + From 99813877b6839e19f8d74a038411ece19594befb Mon Sep 17 00:00:00 2001 From: liyi Date: Tue, 8 Apr 2025 14:35:15 +0800 Subject: [PATCH 05/26] =?UTF-8?q?fix:=E8=B0=83=E6=95=B4=E4=BA=BA=E8=84=B8?= =?UTF-8?q?=E5=88=97=E8=A1=A8=E5=8A=A0=E8=BD=BD=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../face/faceList/faceList_logic.dart | 39 ++++++++++------- .../face/faceList/faceList_page.dart | 42 ++++++------------- 2 files changed, 38 insertions(+), 43 deletions(-) diff --git a/lib/main/lockDetail/face/faceList/faceList_logic.dart b/lib/main/lockDetail/face/faceList/faceList_logic.dart index debdc5ce..9781a916 100755 --- a/lib/main/lockDetail/face/faceList/faceList_logic.dart +++ b/lib/main/lockDetail/face/faceList/faceList_logic.dart @@ -22,6 +22,7 @@ class FaceListLogic extends BaseGetXController { // 获取解析后的数据 late StreamSubscription _replySubscription; + void _initReplySubscription() { _replySubscription = EventBusManager().eventBus!.on().listen((Reply reply) { @@ -77,11 +78,15 @@ class FaceListLogic extends BaseGetXController { userID: (await Storage.getUid())!, faceNo: state.deletFaceNo, useCountLimit: 0xffff, - operate: state.isDeletAll == true ? 3 : 2, // 0:注册 1:修改 2:删除 3:删除全部 + operate: state.isDeletAll == true ? 3 : 2, + // 0:注册 1:修改 2:删除 3:删除全部 isAdmin: 0, - isForce: 0, // 是否是胁迫 - isRound: 0, // 是否是循环 - weekRound: 0, // 周循环 + isForce: 0, + // 是否是胁迫 + isRound: 0, + // 是否是循环 + weekRound: 0, + // 周循环 startDate: 0x11223344, endDate: 0x11223344, startTime: '0', @@ -277,11 +282,15 @@ class FaceListLogic extends BaseGetXController { userID: (await Storage.getUid())!, faceNo: state.deletFaceNo, useCountLimit: 0xffff, - operate: state.isDeletAll == true ? 3 : 2, // 0:注册 1:修改 2:删除 3:删除全部 + operate: state.isDeletAll == true ? 3 : 2, + // 0:注册 1:修改 2:删除 3:删除全部 isAdmin: 0, - isForce: 0, // 是否是胁迫 - isRound: 0, // 是否是循环 - weekRound: 0, // 周循环 + isForce: 0, + // 是否是胁迫 + isRound: 0, + // 是否是循环 + weekRound: 0, + // 周循环 startDate: 0x11223344, endDate: 0x11223344, startTime: '0', @@ -348,8 +357,8 @@ class FaceListLogic extends BaseGetXController { lockId: state.lockId.value, ); if (entity.errorCode!.codeIsSuccessful) { - showToast('删除成功'.tr, something: () { - getFaceListData(isRefresh: true); + showToast('删除成功'.tr, something: () async { + await getFaceListData(isRefresh: true); }); } } @@ -366,8 +375,8 @@ class FaceListLogic extends BaseGetXController { lockId: state.lockId.value, ); if (entity.errorCode!.codeIsSuccessful) { - showToast('重置成功'.tr, something: () { - getFaceListData(isRefresh: true); + showToast('重置成功'.tr, something: () async{ + await getFaceListData(isRefresh: true); }); } } @@ -403,11 +412,12 @@ class FaceListLogic extends BaseGetXController { // 监听修改完详情之后刷新列表 late StreamSubscription _teamEvent; + void _initRefreshAction() { _teamEvent = eventBus .on() - .listen((OtherTypeRefreshListEvent event) { - getFaceListData(isRefresh: true); + .listen((OtherTypeRefreshListEvent event) async { + await getFaceListData(isRefresh: true); }); } @@ -434,6 +444,7 @@ class FaceListLogic extends BaseGetXController { // senderCheckingUserInfoCount(); } + getFaceListData(isRefresh: true); } @override diff --git a/lib/main/lockDetail/face/faceList/faceList_page.dart b/lib/main/lockDetail/face/faceList/faceList_page.dart index 5758785b..43248d26 100755 --- a/lib/main/lockDetail/face/faceList/faceList_page.dart +++ b/lib/main/lockDetail/face/faceList/faceList_page.dart @@ -1,4 +1,3 @@ - import 'package:flutter/material.dart'; import 'package:flutter_easyloading/flutter_easyloading.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; @@ -31,24 +30,6 @@ class _FaceListPageState extends State with RouteAware { final FaceListLogic logic = Get.put(FaceListLogic()); final FaceListState state = Get.find().state; - Future getHttpData({required bool isRefresh}) async { - final bool? isDemoMode = await Storage.getBool(ifIsDemoModeOrNot); - if (isDemoMode == false) { - logic.getFaceListData(isRefresh: isRefresh).then((FingerprintListDataEntity value) { - if (mounted) { - setState(() {}); - } - }); - } - } - - @override - void initState() { - super.initState(); - - getHttpData(isRefresh: true); - } - @override Widget build(BuildContext context) { return Scaffold( @@ -92,17 +73,17 @@ class _FaceListPageState extends State with RouteAware { ), body: EasyRefreshTool( onRefresh: () { - getHttpData(isRefresh: true); + logic.getFaceListData(isRefresh: true); }, onLoad: () { - getHttpData(isRefresh: false); + logic.getFaceListData(isRefresh: false); }, child: Column( children: [ KeySearchWidget( editingController: state.searchController, onSubmittedAction: () { - getHttpData(isRefresh: true); + logic.getFaceListData(isRefresh: true); }, ), SizedBox( @@ -110,14 +91,15 @@ class _FaceListPageState extends State with RouteAware { ), Expanded(child: _buildMainUI()), AddBottomWhiteBtn( - btnName: - '添加人脸'.tr, + btnName: '添加人脸'.tr, onClick: () async { - await Get.toNamed(Routers.addFaceTypePage, arguments: { + await Get.toNamed(Routers.addFaceTypePage, + arguments: { 'lockId': state.lockId.value, 'fromType': 1 // 1从添加钥匙列表进入 2从考勤添加员工入口进入 - })!.then((value) { - getHttpData(isRefresh: true); + })! + .then((value) { + logic.getFaceListData(isRefresh: true); }); }, ), @@ -154,9 +136,11 @@ class _FaceListPageState extends State with RouteAware { logic.getKeyType(getFaceItemData), logic.getKeyDateType(getFaceItemData), () async { await Get.toNamed(Routers.faceDetailPage, - arguments: { + arguments: { 'faceItemData': getFaceItemData, - })!.then((value) => getHttpData(isRefresh: true)); + })! + .then((value) => + logic.getFaceListData(isRefresh: true)); }), ); } From fe82f87200e1b65092f4937af4179615eb111ab4 Mon Sep 17 00:00:00 2001 From: liyi Date: Tue, 8 Apr 2025 14:35:36 +0800 Subject: [PATCH 06/26] =?UTF-8?q?fix:=E8=B0=83=E6=95=B4=E5=A4=9A=E4=B8=AA?= =?UTF-8?q?=E5=AF=B9=E8=AE=B2=E8=AF=B7=E6=B1=82=E6=97=B6=E4=B8=8D=E5=A4=84?= =?UTF-8?q?=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../handle/impl/udp_talk_request_handler.dart | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/lib/talk/starChart/handle/impl/udp_talk_request_handler.dart b/lib/talk/starChart/handle/impl/udp_talk_request_handler.dart index 06b79ad6..be2f4565 100644 --- a/lib/talk/starChart/handle/impl/udp_talk_request_handler.dart +++ b/lib/talk/starChart/handle/impl/udp_talk_request_handler.dart @@ -25,8 +25,24 @@ class UdpTalkRequestHandler extends ScpMessageBaseHandle RxString currentLanguage = CurrentLocaleTool.getCurrentLocaleString().obs; // 当前选择语言 + // 添加上次处理请求的时间戳 + int _lastRequestTime = 0; + @override void handleReq(ScpMessage scpMessage) async { + + final currentTime = DateTime.now().millisecondsSinceEpoch; + // 确保与上次请求间隔至少1秒 + if (currentTime - _lastRequestTime < 1000) { + // 如果间隔小于1秒,直接拒绝请求 + replyErrorMessage(scpMessage); + AppLog.log('对讲请求过于频繁,已拒绝'); + return; + } + + // 更新最后处理时间 + _lastRequestTime = currentTime; + // 判断是否登录账户 final loginData = await Storage.getLoginData(); @@ -47,6 +63,7 @@ class UdpTalkRequestHandler extends ScpMessageBaseHandle } else { // 拒绝接听,回复失败 replyErrorMessage(scpMessage); + AppLog.log('正在接听,回复拒绝'); } } From 5864b290557005543af2b581949c4ef2ee248c8e Mon Sep 17 00:00:00 2001 From: liyi Date: Tue, 8 Apr 2025 14:35:43 +0800 Subject: [PATCH 07/26] =?UTF-8?q?fix:=E8=B0=83=E6=95=B4=E5=9B=BD=E9=99=85?= =?UTF-8?q?=E5=8C=96=E5=86=85=E5=AE=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lan/lan_hk.json | 6 +++--- lan/lan_tw.json | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lan/lan_hk.json b/lan/lan_hk.json index 101c334c..49b5232c 100644 --- a/lan/lan_hk.json +++ b/lan/lan_hk.json @@ -173,9 +173,9 @@ "接收人信息": "收件人", "转移网关": "傳輸網關", "锁屏": "屏幕鎖定", - "已关闭": "關閉", - "已开启": "上", - "开启": "開", + "已关闭": "已關閉", + "已开启": "已開啟", + "开启": "開啟", "确定要开启重置键?": "繼續啟用Reset掣?", "确定要关闭重置键?": "繼續禁用Reset掣?", "隐藏无效开锁权限": "隱藏無效訪問權限", diff --git a/lan/lan_tw.json b/lan/lan_tw.json index f1ed8445..7110352a 100644 --- a/lan/lan_tw.json +++ b/lan/lan_tw.json @@ -172,9 +172,9 @@ "接收人信息": "收件人", "转移网关": "傳輸網關", "锁屏": "屏幕鎖定", - "已关闭": "關", - "已开启": "開啟", - "开启": "打開", + "已关闭": "已關閉", + "已开启": "已開啟", + "开启": "開啟", "确定要开启重置键?": "是否繼續啟用重置按鈕?", "确定要关闭重置键?": "是否繼續禁用重置按鈕?", "隐藏无效开锁权限": "隱藏無效訪問", From 47b0a18ef3d998ea238fa172a1d7657c35b6fb17 Mon Sep 17 00:00:00 2001 From: liyi Date: Tue, 8 Apr 2025 16:43:11 +0800 Subject: [PATCH 08/26] =?UTF-8?q?fix:=E8=B0=83=E6=95=B4=E8=A7=86=E9=A2=91?= =?UTF-8?q?=E5=B8=A7=E7=BC=93=E5=86=B2=E5=8C=BA=E9=80=BB=E8=BE=91=E8=AE=A1?= =?UTF-8?q?=E7=AE=97=E9=80=BB=E8=BE=91=EF=BC=8C=E5=A2=9E=E5=8A=A0=E7=BC=93?= =?UTF-8?q?=E5=86=B2=E5=8C=BA=E6=9C=80=E5=A4=A7=E5=A4=A7=E5=B0=8F=E8=87=B3?= =?UTF-8?q?20=E5=B8=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../views/talkView/talk_view_logic.dart | 48 +++++++++++-------- 1 file changed, 27 insertions(+), 21 deletions(-) diff --git a/lib/talk/starChart/views/talkView/talk_view_logic.dart b/lib/talk/starChart/views/talkView/talk_view_logic.dart index 8c0e3737..05d0636c 100644 --- a/lib/talk/starChart/views/talkView/talk_view_logic.dart +++ b/lib/talk/starChart/views/talkView/talk_view_logic.dart @@ -56,6 +56,9 @@ class TalkViewLogic extends BaseGetXController { final Map _imageCache = {}; + // 添加一个变量用于记录上一帧的时间戳 + int _lastFrameTimestamp = 0; // 初始值为 0 + // 添加帧率计算相关变量 int _frameCount = 0; int _lastFpsUpdateTime = 0; @@ -100,11 +103,11 @@ class TalkViewLogic extends BaseGetXController { // 判断数据类型,进行分发处理 switch (contentType) { case TalkData_ContentTypeE.G711: - // 第一帧到达时记录开始时间 - if (_isFirstAudioFrame) { - _startAudioTime = currentTime; - _isFirstAudioFrame = false; - } + // // 第一帧到达时记录开始时间 + // if (_isFirstAudioFrame) { + // _startAudioTime = currentTime; + // _isFirstAudioFrame = false; + // } // 计算音频延迟 final expectedTime = _startAudioTime + talkData.durationMs; @@ -130,15 +133,16 @@ class TalkViewLogic extends BaseGetXController { if (_isFirstFrame) { _startTime = currentTime; _isFirstFrame = false; - // AppLog.log('记录第一帧的时间戳${currentTime},${talkData.durationMs}'); + AppLog.log('第一帧帧的时间戳:${talkData.durationMs}'); } + // AppLog.log('其他帧的时间戳:${talkData.durationMs}'); + // 计算帧间间隔 + if (_lastFrameTimestamp != 0) { + final int frameInterval = talkData.durationMs - _lastFrameTimestamp; + _adjustBufferSize(frameInterval); // 根据帧间间隔调整缓冲区 + } + _lastFrameTimestamp = talkData.durationMs; // 更新上一帧时间戳 - // 计算实际延迟:当前时间 - 预期播放时间 - final expectedTime = _startTime + talkData.durationMs; - final videoDelay = currentTime - expectedTime; // 修改延迟计算方式 - - // 动态调整缓冲区 - _adjustBufferSize(videoDelay); // 然后添加到播放缓冲区 if (state.videoBuffer.length >= bufferSize) { state.videoBuffer.removeAt(0); @@ -257,19 +261,21 @@ class TalkViewLogic extends BaseGetXController { } // 新增:动态调整缓冲区大小的方法 - void _adjustBufferSize(int delay) { - const int delayThresholdHigh = 250; // 高延迟阈值(约3帧的时间) - const int delayThresholdLow = 166; // 低延迟阈值(约2帧的时间) + void _adjustBufferSize(int frameInterval) { + const int frameDuration = 83; // 假设每帧的时间间隔为 83ms(12fps) + const int delayThresholdHigh = frameDuration * 2; // 高延迟阈值(2帧时间) + const int delayThresholdLow = frameDuration; // 低延迟阈值(1帧时间) const int adjustInterval = 1; // 每次调整1帧 - if (delay > delayThresholdHigh && bufferSize < maxBufferSize) { - // 延迟较大,增加缓冲区 + if (frameInterval > delayThresholdHigh && bufferSize < maxBufferSize) { + // 帧间间隔较大,增加缓冲区 bufferSize = min(bufferSize + adjustInterval, maxBufferSize); - // AppLog.log('📈 增加缓冲区 - 当前大小: $bufferSize, 延迟: ${delay}ms'); - } else if (delay < delayThresholdLow && bufferSize > minBufferSize) { - // 延迟较小,减少缓冲区 + AppLog.log('📈 增加缓冲区 - 当前大小: $bufferSize, 帧间间隔: ${frameInterval}ms'); + } else if (frameInterval < delayThresholdLow && + bufferSize > minBufferSize) { + // 帧间间隔较小,减少缓冲区 bufferSize = max(bufferSize - adjustInterval, minBufferSize); - // AppLog.log('📉 减少缓冲区 - 当前大小: $bufferSize, 延迟: ${delay}ms'); + AppLog.log('📉 减少缓冲区 - 当前大小: $bufferSize, 帧间间隔: ${frameInterval}ms'); } } From c373cc402a5b258c27b1173eedaba1508d16dbeb Mon Sep 17 00:00:00 2001 From: liyi Date: Wed, 9 Apr 2025 10:40:15 +0800 Subject: [PATCH 09/26] =?UTF-8?q?fix:=E8=B0=83=E6=95=B4=E8=AE=BE=E7=BD=AE?= =?UTF-8?q?=E9=A1=B9=E7=9B=AE=E8=B6=85=E5=87=BA=E5=B1=8F=E5=B9=95=E6=97=B6?= =?UTF-8?q?=E6=97=A0=E6=B3=95=E4=B8=8B=E6=BB=91=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/main/lockDetail/lockDetail/lockDetail_page.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/main/lockDetail/lockDetail/lockDetail_page.dart b/lib/main/lockDetail/lockDetail/lockDetail_page.dart index 4352d93d..db230836 100755 --- a/lib/main/lockDetail/lockDetail/lockDetail_page.dart +++ b/lib/main/lockDetail/lockDetail/lockDetail_page.dart @@ -1024,7 +1024,7 @@ class _LockDetailPageState extends State Widget widget = getBottomWidget()[index]; return widget; }, - physics: const NeverScrollableScrollPhysics(), + // physics: const NeverScrollableScrollPhysics(), shrinkWrap: true, ) From 80787fd0ea8e93c18d17ddef05744e587670890a Mon Sep 17 00:00:00 2001 From: Liuyf Date: Thu, 10 Apr 2025 09:50:36 +0800 Subject: [PATCH 10/26] =?UTF-8?q?fix:=20=E4=B8=87=E5=B8=88=E5=82=85?= =?UTF-8?q?=E5=85=A5=E5=8F=A3=E9=81=AE=E7=9B=96=E4=BD=8F=E4=BA=86=E5=88=A0?= =?UTF-8?q?=E9=99=A4=E8=B4=A6=E5=8F=B7=E5=8A=9F=E8=83=BD=E5=85=A5=E5=8F=A3?= =?UTF-8?q?=EF=BC=8C=E5=AF=BC=E8=87=B4=E5=AE=A1=E6=A0=B8=E4=B8=8D=E9=80=9A?= =?UTF-8?q?=E8=BF=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/mine/mineSet/mineSet/mineSet_page.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/mine/mineSet/mineSet/mineSet_page.dart b/lib/mine/mineSet/mineSet/mineSet_page.dart index a098bb8b..a2926a55 100755 --- a/lib/mine/mineSet/mineSet/mineSet_page.dart +++ b/lib/mine/mineSet/mineSet/mineSet_page.dart @@ -456,10 +456,10 @@ class _MineSetPageState extends State // showLoginOutAlertTipDialog(); }), Container( - padding: EdgeInsets.only(right: 30.w, top: 30.h), + padding: EdgeInsets.only(left: 30.w, top: 30.h), // color: Colors.red, child: Row( - mainAxisAlignment: MainAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.start, children: [ TextButton( child: Text( From 49ed1695069bd42d331edcad92c8e8b84e7da017 Mon Sep 17 00:00:00 2001 From: liyi Date: Thu, 10 Apr 2025 11:05:09 +0800 Subject: [PATCH 11/26] =?UTF-8?q?fix:=E8=B0=83=E6=95=B4=E8=8E=B7=E5=8F=96?= =?UTF-8?q?=E9=85=8D=E7=BD=91=E4=BF=A1=E6=81=AF=E4=BD=BF=E7=94=A8=E4=BA=8B?= =?UTF-8?q?=E4=BB=B6=E9=80=9A=E7=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/main/lockDetail/lockDetail/lockDetail_logic.dart | 11 +++++++++-- lib/main/lockDetail/lockDetail/lockDetail_page.dart | 1 - .../configuringWifi/configuringWifi_logic.dart | 2 ++ lib/tools/eventBusEventManage.dart | 4 ++++ 4 files changed, 15 insertions(+), 3 deletions(-) diff --git a/lib/main/lockDetail/lockDetail/lockDetail_logic.dart b/lib/main/lockDetail/lockDetail/lockDetail_logic.dart index ee7ba5f8..80198af5 100755 --- a/lib/main/lockDetail/lockDetail/lockDetail_logic.dart +++ b/lib/main/lockDetail/lockDetail/lockDetail_logic.dart @@ -285,7 +285,7 @@ class LockDetailLogic extends BaseGetXController { final List publicKeyData = state.keyInfos.value.bluetooth!.publicKey!.cast(); final List saveStrList = changeIntListToStringList(publicKeyData); - await Storage.setStringList(saveBluePublicKey, saveStrList); + await Storage.setStringList(saveBluePublicKey, saveStrList); // 私钥 final List privateKeyData = @@ -298,7 +298,7 @@ class LockDetailLogic extends BaseGetXController { final List signKeyData = state.keyInfos.value.bluetooth!.signKey!.cast(); final List saveSignKeyList = changeIntListToStringList(signKeyData); - await Storage.setStringList(saveBlueSignKey, saveSignKeyList); + await Storage.setStringList(saveBlueSignKey, saveSignKeyList); final bool ifHaveKey = await Storage.ifHaveKey(saveBlueToken); if (!ifHaveKey) { @@ -838,5 +838,12 @@ class LockDetailLogic extends BaseGetXController { state.keyInfos.refresh(); } }); + + eventBus + .on() + .listen((SuccessfulDistributionNetwork event) { + // 配网成功获取一下配网信息 + requestDeviceNetworkInfo(); + }); } } diff --git a/lib/main/lockDetail/lockDetail/lockDetail_page.dart b/lib/main/lockDetail/lockDetail/lockDetail_page.dart index db230836..1040b5ba 100755 --- a/lib/main/lockDetail/lockDetail/lockDetail_page.dart +++ b/lib/main/lockDetail/lockDetail/lockDetail_page.dart @@ -89,7 +89,6 @@ class _LockDetailPageState extends State AppRouteObserver().routeObserver.subscribe(this, ModalRoute.of(context)!); state.isOpenLockNeedOnline.refresh(); - logic.requestDeviceNetworkInfo(); } StreamSubscription? _lockRefreshLockDetailInfoDataEvent; diff --git a/lib/main/lockDetail/lockSet/configuringWifi/configuringWifi/configuringWifi_logic.dart b/lib/main/lockDetail/lockSet/configuringWifi/configuringWifi/configuringWifi_logic.dart index c38d4761..9b25bf55 100755 --- a/lib/main/lockDetail/lockSet/configuringWifi/configuringWifi/configuringWifi_logic.dart +++ b/lib/main/lockDetail/lockSet/configuringWifi/configuringWifi/configuringWifi_logic.dart @@ -484,6 +484,8 @@ class ConfiguringWifiLogic extends BaseGetXController { dismissEasyLoading(); eventBus .fire(PassCurrentLockInformationEvent(state.lockSetInfoData.value)); + eventBus + .fire(SuccessfulDistributionNetwork()); if (state.loadingTimer != null) { state.loadingTimer!.cancel(); state.loadingTimer = null; diff --git a/lib/tools/eventBusEventManage.dart b/lib/tools/eventBusEventManage.dart index a1791c6e..810ad0a6 100755 --- a/lib/tools/eventBusEventManage.dart +++ b/lib/tools/eventBusEventManage.dart @@ -200,3 +200,7 @@ class AgreePrivacyAgreement { AgreePrivacyAgreement(); } +/// 配网成功 +class SuccessfulDistributionNetwork { + SuccessfulDistributionNetwork(); +} From cd41dd4ccf8e1b25872267799bd3479df09bb8d6 Mon Sep 17 00:00:00 2001 From: liyi Date: Thu, 10 Apr 2025 16:54:59 +0800 Subject: [PATCH 12/26] =?UTF-8?q?fix:=E8=B0=83=E6=95=B4=E9=85=8D=E7=BD=91l?= =?UTF-8?q?oading=E5=8D=A1=E4=B8=BB=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../configuringWifi_logic.dart | 156 +++++++----------- .../addLock/nearbyLock/nearbyLock_logic.dart | 4 +- 2 files changed, 61 insertions(+), 99 deletions(-) diff --git a/lib/main/lockDetail/lockSet/configuringWifi/configuringWifi/configuringWifi_logic.dart b/lib/main/lockDetail/lockSet/configuringWifi/configuringWifi/configuringWifi_logic.dart index 9b25bf55..25c8e43d 100755 --- a/lib/main/lockDetail/lockSet/configuringWifi/configuringWifi/configuringWifi_logic.dart +++ b/lib/main/lockDetail/lockSet/configuringWifi/configuringWifi/configuringWifi_logic.dart @@ -62,17 +62,15 @@ class ConfiguringWifiLogic extends BaseGetXController { peerId: peerId, ); if (entity.errorCode!.codeIsSuccessful) { + // 设置锁的peerID + StartChartManage().lockNetworkInfo = DeviceNetworkInfo( + wifiName: wifiName, + networkMac: networkMac, + secretKey: secretKey, + peerId: peerId, + ); - showToast('配网成功'.tr, something: () async { - // 设置锁的peerID - StartChartManage().lockNetworkInfo = DeviceNetworkInfo( - wifiName: wifiName, - networkMac: networkMac, - secretKey: secretKey, - peerId: peerId, - ); - }); - _getUploadLockSet(); + await _getUploadLockSet(); } } @@ -106,8 +104,11 @@ class ConfiguringWifiLogic extends BaseGetXController { // WIFI配网结果 Future _replySenderConfiguringWifiResult(Reply reply) async { final int status = reply.data[2]; - state.sureBtnState.value = 0; - state.isLoading.value = false; + // state.sureBtnState.value = 0; + + // 取消loading超时定时器 + state.loadingTimer?.cancel(); + state.loadingTimer = null; switch (status) { case 0x00: @@ -140,15 +141,17 @@ class ConfiguringWifiLogic extends BaseGetXController { secretKey: secretKey ?? '', deviceMac: deviceMac ?? '', networkMac: networkMac ?? ''); + break; default: //失败 - dismissEasyLoading(); + dismissEasyLoading(); // 关闭loading + cancelBlueConnetctToastTimer(); if (state.loadingTimer != null) { state.loadingTimer!.cancel(); state.loadingTimer = null; } - cancelBlueConnetctToastTimer(); + showToast('配网失败'.tr); state.isLoading.value = false; break; @@ -164,7 +167,7 @@ class ConfiguringWifiLogic extends BaseGetXController { // 点击配置wifi Future senderConfiguringWifiAction() async { AppLog.log('开始配网${EasyLoading.isShow}'); - EasyLoading.show(); + if (state.isLoading.isTrue) { AppLog.log('正在配网中请勿重复点击'); return; @@ -178,10 +181,10 @@ class ConfiguringWifiLogic extends BaseGetXController { showToast('请输入WiFi密码'.tr); return; } - if (state.sureBtnState.value == 1) { - return; - } - state.sureBtnState.value = 1; + // if (state.sureBtnState.value == 1) { + // return; + // } + // state.sureBtnState.value = 1; final GetGatewayConfigurationEntity entity = await ApiRepository.to.getGatewayConfigurationNotLoading(timeout: 60); @@ -218,9 +221,13 @@ class ConfiguringWifiLogic extends BaseGetXController { // 如果为空,则直接赋值 state.getGatewayConfigurationStr = "{\"userPeerld\": \"$appPeerId\"}"; } + showEasyLoading(); + showBlueConnetctToastTimer(action: () { + dismissEasyLoading(); + state.isLoading.value = false; + }); - AppLog.log('获取到配网信息===开始发送蓝牙指令${EasyLoading.isShow}'); - + // 发送配网指令 BlueManage().blueSendData( BlueManage().connectDeviceName, (BluetoothConnectionState connectionState) async { @@ -233,35 +240,16 @@ class ConfiguringWifiLogic extends BaseGetXController { } else if (connectionState == BluetoothConnectionState.disconnected) { dismissEasyLoading(); cancelBlueConnetctToastTimer(); - state.sureBtnState.value = 0; + state.isLoading.value = false; + // state.sureBtnState.value = 0; if (state.ifCurrentScreen.value == true) { showBlueConnetctToast(); } } }, - isAddEquipment: true, + isAddEquipment: false, ); - state.loadingTimer ??= Timer.periodic(Duration(milliseconds: 100), (timer) { - if (!EasyLoading.isShow) { - EasyLoading.show(); - } - }); - state.isLoading.value = true; - // 添加15秒超时检查 - Future.delayed(const Duration(seconds: 15), () { - if (state.isLoading.isTrue) { - EasyLoading.dismiss(); - state.isLoading.value = false; - state.sureBtnState.value = 0; - if (state.loadingTimer != null) { - state.loadingTimer!.cancel(); - state.loadingTimer = null; - } - showToast('配网失败'.tr); - } - }); - AppLog.log('发送方法执行完毕${EasyLoading.isShow}'); } // 获取设备状态 @@ -320,7 +308,7 @@ class ConfiguringWifiLogic extends BaseGetXController { getWifiLockServiceIpAndPort(); _initReplySubscription(); - getDevicesStatusAction(); + // getDevicesStatusAction(); } @override @@ -336,13 +324,13 @@ class ConfiguringWifiLogic extends BaseGetXController { void _replyGatewayGetStatusReply(GatewayGetStatusReply reply) { final int status = reply.data[2]; - + //成功 + dismissEasyLoading(); + cancelBlueConnetctToastTimer(); switch (status) { case 0x00: //成功 - // state.sureBtnState.value = 0; - cancelBlueConnetctToastTimer(); - dismissEasyLoading(); + // state.sureBtnState.value = 0; final GetGatewayInfoModel gatewayModel = GetGatewayInfoModel(); // 网关MAC地址 @@ -393,28 +381,17 @@ class ConfiguringWifiLogic extends BaseGetXController { } } - void _replyStatusInfo(reply) {} - // 上传数据获取设置 Future _getUploadLockSet() async { - // showEasyLoading(); - // showBlueConnetctToastTimer(action: () { - // dismissEasyLoading(); - // }); - BlueManage().blueSendData(BlueManage().connectDeviceName, - (BluetoothConnectionState connectionState) async { - if (connectionState == BluetoothConnectionState.connected) { - final List? token = await Storage.getStringList(saveBlueToken); - final List getTokenList = changeStringListToIntList(token!); - - _uploadLockSet(getTokenList); - } else if (connectionState == BluetoothConnectionState.disconnected) { - cancelBlueConnetctToastTimer(); - if (state.ifCurrentScreen.value == true) { - showBlueConnetctToast(); - } - } + showEasyLoading(); + showBlueConnetctToastTimer(action: () { + dismissEasyLoading(); }); + + final List? token = await Storage.getStringList(saveBlueToken); + final List getTokenList = changeStringListToIntList(token!); + + await _uploadLockSet(getTokenList); } // 公共的上传锁设置 @@ -438,15 +415,15 @@ class ConfiguringWifiLogic extends BaseGetXController { // 上传数据获取锁设置解析 Future _replyUpdataLockSetReply(Reply reply) async { final int status = reply.data[2]; + dismissEasyLoading(); // 关闭loading + cancelBlueConnetctToastTimer(); switch (status) { case 0x00: - //成功 - dismissEasyLoading(); - cancelBlueConnetctToastTimer(); - _lockDataUpload( + await _lockDataUpload( uploadType: 1, recordType: 0, records: reply.data.sublist(7, reply.data.length)); + break; case 0x06: //无权限 @@ -475,33 +452,18 @@ class ConfiguringWifiLogic extends BaseGetXController { records: records, isUnShowLoading: true); if (entity.errorCode!.codeIsSuccessful) { - await Future.delayed((Duration(seconds: 1))); - if (state.pageName.value == 'lockSet') { - Get.close(2); - } else { - Get.offAllNamed(Routers.starLockMain); - } - dismissEasyLoading(); - eventBus - .fire(PassCurrentLockInformationEvent(state.lockSetInfoData.value)); - eventBus - .fire(SuccessfulDistributionNetwork()); - if (state.loadingTimer != null) { - state.loadingTimer!.cancel(); - state.loadingTimer = null; - } - } - } + showToast('配网成功'.tr, something: () { + state.isLoading.value = false; + if (state.pageName.value == 'lockSet') { + Get.close(2); + } else { + Get.offAllNamed(Routers.starLockMain); + } - @override - void dispose() { - dismissEasyLoading(); - // TODO: implement dispose - super.dispose(); - state.isLoading.value = false; - if (state.loadingTimer != null) { - state.loadingTimer!.cancel(); - state.loadingTimer = null; + eventBus + .fire(PassCurrentLockInformationEvent(state.lockSetInfoData.value)); + eventBus.fire(SuccessfulDistributionNetwork()); + }); } } } diff --git a/lib/mine/addLock/nearbyLock/nearbyLock_logic.dart b/lib/mine/addLock/nearbyLock/nearbyLock_logic.dart index 77872c3c..05b499f0 100755 --- a/lib/mine/addLock/nearbyLock/nearbyLock_logic.dart +++ b/lib/mine/addLock/nearbyLock/nearbyLock_logic.dart @@ -93,7 +93,6 @@ class NearbyLockLogic extends BaseGetXController { showToast('固件升级完成'.tr); closeOTADAta(); } - dismissEasyLoading(); }); } @@ -160,6 +159,7 @@ class NearbyLockLogic extends BaseGetXController { // 获取星锁状态 Future _replyGetStarLockStatusInfo(Reply reply) async { final int status = reply.data[2]; + dismissEasyLoading(); switch (status) { case 0x00: //成功 @@ -743,8 +743,8 @@ class NearbyLockLogic extends BaseGetXController { @override void onClose() { - super.onClose(); _replySubscription?.cancel(); + super.onClose(); } Future getNearByLimits() async { From 807c71b614abbb21813c2009be84e083a10d560e Mon Sep 17 00:00:00 2001 From: liyi Date: Thu, 10 Apr 2025 18:16:48 +0800 Subject: [PATCH 13/26] =?UTF-8?q?fix:=E5=9B=BA=E5=AE=9A=E4=B8=BA20?= =?UTF-8?q?=E9=92=88=E7=BC=93=E5=86=B2=E5=8C=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../views/talkView/talk_view_logic.dart | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/lib/talk/starChart/views/talkView/talk_view_logic.dart b/lib/talk/starChart/views/talkView/talk_view_logic.dart index 05d0636c..d4fd18f5 100644 --- a/lib/talk/starChart/views/talkView/talk_view_logic.dart +++ b/lib/talk/starChart/views/talkView/talk_view_logic.dart @@ -39,7 +39,7 @@ class TalkViewLogic extends BaseGetXController { final int minBufferSize = 2; // 最小缓冲2帧,约166ms final int maxBufferSize = 8; // 最大缓冲8帧,约666ms - int bufferSize = 3; // 初始化为默认大小 + int bufferSize = 20; // 初始化为默认大小 // 修改音频相关的成员变量 final int minAudioBufferSize = 1; // 音频最小缓冲1帧 final int maxAudioBufferSize = 3; // 音频最大缓冲3帧 @@ -137,11 +137,11 @@ class TalkViewLogic extends BaseGetXController { } // AppLog.log('其他帧的时间戳:${talkData.durationMs}'); // 计算帧间间隔 - if (_lastFrameTimestamp != 0) { - final int frameInterval = talkData.durationMs - _lastFrameTimestamp; - _adjustBufferSize(frameInterval); // 根据帧间间隔调整缓冲区 - } - _lastFrameTimestamp = talkData.durationMs; // 更新上一帧时间戳 + // if (_lastFrameTimestamp != 0) { + // final int frameInterval = talkData.durationMs - _lastFrameTimestamp; + // _adjustBufferSize(frameInterval); // 根据帧间间隔调整缓冲区 + // } + // _lastFrameTimestamp = talkData.durationMs; // 更新上一帧时间戳 // 然后添加到播放缓冲区 if (state.videoBuffer.length >= bufferSize) { @@ -185,16 +185,16 @@ class TalkViewLogic extends BaseGetXController { state.videoBuffer.removeAt(oldestIndex); // 移除已播放的帧 // 更新帧率计算 - _frameCount++; - final currentTime = DateTime.now().millisecondsSinceEpoch; - final elapsed = currentTime - _lastFpsUpdateTime; - - if (elapsed >= 1000) { - // 每秒更新一次 - state.fps.value = (_frameCount * 1000 / elapsed).round(); - _frameCount = 0; - _lastFpsUpdateTime = currentTime; - } + // _frameCount++; + // final currentTime = DateTime.now().millisecondsSinceEpoch; + // final elapsed = currentTime - _lastFpsUpdateTime; + // + // if (elapsed >= 1000) { + // // 每秒更新一次 + // state.fps.value = (_frameCount * 1000 / elapsed).round(); + // _frameCount = 0; + // _lastFpsUpdateTime = currentTime; + // } // AppLog.log('🎬 播放帧 - 缓冲区剩余: ${state.videoBuffer.length}/${bufferSize}, ' // '播放延迟: ${currentTime - oldestFrame.durationMs}ms, ' // '帧时间戳: ${oldestFrame.durationMs}'); From c4191dbc95559b48e6c07b02f0729ebb415cd9c5 Mon Sep 17 00:00:00 2001 From: liyi Date: Fri, 11 Apr 2025 10:06:09 +0800 Subject: [PATCH 14/26] =?UTF-8?q?fix:=E8=B0=83=E6=95=B4=E8=8E=B7=E5=8F=96?= =?UTF-8?q?=E5=8D=A1=E7=89=87=E6=97=B6=E4=BC=9A=E5=88=B7=E6=96=B0=E5=A4=9A?= =?UTF-8?q?=E4=B8=AA=E5=88=97=E8=A1=A8=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../card/cardList/cardList_logic.dart | 27 +++++++++---- .../card/cardList/cardList_page.dart | 40 +++++++++---------- 2 files changed, 39 insertions(+), 28 deletions(-) diff --git a/lib/main/lockDetail/card/cardList/cardList_logic.dart b/lib/main/lockDetail/card/cardList/cardList_logic.dart index a11cd18c..022ff0fb 100755 --- a/lib/main/lockDetail/card/cardList/cardList_logic.dart +++ b/lib/main/lockDetail/card/cardList/cardList_logic.dart @@ -28,6 +28,7 @@ class CardListLogic extends BaseGetXController { // 获取解析后的数据 late StreamSubscription _replySubscription; + void _initReplySubscription() { _replySubscription = EventBusManager().eventBus!.on().listen((Reply reply) { @@ -69,11 +70,15 @@ class CardListLogic extends BaseGetXController { userID: (await Storage.getUid())!, cardNo: state.deletCardNo, useCountLimit: 0xffff, - operate: state.isDeletAll == true ? 3 : 2, // 0:注册 1:修改 2:删除 3:删除全部 + operate: state.isDeletAll == true ? 3 : 2, + // 0:注册 1:修改 2:删除 3:删除全部 isAdmin: 0, - isForce: 0, // 是否是胁迫 - isRound: 0, // 是否是循环 - weekRound: 0, // 周循环 + isForce: 0, + // 是否是胁迫 + isRound: 0, + // 是否是循环 + weekRound: 0, + // 周循环 startDate: 0x11223344, endDate: 0x11223344, startTime: '0', @@ -116,11 +121,15 @@ class CardListLogic extends BaseGetXController { userID: (await Storage.getUid())!, cardNo: state.deletCardNo, useCountLimit: 0xffff, - operate: state.isDeletAll == true ? 3 : 2, // 0:注册 1:修改 2:删除 3:删除全部 + operate: state.isDeletAll == true ? 3 : 2, + // 0:注册 1:修改 2:删除 3:删除全部 isAdmin: 0, - isForce: 0, // 是否是胁迫 - isRound: 0, // 是否是循环 - weekRound: 0, // 周循环 + isForce: 0, + // 是否是胁迫 + isRound: 0, + // 是否是循环 + weekRound: 0, + // 周循环 startDate: 0x11223344, endDate: 0x11223344, startTime: '0', @@ -193,6 +202,7 @@ class CardListLogic extends BaseGetXController { // 监听修改完详情之后刷新列表 late StreamSubscription _teamEvent; + void _initRefreshAction() { _teamEvent = eventBus .on() @@ -240,6 +250,7 @@ class CardListLogic extends BaseGetXController { _initRefreshAction(); } + await getICCardListData(isRefresh: true); } @override diff --git a/lib/main/lockDetail/card/cardList/cardList_page.dart b/lib/main/lockDetail/card/cardList/cardList_page.dart index 705d5c8c..f5fe77e1 100755 --- a/lib/main/lockDetail/card/cardList/cardList_page.dart +++ b/lib/main/lockDetail/card/cardList/cardList_page.dart @@ -31,24 +31,24 @@ class _CardListPageState extends State with RouteAware { final CardListLogic logic = Get.put(CardListLogic()); final CardListState state = Get.find().state; - Future getHttpData({required bool isRefresh}) async { - final bool? isDemoMode = await Storage.getBool(ifIsDemoModeOrNot); - if (isDemoMode == false) { - logic - .getICCardListData(isRefresh: isRefresh) - .then((FingerprintListDataEntity value) { - if (mounted) { - setState(() {}); - } - }); - } - } + // Future logic.getICCardListData({required bool isRefresh}) async { + // final bool? isDemoMode = await Storage.getBool(ifIsDemoModeOrNot); + // if (isDemoMode == false) { + // logic + // .getICCardListData(isRefresh: isRefresh) + // .then((FingerprintListDataEntity value) { + // if (mounted) { + // setState(() {}); + // } + // }); + // } + // } @override void initState() { super.initState(); - getHttpData(isRefresh: true); + // logic.getICCardListData(isRefresh: true); } @override @@ -92,17 +92,17 @@ class _CardListPageState extends State with RouteAware { ), body: EasyRefreshTool( onRefresh: () { - getHttpData(isRefresh: true); + logic.getICCardListData(isRefresh: true); }, onLoad: () { - getHttpData(isRefresh: false); + logic.getICCardListData(isRefresh: false); }, child: Column( children: [ KeySearchWidget( editingController: state.searchController, onSubmittedAction: () { - getHttpData(isRefresh: true); + logic.getICCardListData(isRefresh: true); }, ), SizedBox(height: 20.h), @@ -115,10 +115,10 @@ class _CardListPageState extends State with RouteAware { 'fromType': 1 // 1从添加钥匙列表进入 2从考勤添加员工入口进入 })! .then((value) { - getHttpData(isRefresh: true); + logic.getICCardListData(isRefresh: true); }); // if (data != null) { - // getHttpData(isRefresh: true); + // logic.getICCardListData(isRefresh: true); // } }, ), @@ -180,9 +180,9 @@ class _CardListPageState extends State with RouteAware { arguments: { 'fingerprintItemData': fingerprintItemData, })! - .then((value) => getHttpData(isRefresh: true)); + .then((value) => logic.getICCardListData(isRefresh: true)); // if (data != null) { - // getHttpData(isRefresh: true); + // logic.getICCardListData(isRefresh: true); // } }), ); From c9690430f70e86c07c5552ec62eeb36313ac8af1 Mon Sep 17 00:00:00 2001 From: liyi Date: Tue, 15 Apr 2025 16:01:16 +0800 Subject: [PATCH 15/26] =?UTF-8?q?fix:=E8=B0=83=E6=95=B4=E7=AE=A1=E7=90=86?= =?UTF-8?q?=E5=91=98=E5=B7=B2=E6=BB=A1=E6=8F=90=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lockDetail/card/addICCard/addICCard_logic.dart | 11 ++++++++++- lib/main/lockDetail/face/addFace/addFace_logic.dart | 12 +++++++++--- .../addFingerprint/addFingerprint_logic.dart | 9 ++++++--- lib/main/lockDetail/palm/addPalm/addPalm_logic.dart | 7 +++++++ .../addRemoteControl/addRemoteControl_logic.dart | 8 ++++++++ 5 files changed, 40 insertions(+), 7 deletions(-) diff --git a/lib/main/lockDetail/card/addICCard/addICCard_logic.dart b/lib/main/lockDetail/card/addICCard/addICCard_logic.dart index dda931b0..2729347b 100755 --- a/lib/main/lockDetail/card/addICCard/addICCard_logic.dart +++ b/lib/main/lockDetail/card/addICCard/addICCard_logic.dart @@ -80,7 +80,7 @@ class AddICCardLogic extends BaseGetXController { final List token = reply.data.sublist(5, 9); final List saveStrList = changeIntListToStringList(token); Storage.setStringList(saveBlueToken, saveStrList); - // AppLog.log('添加卡token:$token'); + AppLog.log('添加卡token:$token'); IoSenderManage.senderAddCardWithTimeCycleCoercionCommand( keyID: '1', @@ -107,6 +107,14 @@ class AddICCardLogic extends BaseGetXController { token: token, isBeforeAddUser: false); break; + case 0xFE: + case 12: + // 管理员已满 + state.ifAddState.value = false; + showToast('管理员已满'.tr, something: () { + Get.back(); + }); + break; default: //失败 state.ifAddState.value = false; @@ -146,6 +154,7 @@ class AddICCardLogic extends BaseGetXController { Get.close(1); break; case 0xFE: + case 0x12: // 管理员已满 showToast('管理员已满'.tr); Get.close(1); diff --git a/lib/main/lockDetail/face/addFace/addFace_logic.dart b/lib/main/lockDetail/face/addFace/addFace_logic.dart index d7fe6bd3..5900580c 100755 --- a/lib/main/lockDetail/face/addFace/addFace_logic.dart +++ b/lib/main/lockDetail/face/addFace/addFace_logic.dart @@ -54,7 +54,7 @@ class AddFaceLogic extends BaseGetXController { // 最大图片数 state.maxRegCount.value = reply.data[11]; - // AppLog.log('人脸开始state.maxRegCount.value:${state.maxRegCount.value}'); + AppLog.log('人脸开始state.maxRegCount.value:${state.maxRegCount.value}'); break; case 0x06: //无权限 @@ -89,6 +89,12 @@ class AddFaceLogic extends BaseGetXController { isBeforeAddUser: false ); break; + case 0xFE: + case 12: + // 管理员已满 + showToast('管理员已满'.tr); + Get.close(1); + break; default: //失败 state.ifAddState.value = false; @@ -112,9 +118,9 @@ class AddFaceLogic extends BaseGetXController { Get.close(1); break; case 0xFE: + case 12: // 管理员已满 showToast('管理员已满'.tr); - state.ifAddState.value = false; Get.close(1); break; case 0xFD: @@ -138,7 +144,7 @@ class AddFaceLogic extends BaseGetXController { // 添加人脸中 // 当前注册数 state.regIndex.value = reply.data[6]; - // AppLog.log('注册人脸过程state.regIndex.value:${state.regIndex.value}'); + AppLog.log('注册人脸过程state.regIndex.value:${state.regIndex.value}'); break; } diff --git a/lib/main/lockDetail/fingerprint/addFingerprint/addFingerprint_logic.dart b/lib/main/lockDetail/fingerprint/addFingerprint/addFingerprint_logic.dart index 6bd97fb8..c5ff8d1c 100755 --- a/lib/main/lockDetail/fingerprint/addFingerprint/addFingerprint_logic.dart +++ b/lib/main/lockDetail/fingerprint/addFingerprint/addFingerprint_logic.dart @@ -106,6 +106,7 @@ class AddFingerprintLogic extends BaseGetXController { isBeforeAddUser: false); break; case 0xFE: + case 12: // 管理员已满 state.ifAddState.value = false; showToast('管理员已满'.tr, something: () { @@ -139,10 +140,12 @@ class AddFingerprintLogic extends BaseGetXController { Get.close(1); break; case 0xFE: - // 管理员已满 - showToast('管理员已满'.tr); + case 12: + // 管理员已满 state.ifAddState.value = false; - Get.close(1); + showToast('管理员已满'.tr, something: () { + Get.back(); + }); break; case 0xFD: // 用户已满 diff --git a/lib/main/lockDetail/palm/addPalm/addPalm_logic.dart b/lib/main/lockDetail/palm/addPalm/addPalm_logic.dart index 19ca548d..eb843a3a 100755 --- a/lib/main/lockDetail/palm/addPalm/addPalm_logic.dart +++ b/lib/main/lockDetail/palm/addPalm/addPalm_logic.dart @@ -90,6 +90,12 @@ class AddPalmLogic extends BaseGetXController { isBeforeAddUser: false ); break; + case 0xFE: + case 12: + // 管理员已满 + showToast('管理员已满'.tr); + Get.close(1); + break; default: //失败 state.ifAddState.value = false; @@ -111,6 +117,7 @@ class AddPalmLogic extends BaseGetXController { Get.close(1); break; case 0xFE: + case 12: // 管理员已满 showToast('管理员已满'.tr); Get.close(1); diff --git a/lib/main/lockDetail/remoteControl/addRemoteControl/addRemoteControl_logic.dart b/lib/main/lockDetail/remoteControl/addRemoteControl/addRemoteControl_logic.dart index 7916fd7e..35d5a10e 100644 --- a/lib/main/lockDetail/remoteControl/addRemoteControl/addRemoteControl_logic.dart +++ b/lib/main/lockDetail/remoteControl/addRemoteControl/addRemoteControl_logic.dart @@ -90,6 +90,13 @@ class AddRemoteControlLogic extends BaseGetXController{ isBeforeAddUser: false ); break; + case 0xFE: + case 12: + // 管理员已满 + showToast('管理员已满'.tr); + state.ifAddState.value = false; + Get.close(1); + break; default: //失败 state.ifAddState.value = false; @@ -110,6 +117,7 @@ class AddRemoteControlLogic extends BaseGetXController{ Get.close(1); break; case 0xFE: + case 0x12: // 管理员已满 showToast('管理员已满'.tr); Get.close(1); From 02d0bc49d329d813cd96448307c8519233b9ebd3 Mon Sep 17 00:00:00 2001 From: liyi Date: Wed, 16 Apr 2025 14:11:38 +0800 Subject: [PATCH 16/26] =?UTF-8?q?fix:=E8=B0=83=E6=95=B4=E6=8C=87=E7=BA=B9?= =?UTF-8?q?=E5=88=B7=E6=96=B0=E5=A4=9A=E4=B8=AA=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../fingerprint/fingerprintList/fingerprintList_logic.dart | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/main/lockDetail/fingerprint/fingerprintList/fingerprintList_logic.dart b/lib/main/lockDetail/fingerprint/fingerprintList/fingerprintList_logic.dart index 09523db0..3c886df8 100755 --- a/lib/main/lockDetail/fingerprint/fingerprintList/fingerprintList_logic.dart +++ b/lib/main/lockDetail/fingerprint/fingerprintList/fingerprintList_logic.dart @@ -404,8 +404,8 @@ class FingerprintListLogic extends BaseGetXController { void _initRefreshAction() { _teamEvent = eventBus .on() - .listen((OtherTypeRefreshListEvent event) { - getFingerprintsListData(isRefresh: true); + .listen((OtherTypeRefreshListEvent event) async { + await getFingerprintsListData(isRefresh: true); }); } @@ -460,7 +460,7 @@ class FingerprintListLogic extends BaseGetXController { if (isDemoMode == false) { _initReplySubscription(); - _initRefreshAction(); + // _initRefreshAction(); getFingerprintsListData(isRefresh: true); } } From 2e340921c19b433caa18e7b40c95eb5d4d5f618a Mon Sep 17 00:00:00 2001 From: liyi Date: Wed, 16 Apr 2025 14:12:00 +0800 Subject: [PATCH 17/26] =?UTF-8?q?fix:=E8=B0=83=E6=95=B4=E5=87=BA=E7=8E=B0?= =?UTF-8?q?=E4=B8=80=E9=94=AE=E7=99=BB=E5=BD=95=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/login/login/starLock_login_logic.dart | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/login/login/starLock_login_logic.dart b/lib/login/login/starLock_login_logic.dart index d0f5d2cd..a03eca9f 100755 --- a/lib/login/login/starLock_login_logic.dart +++ b/lib/login/login/starLock_login_logic.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:star_lock/apm/apm_helper.dart'; @@ -174,8 +176,10 @@ class StarLockLoginLogic extends BaseGetXController { state.canNext.value = state.pwdIsOK && state.isEmailOrPhone; } + late StreamSubscription _agreePrivacySubscription; + void _initEventListen() { - eventBus + _agreePrivacySubscription = eventBus .on() .listen((AgreePrivacyAgreement event) async { await JverifyOneClickLoginManage(); @@ -194,6 +198,8 @@ class StarLockLoginLogic extends BaseGetXController { @override void onClose() { + // 取消事件监听 + _agreePrivacySubscription.cancel(); state.onClose(); super.onClose(); } From 204affd6b1e217bdea2dbb600f86cde54a51d14f Mon Sep 17 00:00:00 2001 From: liyi Date: Wed, 16 Apr 2025 14:13:31 +0800 Subject: [PATCH 18/26] =?UTF-8?q?fix:=E8=B0=83=E6=95=B4=E5=AF=86=E7=A0=81?= =?UTF-8?q?=E5=8F=82=E6=95=B0=E6=A0=BC=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../passwordKeyDetail/passwordKeyDetail_logic.dart | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/lib/main/lockDetail/passwordKey/passwordKeyDetail/passwordKeyDetail_logic.dart b/lib/main/lockDetail/passwordKey/passwordKeyDetail/passwordKeyDetail_logic.dart index 04059392..33b2f2f7 100755 --- a/lib/main/lockDetail/passwordKey/passwordKeyDetail/passwordKeyDetail_logic.dart +++ b/lib/main/lockDetail/passwordKey/passwordKeyDetail/passwordKeyDetail_logic.dart @@ -152,6 +152,13 @@ class PasswordKeyDetailLogic extends BaseGetXController { final List? token = await Storage.getStringList(saveBlueToken); final List getTokenList = changeStringListToIntList(token!); + int startTime = 0; + int endTime = 0; + if (state.itemData.value.keyboardPwdType != 2) { + startTime = state.itemData.value.startDate! ~/ 1000; + endTime = state.itemData.value.endDate! ~/ 1000; + } + IoSenderManage.senderCustomPasswordsCommand( keyID: state.itemData.value.keyboardPwdId!.toString(), userID: await Storage.getUid(), @@ -162,8 +169,8 @@ class PasswordKeyDetailLogic extends BaseGetXController { ? (state.isDeletPasswordKey.value == true ? 2 : 1) : 3, isAdmin: state.isAdministrator.value == true ? 1 : 0, - startTime: state.itemData.value.startDate! ~/ 1000, - endTime: state.itemData.value.endDate! ~/ 1000, + startTime: startTime, + endTime: endTime, needAuthor: 1, isBeforeAddUser: false, signKey: signKeyDataList, From 7f2d591e674cb7b5993170538819a1f66d486e3c Mon Sep 17 00:00:00 2001 From: liyi Date: Wed, 16 Apr 2025 14:13:50 +0800 Subject: [PATCH 19/26] =?UTF-8?q?style:=E5=8E=BB=E9=99=A4=E5=A4=9A?= =?UTF-8?q?=E4=BD=99=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../addLock/nearbyLock/nearbyLock_logic.dart | 44 ------------------- 1 file changed, 44 deletions(-) diff --git a/lib/mine/addLock/nearbyLock/nearbyLock_logic.dart b/lib/mine/addLock/nearbyLock/nearbyLock_logic.dart index 05b499f0..75d52cf4 100755 --- a/lib/mine/addLock/nearbyLock/nearbyLock_logic.dart +++ b/lib/mine/addLock/nearbyLock/nearbyLock_logic.dart @@ -449,50 +449,6 @@ class NearbyLockLogic extends BaseGetXController { } } - /// 判断 128-bit UUID 是否已配对 - bool isPaired128Bit(String serviceUuid) { - if (serviceUuid.length != 36) return false; // 确保是 128-bit UUID - try { - String status = serviceUuid.substring(30, 32); // 获取第 31 和 32 位 - return status == '01'; // '01' 表示已配对 - } catch (e) { - return false; // 如果索引越界或其他错误,返回 false - } - } - - /// 判断 128-bit UUID 是否休眠 - bool isSleeping128Bit(String serviceUuid) { - if (serviceUuid.length != 36) return false; // 确保是 128-bit UUID - try { - String status = serviceUuid.substring(32, 34); // 获取第 33 和 34 位 - return status == '00'; // '00' 表示休眠 - } catch (e) { - return false; // 如果索引越界或其他错误,返回 false - } - } - - /// 判断 32-bit UUID 是否已配对 - bool isPaired32Bit(String serviceUuid) { - if (serviceUuid.length != 8) return false; // 确保是 32-bit UUID - try { - String status = serviceUuid.substring(3, 5); // 获取第 4 和 5 位 - return status == '01'; // '01' 表示已配对 - } catch (e) { - return false; // 如果索引越界或其他错误,返回 false - } - } - - /// 判断 32-bit UUID 是否休眠 - bool isSleeping32Bit(String serviceUuid) { - if (serviceUuid.length != 8) return false; // 确保是 32-bit UUID - try { - String status = serviceUuid.substring(5, 7); // 获取第 6 和 7 位 - return status == '00'; // '00' 表示休眠 - } catch (e) { - return false; // 如果索引越界或其他错误,返回 false - } - } - void stopScanBlueList() { BlueManage().disconnect(); BlueManage().stopScan(); From 084f887e899966bad33bc223fe9f11e4cad54579 Mon Sep 17 00:00:00 2001 From: liyi Date: Wed, 16 Apr 2025 14:14:06 +0800 Subject: [PATCH 20/26] =?UTF-8?q?style:=E8=B0=83=E6=95=B4=E4=B8=80?= =?UTF-8?q?=E9=94=AE=E7=99=BB=E5=BD=95=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/main.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/main.dart b/lib/main.dart index 9e9f5927..ee1c0ca7 100755 --- a/lib/main.dart +++ b/lib/main.dart @@ -106,7 +106,6 @@ Future privacySDKInitialization() async { // 初始化一键登录服务 final StarLockLoginLogic loginLogic = Get.put(StarLockLoginLogic()); await JverifyOneClickLoginManage(); - loginLogic.oneClickLoginAction(); loginLogic.state.isCheckVerifyEnable.value = await JverifyOneClickLoginManage().checkVerifyEnable(); eventBus.fire(AgreePrivacyAgreement()); From 4234464533ffa2425dda20f7901ad832a4b167d6 Mon Sep 17 00:00:00 2001 From: liyi Date: Wed, 16 Apr 2025 14:15:11 +0800 Subject: [PATCH 21/26] =?UTF-8?q?fix:=E5=A2=9E=E5=8A=A0=E4=BA=8B=E4=BB=B6?= =?UTF-8?q?=E7=9B=91=E5=90=AC=E5=AF=B9=E5=BA=94=E5=8F=98=E9=87=8F=EF=BC=8C?= =?UTF-8?q?=E7=94=A8=E4=BA=8E=E5=90=8E=E7=BB=AD=E5=8F=96=E6=B6=88=E7=9B=91?= =?UTF-8?q?=E5=90=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/main/lockDetail/lockDetail/lockDetail_logic.dart | 4 ++-- lib/main/lockDetail/lockDetail/lockDetail_state.dart | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/main/lockDetail/lockDetail/lockDetail_logic.dart b/lib/main/lockDetail/lockDetail/lockDetail_logic.dart index 80198af5..03b69a5b 100755 --- a/lib/main/lockDetail/lockDetail/lockDetail_logic.dart +++ b/lib/main/lockDetail/lockDetail/lockDetail_logic.dart @@ -814,7 +814,7 @@ class LockDetailLogic extends BaseGetXController { } }); - eventBus + state.DetailLockInfo = eventBus .on() .listen((PassCurrentLockInformationEvent event) { if (event.lockSetInfoData.lockSettingInfo != null && @@ -839,7 +839,7 @@ class LockDetailLogic extends BaseGetXController { } }); - eventBus + state.SuccessfulDistributionNetworkEvent = eventBus .on() .listen((SuccessfulDistributionNetwork event) { // 配网成功获取一下配网信息 diff --git a/lib/main/lockDetail/lockDetail/lockDetail_state.dart b/lib/main/lockDetail/lockDetail/lockDetail_state.dart index 760f1289..01178f52 100755 --- a/lib/main/lockDetail/lockDetail/lockDetail_state.dart +++ b/lib/main/lockDetail/lockDetail/lockDetail_state.dart @@ -14,6 +14,8 @@ class LockDetailState { late StreamSubscription replySubscription; StreamSubscription? lockSetOpenOrCloseCheckInRefreshLockDetailWithAttendanceEvent; StreamSubscription? LockSetChangeSetRefreshLockDetailWithTypeSubscription; + StreamSubscription? DetailLockInfo; + StreamSubscription? SuccessfulDistributionNetworkEvent; String lockNetToken = '0'; int differentialTime = 0;// 服务器时间与本地时间差值 From a259ed9dd3d6e9ec3d6ccf4c896efdbd0c1f9251 Mon Sep 17 00:00:00 2001 From: liyi Date: Wed, 16 Apr 2025 14:16:27 +0800 Subject: [PATCH 22/26] =?UTF-8?q?fix:=E5=A2=9E=E5=8A=A0=E7=BC=93=E5=86=B2?= =?UTF-8?q?=E5=8C=BA=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../handle/other/talk_data_repository.dart | 28 ++----------------- .../views/talkView/talk_view_logic.dart | 21 +++++++------- 2 files changed, 13 insertions(+), 36 deletions(-) diff --git a/lib/talk/starChart/handle/other/talk_data_repository.dart b/lib/talk/starChart/handle/other/talk_data_repository.dart index 864aa4aa..062835cb 100644 --- a/lib/talk/starChart/handle/other/talk_data_repository.dart +++ b/lib/talk/starChart/handle/other/talk_data_repository.dart @@ -2,7 +2,6 @@ import 'dart:async'; import 'package:star_lock/talk/starChart/proto/talk_data.pb.dart'; class TalkDataRepository { - // 创建一个私有的构造函数,防止外部创建实例 TalkDataRepository._() { _talkDataStreamController = StreamController.broadcast( onListen: () { @@ -11,47 +10,26 @@ class TalkDataRepository { onCancel: () { _isListening = false; }, - sync: false, // 异步模式 + sync: false, // 改为同步模式以提高实时性 ); } - // 使用 _instance 来保存单例对象 static final TalkDataRepository _instance = TalkDataRepository._(); - // 提供一个静态方法来获取单例实例 static TalkDataRepository get instance => _instance; - // 创建一个 StreamController late final StreamController _talkDataStreamController; - bool _isListening = false; - // 用于存储数据的缓冲区 - final List _buffer = []; + // 直接返回原始流,不做转换 + Stream get talkDataStream => _talkDataStreamController.stream; - // 提供一个方法来获取 Stream - Stream get talkDataStream => - _talkDataStreamController.stream.transform( - StreamTransformer.fromHandlers( - handleData: (TalkData data, EventSink sink) { - // 限制缓冲区大小为 100 - if (_buffer.length >= 100) { - _buffer.removeAt(0); // 丢弃最旧的数据 - } - _buffer.add(data); - sink.add(data); - }, - ), - ); - - // 提供一个方法来添加 TalkData 到 Stream void addTalkData(TalkData talkData) { if (_isListening) { _talkDataStreamController.add(talkData); } } - // 提供一个方法来关闭 StreamController void dispose() { _talkDataStreamController.close(); } diff --git a/lib/talk/starChart/views/talkView/talk_view_logic.dart b/lib/talk/starChart/views/talkView/talk_view_logic.dart index d4fd18f5..779e44e9 100644 --- a/lib/talk/starChart/views/talkView/talk_view_logic.dart +++ b/lib/talk/starChart/views/talkView/talk_view_logic.dart @@ -38,8 +38,8 @@ class TalkViewLogic extends BaseGetXController { final LockDetailState lockDetailState = Get.put(LockDetailLogic()).state; final int minBufferSize = 2; // 最小缓冲2帧,约166ms - final int maxBufferSize = 8; // 最大缓冲8帧,约666ms - int bufferSize = 20; // 初始化为默认大小 + final int maxBufferSize = 20; // 最大缓冲8帧,约666ms + int bufferSize = 8; // 初始化为默认大小 // 修改音频相关的成员变量 final int minAudioBufferSize = 1; // 音频最小缓冲1帧 final int maxAudioBufferSize = 3; // 音频最大缓冲3帧 @@ -137,11 +137,11 @@ class TalkViewLogic extends BaseGetXController { } // AppLog.log('其他帧的时间戳:${talkData.durationMs}'); // 计算帧间间隔 - // if (_lastFrameTimestamp != 0) { - // final int frameInterval = talkData.durationMs - _lastFrameTimestamp; - // _adjustBufferSize(frameInterval); // 根据帧间间隔调整缓冲区 - // } - // _lastFrameTimestamp = talkData.durationMs; // 更新上一帧时间戳 + if (_lastFrameTimestamp != 0) { + final int frameInterval = talkData.durationMs - _lastFrameTimestamp; + _adjustBufferSize(frameInterval); // 根据帧间间隔调整缓冲区 + } + _lastFrameTimestamp = talkData.durationMs; // 更新上一帧时间戳 // 然后添加到播放缓冲区 if (state.videoBuffer.length >= bufferSize) { @@ -184,7 +184,7 @@ class TalkViewLogic extends BaseGetXController { state.listData.value = Uint8List.fromList(oldestFrame.content); state.videoBuffer.removeAt(oldestIndex); // 移除已播放的帧 - // 更新帧率计算 + // // 更新帧率计算 // _frameCount++; // final currentTime = DateTime.now().millisecondsSinceEpoch; // final elapsed = currentTime - _lastFpsUpdateTime; @@ -195,9 +195,7 @@ class TalkViewLogic extends BaseGetXController { // _frameCount = 0; // _lastFpsUpdateTime = currentTime; // } - // AppLog.log('🎬 播放帧 - 缓冲区剩余: ${state.videoBuffer.length}/${bufferSize}, ' - // '播放延迟: ${currentTime - oldestFrame.durationMs}ms, ' - // '帧时间戳: ${oldestFrame.durationMs}'); + } else { // AppLog.log('⚠️ 帧未找到缓存 - Key: $cacheKey'); state.videoBuffer.removeAt(oldestIndex); // 移除无法播放的帧 @@ -499,6 +497,7 @@ class TalkViewLogic extends BaseGetXController { _initAudioRecorder(); requestPermissions(); + } @override From 50944a082b088532849bb2d73c9c2a0e14b816ac Mon Sep 17 00:00:00 2001 From: liyi Date: Wed, 16 Apr 2025 14:28:18 +0800 Subject: [PATCH 23/26] =?UTF-8?q?fix:=E8=B0=83=E6=95=B4=E5=BC=82=E5=B8=B8?= =?UTF-8?q?=E5=90=8E=E4=B8=AD=E6=96=AD=E6=8C=81=E7=BB=AD=E5=8F=91=E9=80=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/talk/starChart/star_chart_manage.dart | 44 ++++++++++++----------- 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/lib/talk/starChart/star_chart_manage.dart b/lib/talk/starChart/star_chart_manage.dart index 7f60fc25..0e0e9eb8 100644 --- a/lib/talk/starChart/star_chart_manage.dart +++ b/lib/talk/starChart/star_chart_manage.dart @@ -595,27 +595,31 @@ class StartChartManage { // 发送拒绝接听消息 void startTalkRejectMessageTimer() async { - talkRejectTimer ??= Timer.periodic( - Duration(seconds: _defaultIntervalTime), - (Timer timer) async { - _sendTalkRejectMessage(); - }, - ); + try { + talkRejectTimer ??= Timer.periodic( + Duration(seconds: _defaultIntervalTime), + (Timer timer) async { + _sendTalkRejectMessage(); + }, + ); + } catch (e) { + AppLog.log("startTalkRejectMessageTimer e:${e}"); + } finally { + // 设置状态为拒绝 + StartChartTalkStatus.instance.setRejected(); + // 停止播放铃声 + AudioPlayerManager().stopRingtone(); + // 停止发送通话保持消息、通话预期数据请求 + stopTalkExpectMessageTimer(); + stopTalkPingMessageTimer(); + stopCallRequestMessageTimer(); + stopSendingRbcuInfoMessages(); + stopSendingRbcuProBeMessages(); + // 取消定时器 - // 设置状态为拒绝 - StartChartTalkStatus.instance.setRejected(); - // 停止播放铃声 - AudioPlayerManager().stopRingtone(); - // 停止发送通话保持消息、通话预期数据请求 - stopTalkExpectMessageTimer(); - stopTalkPingMessageTimer(); - stopCallRequestMessageTimer(); - stopSendingRbcuInfoMessages(); - stopSendingRbcuProBeMessages(); - // 取消定时器 - - talkePingOverTimeTimerManager.cancel(); - talkDataOverTimeTimerManager.cancel(); + talkePingOverTimeTimerManager.cancel(); + talkDataOverTimeTimerManager.cancel(); + } } // 发送期望接受消息 From 7ca848d61b99de89bde7af4b9c7a7cfaa4f2e031 Mon Sep 17 00:00:00 2001 From: liyi Date: Wed, 16 Apr 2025 17:59:21 +0800 Subject: [PATCH 24/26] =?UTF-8?q?fix:=E8=B0=83=E6=95=B4=E5=88=A4=E6=96=AD?= =?UTF-8?q?=E6=98=AF=E5=9B=BD=E5=86=85=E6=89=8D=E5=88=9D=E5=A7=8B=E5=8C=96?= =?UTF-8?q?=E4=B8=80=E9=94=AE=E7=99=BB=E5=BD=95=E7=9A=84sdk?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/login/login/starLock_login_logic.dart | 21 +++++++++++++------ lib/main.dart | 25 +++++++++++++++++------ 2 files changed, 34 insertions(+), 12 deletions(-) diff --git a/lib/login/login/starLock_login_logic.dart b/lib/login/login/starLock_login_logic.dart index a03eca9f..f6130c6b 100755 --- a/lib/login/login/starLock_login_logic.dart +++ b/lib/login/login/starLock_login_logic.dart @@ -15,6 +15,7 @@ import 'package:star_lock/network/start_chart_api.dart'; import 'package:star_lock/talk/starChart/entity/star_chart_register_node_entity.dart'; import 'package:star_lock/tools/appFirstEnterHandle.dart'; import 'package:star_lock/tools/baseGetXController.dart'; +import 'package:star_lock/translations/current_locale_tool.dart'; import '../../main/lockMian/lockMain/lockMain_logic.dart'; import '../../mine/mine/starLockMine_logic.dart'; @@ -182,11 +183,19 @@ class StarLockLoginLogic extends BaseGetXController { _agreePrivacySubscription = eventBus .on() .listen((AgreePrivacyAgreement event) async { - await JverifyOneClickLoginManage(); - oneClickLoginAction(); - state.isCheckVerifyEnable.value = - await JverifyOneClickLoginManage().checkVerifyEnable(); - AppLog.log('一键登录初始化认证结果:${state.isCheckVerifyEnable.value}'); + /// 检查ip如果属于国内才进行初始化 + final CheckIPEntity entity = await ApiRepository.to.checkIpAction(ip: ''); + String currentLanguage = + CurrentLocaleTool.getCurrentLocaleString(); // 当前选择语言 + // 判断如果ip是国内的且选的是中文才初始化一键登录 + if (entity.data!.abbreviation?.toLowerCase() == 'cn' && + currentLanguage == 'zh_CN') { + // 初始化一键登录服务 + await JverifyOneClickLoginManage(); + state.isCheckVerifyEnable.value = + await JverifyOneClickLoginManage().checkVerifyEnable(); + AppLog.log('一键登录初始化认证结果:${state.isCheckVerifyEnable.value}'); + } }); } @@ -204,7 +213,7 @@ class StarLockLoginLogic extends BaseGetXController { super.onClose(); } - //刷新设备信息 +//刷新设备信息 Future flushedDeviceInfo() async { XSConstantMacro().getDeviceInfoData().then((Map data) { state.deviceInfoMap.value = data; diff --git a/lib/main.dart b/lib/main.dart index ee1c0ca7..69901fff 100755 --- a/lib/main.dart +++ b/lib/main.dart @@ -10,12 +10,14 @@ import 'package:path/path.dart' as path; import 'package:provider/provider.dart'; import 'package:star_lock/flavors.dart'; import 'package:star_lock/login/login/starLock_login_logic.dart'; +import 'package:star_lock/login/register/entity/checkIP_entity.dart'; import 'package:star_lock/mine/about/debug/debug_tool.dart'; import 'package:star_lock/network/api_provider.dart'; import 'package:star_lock/network/api_repository.dart'; import 'package:star_lock/network/start_chart_api.dart'; import 'package:star_lock/talk/starChart/handle/impl/debug_Info_model.dart'; import 'package:star_lock/talk/starChart/status/appLifecycle_observer.dart'; +import 'package:star_lock/tools/baseGetXController.dart'; import 'package:star_lock/tools/bugly/bugly_tool.dart'; import 'package:star_lock/tools/device_info_service.dart'; import 'package:star_lock/tools/eventBusEventManage.dart'; @@ -24,6 +26,7 @@ import 'package:star_lock/tools/platform_info_services.dart'; import 'package:star_lock/tools/push/notification_service.dart'; import 'package:star_lock/tools/push/xs_jPhush.dart'; import 'package:star_lock/tools/storage.dart'; +import 'package:star_lock/translations/current_locale_tool.dart'; import 'package:star_lock/translations/trans_lib.dart'; import 'apm/apm_helper.dart'; @@ -103,10 +106,20 @@ Future privacySDKInitialization() async { await jpushProvider.initJPushService(); NotificationService().init(); // 初始化通知服务 - // 初始化一键登录服务 - final StarLockLoginLogic loginLogic = Get.put(StarLockLoginLogic()); - await JverifyOneClickLoginManage(); - loginLogic.state.isCheckVerifyEnable.value = - await JverifyOneClickLoginManage().checkVerifyEnable(); - eventBus.fire(AgreePrivacyAgreement()); + /// 检查ip如果属于国内才进行初始化 + final CheckIPEntity entity = await ApiRepository.to.checkIpAction(ip: ''); + if (entity.errorCode!.codeIsSuccessful) { + String currentLanguage = + CurrentLocaleTool.getCurrentLocaleString(); // 当前选择语言 + // 判断如果ip是国内的且选的是中文才初始化一键登录 + if (entity.data!.abbreviation?.toLowerCase() == 'cn' && + currentLanguage == 'zh_CN') { + // 初始化一键登录服务 + final StarLockLoginLogic loginLogic = Get.put(StarLockLoginLogic()); + await JverifyOneClickLoginManage(); + loginLogic.state.isCheckVerifyEnable.value = + await JverifyOneClickLoginManage().checkVerifyEnable(); + eventBus.fire(AgreePrivacyAgreement()); + } + } } From 0d8d5cb0c83c92d40aec0aa78661fd0d2230d5a5 Mon Sep 17 00:00:00 2001 From: liyi Date: Fri, 18 Apr 2025 10:33:51 +0800 Subject: [PATCH 25/26] =?UTF-8?q?fix:=E8=B0=83=E6=95=B4h264=20webview?= =?UTF-8?q?=E6=92=AD=E6=94=BE=E6=95=88=E6=9E=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- assets/html/h264.html | 133 +++++----- .../lockDetail/lockDetail_logic.dart | 1 + .../normallyOpenMode_logic.dart | 73 +++--- .../starChart/constant/talk_constant.dart | 12 + .../handle/impl/udp_talk_data_handler.dart | 78 ++---- .../handle/other/h264_frame_handler.dart | 94 +------ .../handle/other/packet_loss_statistics.dart | 94 +++++++ lib/talk/starChart/star_chart_manage.dart | 36 ++- .../views/talkView/talk_view_page.dart | 2 +- .../starChart/webView/h264_web_logic.dart | 231 +++++++++--------- 10 files changed, 391 insertions(+), 363 deletions(-) create mode 100644 lib/talk/starChart/handle/other/packet_loss_statistics.dart diff --git a/assets/html/h264.html b/assets/html/h264.html index 63303e3c..0995b612 100644 --- a/assets/html/h264.html +++ b/assets/html/h264.html @@ -1,86 +1,87 @@ + - + play + - - - + + // Function to return to Flutter page + function returnToFlutter() { + notifyFlutter("Returning to Flutter page"); + } + + // 添加清理方法 + function cleanupJMuxer() { + if (jmuxer) { + try { + jmuxer.destroy(); + jmuxer = null; + console.log('JMuxer cleaned up successfully'); + window.Flutter.postMessage('cleanup_complete'); + } catch (e) { + console.error('Error cleaning up JMuxer:', e); + window.Flutter.postMessage('cleanup_error'); + } + } + } + - + + \ No newline at end of file diff --git a/lib/main/lockDetail/lockDetail/lockDetail_logic.dart b/lib/main/lockDetail/lockDetail/lockDetail_logic.dart index 03b69a5b..f3668a2c 100755 --- a/lib/main/lockDetail/lockDetail/lockDetail_logic.dart +++ b/lib/main/lockDetail/lockDetail/lockDetail_logic.dart @@ -7,6 +7,7 @@ import 'package:get/get.dart'; import 'package:intl/intl.dart'; import 'package:permission_handler/permission_handler.dart'; import 'package:star_lock/apm/apm_helper.dart'; +import 'package:star_lock/appRouters.dart'; import 'package:star_lock/common/XSConstantMacro/XSConstantMacro.dart'; import 'package:star_lock/login/login/entity/LoginEntity.dart'; import 'package:star_lock/main/lockDetail/electronicKey/electronicKeyList/entity/ElectronicKeyListEntity.dart'; diff --git a/lib/main/lockDetail/lockSet/normallyOpenMode/normallyOpenMode_logic.dart b/lib/main/lockDetail/lockSet/normallyOpenMode/normallyOpenMode_logic.dart index c748da0c..c63750d7 100755 --- a/lib/main/lockDetail/lockSet/normallyOpenMode/normallyOpenMode_logic.dart +++ b/lib/main/lockDetail/lockSet/normallyOpenMode/normallyOpenMode_logic.dart @@ -1,4 +1,3 @@ - import 'dart:async'; import 'package:flutter_blue_plus/flutter_blue_plus.dart'; @@ -17,51 +16,59 @@ import '../../../../tools/eventBusEventManage.dart'; import '../../../../tools/storage.dart'; import 'normallyOpenMode_state.dart'; -class NormallyOpenModeLogic extends BaseGetXController{ +class NormallyOpenModeLogic extends BaseGetXController { NormallyOpenModeState state = NormallyOpenModeState(); // 配置锁的常开模式设置 - Future configPassageMode() async{ - if(state.weekDays.value.isEmpty){ + Future configPassageMode() async { + if (state.weekDays.value.isEmpty) { showToast('请选择常开日期'.tr); return; } - if(state.endTimeMinute.value < state.beginTimeMinute.value){ + if (state.endTimeMinute.value < state.beginTimeMinute.value) { showToast('结束时间不能小于开始时间哦'.tr); return; } final List passageModeConfig = []; final Map map = { - 'isAllDay':state.isAllDay.value, - 'weekDays':state.weekDays.value, - 'startDate':state.beginTimeMinute.value, - 'endDate':state.endTimeMinute.value, + 'isAllDay': state.isAllDay.value, + 'weekDays': state.weekDays.value, + 'startDate': state.beginTimeMinute.value, + 'endDate': state.endTimeMinute.value, }; passageModeConfig.add(map); final LoginEntity entity = await ApiRepository.to.setNormallyModeData( lockId: state.lockSetInfoData.value.lockId!, - passageMode:state.isOpenNormallyOpenMode.value == true ? 1:0, + passageMode: state.isOpenNormallyOpenMode.value == true ? 1 : 0, passageModeConfig: passageModeConfig, ); - if(entity.errorCode!.codeIsSuccessful){ - showToast('操作成功'.tr, something: (){ + if (entity.errorCode!.codeIsSuccessful) { + showToast('操作成功'.tr, something: () { eventBus.fire(RefreshLockListInfoDataEvent()); - state.lockSetInfoData.value.lockSettingInfo!.passageMode = state.isOpenNormallyOpenMode.value == true ? 1:0; - eventBus.fire(PassCurrentLockInformationEvent(state.lockSetInfoData.value)); - eventBus.fire(LockSetChangeSetRefreshLockDetailWithType(2, state.lockSetInfoData.value.lockSettingInfo!.passageMode!.toString())); + state.lockSetInfoData.value.lockSettingInfo!.passageMode = + state.isOpenNormallyOpenMode.value == true ? 1 : 0; + eventBus + .fire(PassCurrentLockInformationEvent(state.lockSetInfoData.value)); + eventBus.fire(LockSetChangeSetRefreshLockDetailWithType( + 2, + state.lockSetInfoData.value.lockSettingInfo!.passageMode! + .toString())); + Get.back(); }); } } // 获取解析后的数据 late StreamSubscription _replySubscription; + void _initReplySubscription() { - _replySubscription = EventBusManager().eventBus!.on().listen((Reply reply) { - if(reply is SetSupportFunctionsWithParametersReply) { + _replySubscription = + EventBusManager().eventBus!.on().listen((Reply reply) { + if (reply is SetSupportFunctionsWithParametersReply) { _replySetSupportFunctionsWithParameters(reply); } @@ -93,7 +100,7 @@ class NormallyOpenModeLogic extends BaseGetXController{ // 设置自动落锁数据解析 Future _replySetSupportFunctionsWithParameters(Reply reply) async { final int status = reply.data[2]; - switch(status){ + switch (status) { case 0x00: //成功 state.sureBtnState.value = 0; @@ -111,38 +118,44 @@ class NormallyOpenModeLogic extends BaseGetXController{ // 设置支持功能(带参数) Future sendAutoLock() 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 { + 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? privateKey = + await Storage.getStringList(saveBluePrivateKey); + final List getPrivateKeyList = + changeStringListToIntList(privateKey!); final List? token = await Storage.getStringList(saveBlueToken); final List getTokenList = changeStringListToIntList(token!); - final List? publicKey = await Storage.getStringList(saveBluePublicKey); - final List getPublicKeyList = changeStringListToIntList(publicKey!); + final List? publicKey = + await Storage.getStringList(saveBluePublicKey); + final List getPublicKeyList = + changeStringListToIntList(publicKey!); String weekStr = '00000000'; for (var day in state.weekDays.value) { - final int index = day % 7; // 将周日的索引转换为 0 - weekStr = '${weekStr.substring(0, index)}1${weekStr.substring(index + 1)}'; + final int index = day % 7; // 将周日的索引转换为 0 + weekStr = + '${weekStr.substring(0, index)}1${weekStr.substring(index + 1)}'; } // 倒序 weekStr weekStr = weekStr.split('').reversed.join(''); final int number = int.parse(weekStr, radix: 2); final List list = []; - list.add(state.isOpenNormallyOpenMode.value == true ? 1:0); + list.add(state.isOpenNormallyOpenMode.value == true ? 1 : 0); final int bieginTime = state.beginTimeMinute.value; final double bieginDouble = bieginTime / 256; @@ -159,7 +172,7 @@ class NormallyOpenModeLogic extends BaseGetXController{ list.add(end1); list.add(end2); - list.add(state.isAllDay.value == 1 ? 1:0); + list.add(state.isAllDay.value == 1 ? 1 : 0); list.add(number); list.add(0); @@ -177,7 +190,7 @@ class NormallyOpenModeLogic extends BaseGetXController{ dismissEasyLoading(); cancelBlueConnetctToastTimer(); state.sureBtnState.value = 0; - if(state.ifCurrentScreen.value == true){ + if (state.ifCurrentScreen.value == true) { showBlueConnetctToast(); } } diff --git a/lib/talk/starChart/constant/talk_constant.dart b/lib/talk/starChart/constant/talk_constant.dart index a3847d50..60d57a0d 100644 --- a/lib/talk/starChart/constant/talk_constant.dart +++ b/lib/talk/starChart/constant/talk_constant.dart @@ -1,7 +1,19 @@ +import 'package:star_lock/talk/starChart/proto/talk_expect.pb.dart'; + class TalkConstant { // TalkPing 未收到回复超时时间(s) static const int talkePingOverTime = 10; static const int talkeDataOverTime = 10; + // 收到TalkRequest 未处理超时时间(s) static const int talkeRequestOverTime = 30; + + static TalkExpectReq ImageExpect = TalkExpectReq( + videoType: [VideoTypeE.IMAGE], + audioType: [AudioTypeE.G711], + ); + static TalkExpectReq H264Expect = TalkExpectReq( + videoType: [VideoTypeE.H264], + audioType: [AudioTypeE.G711], + ); } diff --git a/lib/talk/starChart/handle/impl/udp_talk_data_handler.dart b/lib/talk/starChart/handle/impl/udp_talk_data_handler.dart index e2caed39..0a9e7ab3 100644 --- a/lib/talk/starChart/handle/impl/udp_talk_data_handler.dart +++ b/lib/talk/starChart/handle/impl/udp_talk_data_handler.dart @@ -4,6 +4,7 @@ import 'package:star_lock/talk/call/g711.dart'; import 'package:star_lock/talk/starChart/constant/message_type_constant.dart'; import 'package:star_lock/talk/starChart/entity/scp_message.dart'; import 'package:star_lock/talk/starChart/handle/other/h264_frame_handler.dart'; +import 'package:star_lock/talk/starChart/handle/other/packet_loss_statistics.dart'; import 'package:star_lock/talk/starChart/handle/scp_message_base_handle.dart'; import 'package:star_lock/talk/starChart/handle/scp_message_handle.dart'; import 'package:star_lock/talk/starChart/proto/talk_data.pb.dart'; @@ -14,62 +15,6 @@ import 'package:star_lock/talk/starChart/proto/talk_data_h264_frame.pb.dart'; // implements ScpMessageHandler { class UdpTalkDataHandler extends ScpMessageBaseHandle implements ScpMessageHandler { - factory UdpTalkDataHandler() { - return _instance; - } - - UdpTalkDataHandler._internal(); - - static final UdpTalkDataHandler _instance = UdpTalkDataHandler._internal(); - - int _recentRecvDataRate = 0; - int _recentRecvPacketCount = 0; - int _recentSendDataRate = 0; - int _recentSendPacketCount = 0; - - int _lastRecvDataRate = 0; - int _lastRecvPacketCount = 0; - int _lastSendDataRate = 0; - int _lastSendPacketCount = 0; - - void updateRecvDataRate(int dataSize) { - _recentRecvDataRate += dataSize; - _recentRecvPacketCount++; - } - - void updateSendDataRate(int dataSize) { - _recentSendDataRate += dataSize; - _recentSendPacketCount++; - } - - void resetDataRates() { - _lastRecvDataRate = _recentRecvDataRate; - _lastRecvPacketCount = _recentRecvPacketCount; - _lastSendDataRate = _recentSendDataRate; - _lastSendPacketCount = _recentSendPacketCount; - - _recentRecvDataRate = 0; - _recentRecvPacketCount = 0; - _recentSendDataRate = 0; - _recentSendPacketCount = 0; - } - - int getLastRecvDataRate() { - return _lastRecvDataRate; - } - - int getLastRecvPacketCount() { - return _lastRecvPacketCount; - } - - int getLastSendDataRate() { - return _lastSendDataRate; - } - - int getLastSendPacketCount() { - return _lastSendPacketCount; - } - @override void handleReq(ScpMessage scpMessage) {} @@ -95,6 +40,17 @@ class UdpTalkDataHandler extends ScpMessageBaseHandle return buffer.map((byte) => byte.toRadixString(16).padLeft(2, '0')).join(); } + // 在类顶部添加异步日志方法 + void _asyncLog(String message) { + Future.microtask(() { + try { + AppLog.log(message); + } catch (e) { + // 错误处理 + } + }); + } + @override deserializePayload( {required int payloadType, @@ -105,10 +61,12 @@ class UdpTalkDataHandler extends ScpMessageBaseHandle int? spTotal, int? spIndex, int? messageId}) { - // AppLog.log( - // '没有组包之前的每一个包的数据:${byte.length} messageId:$messageId spTotal:$spTotal spIndex:$spIndex PayloadLength:$PayloadLength,byte:${bufferToHexString(byte)}'); + // 获取统计信息 + final stats = PacketLossStatistics().getStatistics(); + _asyncLog('丢包统计: $stats'); + // _asyncLog( + // '分包数据:messageId:$messageId [$spIndex/$spTotal] PayloadLength:$PayloadLength'); if (messageType == MessageTypeConstant.RealTimeData) { - // 回声测试 if (spTotal != null && spTotal > 1 && messageId != null && @@ -161,8 +119,6 @@ class UdpTalkDataHandler extends ScpMessageBaseHandle final TalkDataH264Frame talkDataH264Frame = TalkDataH264Frame(); talkDataH264Frame.mergeFromBuffer(talkData.content); frameHandler.handleFrame(talkDataH264Frame); - // AppLog.log( - // "帧:${talkDataH264Frame.frameType},帧序号:${talkDataH264Frame.frameSeq},对应I帧序号:${talkDataH264Frame.frameSeqI}"); } /// 处理图片数据 diff --git a/lib/talk/starChart/handle/other/h264_frame_handler.dart b/lib/talk/starChart/handle/other/h264_frame_handler.dart index 2b4ea1ee..cd2f8bc2 100644 --- a/lib/talk/starChart/handle/other/h264_frame_handler.dart +++ b/lib/talk/starChart/handle/other/h264_frame_handler.dart @@ -1,105 +1,17 @@ import 'dart:collection'; import 'dart:typed_data'; +import 'package:flutter/services.dart'; import 'package:star_lock/app_settings/app_settings.dart'; import '../../proto/talk_data_h264_frame.pb.dart'; class H264FrameHandler { - final LinkedHashMap _frameBuffer = LinkedHashMap(); - final void Function(List frameData) onCompleteFrame; - final LinkedHashMap _frameTypeIndex = LinkedHashMap(); + final void Function(List frameData) onCompleteFrame; H264FrameHandler({required this.onCompleteFrame}); void handleFrame(TalkDataH264Frame frame) { - // 存储帧 - _frameBuffer[frame.frameSeq] = frame; - _frameTypeIndex[frame.frameSeq] = frame.frameType; - - // 检查是否可以组装完整的 GOP (Group of Pictures) - _tryAssembleFrames(frame.frameSeq); - } - - void _tryAssembleFrames(int currentSeq) { - final List framesToProcess = []; - int? startFrameSeq; - - // 从当前帧开始向前找到最近的 I 帧或 P 帧 - for (int seq = currentSeq; seq >= 0; seq--) { - final frameType = _frameTypeIndex[seq]; - if (frameType == null) continue; - if (frameType == TalkDataH264Frame_FrameTypeE.I) { - startFrameSeq = seq; - break; - } else if (frameType == TalkDataH264Frame_FrameTypeE.P) { - if (_frameBuffer.containsKey(_frameBuffer[seq]!.frameSeqI)) { - startFrameSeq = seq; - break; - } else { - _frameBuffer.remove(seq); - _frameTypeIndex.remove(seq); - } - } - } - - if (startFrameSeq != null) { - for (int seq = startFrameSeq; _frameBuffer.containsKey(seq); seq++) { - framesToProcess.add(seq); - } - - if (framesToProcess.isNotEmpty) { - _processFrames(framesToProcess); - } - } else { - _clearOldFrames(currentSeq); - } - } - - void _processFrames(List frameSeqs) { - // 按顺序组装帧数据 - // final List assembledData = []; - // - // for (var seq in frameSeqs) { - // final frame = _frameBuffer[seq]!; - // assembledData.addAll(frame.frameData); - // - // // 处理完后从缓冲区移除 - // _frameBuffer.remove(seq); - // } - // - // // 回调完整的帧数据 - // onCompleteFrame(assembledData); - // Calculate the total length of the assembled data - int totalLength = frameSeqs.fold( - 0, (sum, seq) => sum + _frameBuffer[seq]!.frameData.length); - - // Allocate a buffer for the assembled data - final assembledData = Uint8List(totalLength); - int offset = 0; - - for (var seq in frameSeqs) { - final frame = _frameBuffer[seq]!; - assembledData.setRange( - offset, offset + frame.frameData.length, frame.frameData); - offset += frame.frameData.length; - - // Remove the frame from the buffer after processing - _frameBuffer.remove(seq); - _frameTypeIndex.remove(seq); - } - - // Callback with the complete frame data - onCompleteFrame(assembledData); - } - - void clear() { - _frameBuffer.clear(); - } - - void _clearOldFrames(int currentSeq) { - // 清理比当前帧序列旧的帧 - _frameBuffer.removeWhere((seq, frame) => seq < currentSeq - 200); // 调整阈值 - _frameTypeIndex.removeWhere((seq, frameType) => seq < currentSeq - 200); + onCompleteFrame(frame.frameData); } } diff --git a/lib/talk/starChart/handle/other/packet_loss_statistics.dart b/lib/talk/starChart/handle/other/packet_loss_statistics.dart new file mode 100644 index 00000000..34dd2282 --- /dev/null +++ b/lib/talk/starChart/handle/other/packet_loss_statistics.dart @@ -0,0 +1,94 @@ +import 'dart:collection'; + +class PacketLossStatistics { + static final PacketLossStatistics _instance = + PacketLossStatistics._internal(); + factory PacketLossStatistics() => _instance; + PacketLossStatistics._internal(); + + // 记录每个messageId的分包信息 + // key: messageId, value: {totalPackets, receivedPackets} + final Map _packetsMap = HashMap(); + + // 统计信息 + int _totalMessages = 0; // 总消息数 + int _lostMessages = 0; // 丢包的消息数 + int _totalPackets = 0; // 总分包数 + int _lostPackets = 0; // 丢失的分包数 + + // 记录分包数据 + void recordPacket(int messageId, int currentIndex, int totalPackets) { + if (!_packetsMap.containsKey(messageId)) { + _packetsMap[messageId] = PacketInfo(totalPackets); + _totalMessages++; + _totalPackets += totalPackets; + } + + _packetsMap[messageId]!.receivedPackets.add(currentIndex); + + // 如果收到了该messageId的最后一个包,进行统计 + if (currentIndex == totalPackets) { + _checkPacketLoss(messageId); + } + } + + // 检查丢包情况 + void _checkPacketLoss(int messageId) { + final info = _packetsMap[messageId]!; + + // 检查是否有丢失的包 + int received = info.receivedPackets.length; + if (received < info.totalPackets) { + _lostMessages++; + _lostPackets += (info.totalPackets - received); + } + + // 清理该messageId的记录,避免内存泄漏 + _packetsMap.remove(messageId); + } + + // 获取丢包率统计信息 + PacketLossInfo getStatistics() { + if (_totalMessages == 0 || _totalPackets == 0) { + return PacketLossInfo(0.0, 0.0); + } + + // 计算消息级别的丢包率 + double messageLossRate = (_lostMessages / _totalMessages) * 100; + + // 计算分包级别的丢包率 + double packetLossRate = (_lostPackets / _totalPackets) * 100; + + return PacketLossInfo(messageLossRate, packetLossRate); + } + + // 重置统计数据 + void reset() { + _packetsMap.clear(); + _totalMessages = 0; + _lostMessages = 0; + _totalPackets = 0; + _lostPackets = 0; + } +} + +// 分包信息类 +class PacketInfo { + final int totalPackets; + final Set receivedPackets = HashSet(); + + PacketInfo(this.totalPackets); +} + +// 丢包统计信息类 +class PacketLossInfo { + final double messageLossRate; // 消息丢失率 + final double packetLossRate; // 分包丢失率 + + PacketLossInfo(this.messageLossRate, this.packetLossRate); + + @override + String toString() { + return 'Message Loss Rate: ${messageLossRate.toStringAsFixed(2)}%, Packet Loss Rate: ${packetLossRate.toStringAsFixed(2)}%'; + } +} diff --git a/lib/talk/starChart/star_chart_manage.dart b/lib/talk/starChart/star_chart_manage.dart index 0e0e9eb8..85785514 100644 --- a/lib/talk/starChart/star_chart_manage.dart +++ b/lib/talk/starChart/star_chart_manage.dart @@ -22,6 +22,7 @@ import 'package:star_lock/talk/starChart/constant/ip_constant.dart'; import 'package:star_lock/talk/starChart/constant/listen_addr_type_constant.dart'; import 'package:star_lock/talk/starChart/constant/message_type_constant.dart'; import 'package:star_lock/talk/starChart/constant/payload_type_constant.dart'; +import 'package:star_lock/talk/starChart/constant/talk_constant.dart'; import 'package:star_lock/talk/starChart/constant/talk_status.dart'; import 'package:star_lock/talk/starChart/entity/relay_info_entity.dart'; import 'package:star_lock/talk/starChart/entity/report_information_data.dart'; @@ -31,6 +32,7 @@ import 'package:star_lock/talk/starChart/exception/start_chart_message_exception import 'package:star_lock/talk/starChart/handle/impl/debug_Info_model.dart'; import 'package:star_lock/talk/starChart/handle/impl/udp_talk_data_handler.dart'; import 'package:star_lock/talk/starChart/handle/other/do_sign.dart'; +import 'package:star_lock/talk/starChart/handle/other/packet_loss_statistics.dart'; import 'package:star_lock/talk/starChart/handle/other/talke_data_over_time_timer_manager.dart'; import 'package:star_lock/talk/starChart/handle/other/talke_ping_over_time_timer_manager.dart'; import 'package:star_lock/talk/starChart/handle/other/talke_request_over_time_timer_manager.dart'; @@ -111,10 +113,7 @@ class StartChartManage { final int _maxPayloadSize = 8 * 1024; // 分包大小 // 默认通话的期望数据格式 - TalkExpectReq _defaultTalkExpect = TalkExpectReq( - videoType: [VideoTypeE.IMAGE], - audioType: [AudioTypeE.G711], - ); + TalkExpectReq _defaultTalkExpect = TalkConstant.H264Expect; String relayPeerId = ''; // 中继peerId @@ -342,7 +341,7 @@ class StartChartManage { } } - // 发送RbcuConfirm 打洞确认 + // 发送打洞确认包 void _sendRbcuConfirmMessage() async { RbcuConfirm( sessionId: _rbcuSessionId, @@ -596,10 +595,18 @@ class StartChartManage { // 发送拒绝接听消息 void startTalkRejectMessageTimer() async { try { + int count = 0; + final int maxCount = 10; // 最大执行次数为10秒 + talkRejectTimer ??= Timer.periodic( Duration(seconds: _defaultIntervalTime), (Timer timer) async { _sendTalkRejectMessage(); + count++; + if (count >= maxCount) { + timer.cancel(); + talkRejectTimer = null; + } }, ); } catch (e) { @@ -1035,6 +1042,14 @@ class StartChartManage { final int payloadType = scpMessage.PayloadType ?? 0; final int messageType = scpMessage.MessageType ?? 0; try { + // 记录分包数据用于统计丢包率 + if (scpMessage.SpIndex != null && + scpMessage.SpTotal != null && + scpMessage.MessageId != null) { + PacketLossStatistics().recordPacket( + scpMessage.MessageId!, scpMessage.SpIndex!, scpMessage.SpTotal!); + } + final ScpMessageHandler handler = ScpMessageHandlerFactory.createHandler(payloadType); if (messageType == MessageTypeConstant.Req) { @@ -1130,10 +1145,7 @@ class StartChartManage { } void reSetDefaultTalkExpect() { - _defaultTalkExpect = TalkExpectReq( - videoType: [VideoTypeE.IMAGE], - audioType: [AudioTypeE.G711], - ); + _defaultTalkExpect = TalkConstant.H264Expect; } TalkExpectReq getDefaultTalkExpect() { @@ -1152,10 +1164,7 @@ class StartChartManage { /// 修改预期接收到的数据 void sendImageVideoAndG711AudioTalkExpectData() { - final talkExpectReq = TalkExpectReq( - videoType: [VideoTypeE.IMAGE], - audioType: [AudioTypeE.G711], - ); + final talkExpectReq = TalkConstant.H264Expect; changeTalkExpectDataTypeAndReStartTalkExpectMessageTimer( talkExpect: talkExpectReq); } @@ -1216,6 +1225,7 @@ class StartChartManage { await Storage.removerStarChartRegisterNodeInfo(); // 关闭udp服务 closeUdpSocket(); + PacketLossStatistics().reset(); } /// 重置数据 diff --git a/lib/talk/starChart/views/talkView/talk_view_page.dart b/lib/talk/starChart/views/talkView/talk_view_page.dart index 9492bc59..38b22343 100644 --- a/lib/talk/starChart/views/talkView/talk_view_page.dart +++ b/lib/talk/starChart/views/talkView/talk_view_page.dart @@ -615,7 +615,7 @@ class _TalkViewPageState extends State state.videoBuffer.clear(); state.listData.value = Uint8List(0); CallTalk().finishAVData(); - UdpTalkDataHandler().resetDataRates(); + // UdpTalkDataHandler().resetDataRates(); super.dispose(); } } diff --git a/lib/talk/starChart/webView/h264_web_logic.dart b/lib/talk/starChart/webView/h264_web_logic.dart index 4b7edc5e..fdbaad3f 100644 --- a/lib/talk/starChart/webView/h264_web_logic.dart +++ b/lib/talk/starChart/webView/h264_web_logic.dart @@ -1,4 +1,5 @@ import 'dart:async'; +import 'dart:collection'; import 'dart:io'; import 'dart:ui' as ui; import 'dart:math'; // Import the math package to use sqrt @@ -23,11 +24,13 @@ import 'package:star_lock/main/lockMian/entity/lockListInfo_entity.dart'; import 'package:star_lock/network/api_repository.dart'; import 'package:star_lock/talk/call/g711.dart'; import 'package:star_lock/talk/starChart/constant/talk_status.dart'; +import 'package:star_lock/talk/starChart/handle/other/packet_loss_statistics.dart'; import 'package:star_lock/talk/starChart/proto/talk_data.pb.dart'; import 'package:star_lock/talk/starChart/proto/talk_expect.pb.dart'; import 'package:star_lock/talk/starChart/star_chart_manage.dart'; import 'package:star_lock/talk/starChart/views/talkView/talk_view_state.dart'; import 'package:star_lock/talk/starChart/webView/h264_web_view_state.dart'; +import 'package:star_lock/tools/G711Tool.dart'; import 'package:star_lock/tools/bugly/bugly_tool.dart'; import 'package:webview_flutter/webview_flutter.dart'; @@ -38,6 +41,14 @@ class H264WebViewLogic extends BaseGetXController { final LockDetailState lockDetailState = Get.put(LockDetailLogic()).state; + // 添加模拟数据相关变量 + static const int CHUNK_SIZE = 4096; + Timer? _mockDataTimer; + // 定义音频帧缓冲和发送函数 + final List _bufferedAudioFrames = []; + final Queue> _frameBuffer = Queue>(); + static const int FRAME_BUFFER_SIZE = 25; + @override void onInit() { super.onInit(); @@ -57,7 +68,7 @@ class H264WebViewLogic extends BaseGetXController { _loadLocalHtml(); // 创建流数据监听 _createFramesStreamListen(); - + // playLocalTestVideo(); _startListenTalkStatus(); state.talkStatus.value = state.startChartTalkStatus.status; // 初始化音频播放器 @@ -86,11 +97,43 @@ class H264WebViewLogic extends BaseGetXController { void _createFramesStreamListen() async { state.talkDataRepository.talkDataStream.listen((TalkData event) async { - // 发送数据给js处理 - _sendBufferedData(event.content); + // 添加新帧到缓冲区 + _frameBuffer.add(event.content); + + // 当缓冲区超过最大容量时,发送最早的帧并移除 + while (_frameBuffer.length > FRAME_BUFFER_SIZE) { + if (_frameBuffer.isNotEmpty) { + final frame = _frameBuffer.removeFirst(); + await _sendBufferedData(frame); + } + } }); } + /// 播放本地测试视频文件 + // Future playLocalTestVideo() async { + // try { + // ByteData data = await rootBundle.load('assets/html/demo.h264'); + // List bytes = data.buffer.asUint8List(); + // + // int offset = 0; + // _mockDataTimer = Timer.periodic(Duration(milliseconds: 40), (timer) { + // if (offset >= bytes.length) { + // timer.cancel(); + // return; + // } + // + // int end = min(offset + CHUNK_SIZE, bytes.length); + // List chunk = bytes.sublist(offset, end); + // _sendBufferedData(chunk); + // + // offset += CHUNK_SIZE; + // }); + // } catch (e) { + // AppLog.log('加载测试视频文件失败: $e'); + // } + // } + /// 加载html文件 Future _loadLocalHtml() async { // 加载 HTML 文件内容 @@ -226,15 +269,17 @@ class H264WebViewLogic extends BaseGetXController { //开始录音 Future startProcessingAudio() async { - // 增加录音帧监听器和错误监听器 - state.voiceProcessor?.addFrameListener(_onFrame); - state.voiceProcessor?.addErrorListener(_onError); try { if (await state.voiceProcessor?.hasRecordAudioPermission() ?? false) { await state.voiceProcessor?.start(state.frameLength, state.sampleRate); final bool? isRecording = await state.voiceProcessor?.isRecording(); state.isRecordingAudio.value = isRecording!; state.startRecordingAudioTime.value = DateTime.now(); + + // 增加录音帧监听器和错误监听器 + state.voiceProcessor + ?.addFrameListeners([_onFrame]); + state.voiceProcessor?.addErrorListener(_onError); } else { // state.errorMessage.value = 'Recording permission not granted'; } @@ -254,8 +299,8 @@ class H264WebViewLogic extends BaseGetXController { state.endRecordingAudioTime.value = DateTime.now(); // 计算录音的持续时间 - final duration = state.endRecordingAudioTime.value! - .difference(state.startRecordingAudioTime.value!); + final Duration duration = state.endRecordingAudioTime.value + .difference(state.startRecordingAudioTime.value); state.recordingAudioTime.value = duration.inSeconds; } on PlatformException catch (ex) { @@ -267,25 +312,71 @@ class H264WebViewLogic extends BaseGetXController { } } - // 音频帧处理 +// 音频帧处理 Future _onFrame(List frame) async { - // 预处理和转码操作放到异步计算线程 - // final processedFrame = await compute(preprocessAudio, frame); - // final list = listLinearToALaw(processedFrame); - final List processedFrame = preprocessAudio(frame); - final List list = listLinearToALaw(processedFrame); + // 添加最大缓冲限制 + if (_bufferedAudioFrames.length > state.frameLength * 3) { + _bufferedAudioFrames.clear(); // 清空过多积累的数据 + return; + } - final int ms = DateTime.now().millisecondsSinceEpoch - - state.startRecordingAudioTime.value.millisecondsSinceEpoch; + // 首先应用固定增益提升基础音量 + List amplifiedFrame = _applyGain(frame, 1.6); + // 编码为G711数据 + List encodedData = G711Tool.encode(amplifiedFrame, 0); // 0表示A-law + _bufferedAudioFrames.addAll(encodedData); + // 使用相对时间戳 + final int ms = DateTime.now().millisecondsSinceEpoch % 1000000; // 使用循环时间戳 + int getFrameLength = state.frameLength; + if (Platform.isIOS) { + getFrameLength = state.frameLength * 2; + } - // 发送音频数据到UDP - await StartChartManage().sendTalkDataMessage( - talkData: TalkData( - content: list, - contentType: TalkData_ContentTypeE.G711, - durationMs: ms, - ), - ); + // 添加发送间隔控制 + if (_bufferedAudioFrames.length >= state.frameLength) { + try { + await StartChartManage().sendTalkDataMessage( + talkData: TalkData( + content: _bufferedAudioFrames, + contentType: TalkData_ContentTypeE.G711, + durationMs: ms, + ), + ); + } finally { + _bufferedAudioFrames.clear(); // 确保清理缓冲区 + } + } else { + _bufferedAudioFrames.addAll(encodedData); + } + } + +// 错误监听 + void _onError(VoiceProcessorException error) { + AppLog.log(error.message!); + } + +// 添加音频增益处理方法 + List _applyGain(List pcmData, double gainFactor) { + List result = List.filled(pcmData.length, 0); + + for (int i = 0; i < pcmData.length; i++) { + // PCM数据通常是有符号的16位整数 + int sample = pcmData[i]; + + // 应用增益 + double amplified = sample * gainFactor; + + // 限制在有效范围内,防止溢出 + if (amplified > 32767) { + amplified = 32767; + } else if (amplified < -32768) { + amplified = -32768; + } + + result[i] = amplified.toInt(); + } + + return result; } /// 挂断 @@ -297,6 +388,9 @@ class H264WebViewLogic extends BaseGetXController { // 拒绝 StartChartManage().startTalkRejectMessageTimer(); } + // _mockDataTimer?.cancel(); + // _mockDataTimer = null; + PacketLossStatistics().reset(); Get.back(); } @@ -315,7 +409,7 @@ class H264WebViewLogic extends BaseGetXController { }); final LockSetInfoEntity lockSetInfoEntity = - await ApiRepository.to.getLockSettingInfoData( + await ApiRepository.to.getLockSettingInfoData( lockId: lockId.toString(), ); if (lockSetInfoEntity.errorCode!.codeIsSuccessful) { @@ -333,93 +427,11 @@ class H264WebViewLogic extends BaseGetXController { } } - List preprocessAudio(List pcmList) { - // 简单的降噪处理 - final List processedList = []; - for (int pcmVal in pcmList) { - // 简单的降噪示例:将小于阈值的信号置为0 - if (pcmVal.abs() < 200) { - pcmVal = 0; - } - processedList.add(pcmVal); - } - return processedList; - } - - List listLinearToALaw(List pcmList) { - final List aLawList = []; - for (int pcmVal in pcmList) { - final int aLawVal = linearToALaw(pcmVal); - aLawList.add(aLawVal); - } - return aLawList; - } - - int linearToALaw(int pcmVal) { - const int ALAW_MAX = 0x7FFF; // 32767 - const int ALAW_BIAS = 0x84; // 132 - - int mask; - int seg; - int aLawVal; - - // Handle sign - if (pcmVal < 0) { - pcmVal = -pcmVal; - mask = 0x7F; // 127 (sign bit is 1) - } else { - mask = 0xFF; // 255 (sign bit is 0) - } - - // Add bias and clamp to ALAW_MAX - pcmVal += ALAW_BIAS; - if (pcmVal > ALAW_MAX) { - pcmVal = ALAW_MAX; - } - - // Determine segment - seg = search(pcmVal); - - // Calculate A-law value - if (seg >= 8) { - aLawVal = 0x7F ^ mask; // Clamp to maximum value - } else { - int quantized = (pcmVal >> (seg + 3)) & 0xF; - aLawVal = (seg << 4) | quantized; - aLawVal ^= 0xD5; // XOR with 0xD5 to match standard A-law table - } - - return aLawVal; - } - - int search(int val) { - final List table = [ - 0xFF, // Segment 0 - 0x1FF, // Segment 1 - 0x3FF, // Segment 2 - 0x7FF, // Segment 3 - 0xFFF, // Segment 4 - 0x1FFF, // Segment 5 - 0x3FFF, // Segment 6 - 0x7FFF // Segment 7 - ]; - const int size = 8; - for (int i = 0; i < size; i++) { - if (val <= table[i]) { - return i; - } - } - return size; - } - -// 错误监听 - void _onError(VoiceProcessorException error) { - AppLog.log(error.message!); - } @override void dispose() { - // TODO: implement dispose + // _mockDataTimer?.cancel(); + // _mockDataTimer = null; super.dispose(); StartChartManage().startTalkHangupMessageTimer(); state.animationController.dispose(); @@ -429,5 +441,6 @@ class H264WebViewLogic extends BaseGetXController { state.oneMinuteTimeTimer = null; stopProcessingAudio(); StartChartManage().reSetDefaultTalkExpect(); + _frameBuffer.clear(); } } From a0d2bdaa7a8877f6d5a6974a8d7bc403bb0e5c7e Mon Sep 17 00:00:00 2001 From: liyi Date: Fri, 18 Apr 2025 10:34:42 +0800 Subject: [PATCH 26/26] =?UTF-8?q?fix:=E8=B0=83=E6=95=B4=E9=BB=98=E8=AE=A4?= =?UTF-8?q?=E4=BD=BF=E7=94=A8Image=E5=AF=B9=E8=AE=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/talk/starChart/star_chart_manage.dart | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/talk/starChart/star_chart_manage.dart b/lib/talk/starChart/star_chart_manage.dart index 85785514..7ffed8e5 100644 --- a/lib/talk/starChart/star_chart_manage.dart +++ b/lib/talk/starChart/star_chart_manage.dart @@ -113,7 +113,7 @@ class StartChartManage { final int _maxPayloadSize = 8 * 1024; // 分包大小 // 默认通话的期望数据格式 - TalkExpectReq _defaultTalkExpect = TalkConstant.H264Expect; + TalkExpectReq _defaultTalkExpect = TalkConstant.ImageExpect; String relayPeerId = ''; // 中继peerId @@ -1145,7 +1145,7 @@ class StartChartManage { } void reSetDefaultTalkExpect() { - _defaultTalkExpect = TalkConstant.H264Expect; + _defaultTalkExpect = TalkConstant.ImageExpect; } TalkExpectReq getDefaultTalkExpect() { @@ -1164,7 +1164,7 @@ class StartChartManage { /// 修改预期接收到的数据 void sendImageVideoAndG711AudioTalkExpectData() { - final talkExpectReq = TalkConstant.H264Expect; + final talkExpectReq = TalkConstant.ImageExpect; changeTalkExpectDataTypeAndReStartTalkExpectMessageTimer( talkExpect: talkExpectReq); }