远程开锁优化
配网错误提示优化 配网界面去掉2.4
This commit is contained in:
parent
cd9e5da6a0
commit
5e0eea5486
@ -2,6 +2,7 @@ import 'dart:async';
|
|||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:device_info_plus/device_info_plus.dart';
|
import 'package:device_info_plus/device_info_plus.dart';
|
||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/scheduler.dart';
|
import 'package:flutter/scheduler.dart';
|
||||||
import 'package:flutter_blue_plus/flutter_blue_plus.dart';
|
import 'package:flutter_blue_plus/flutter_blue_plus.dart';
|
||||||
import 'package:flutter_easyloading/flutter_easyloading.dart';
|
import 'package:flutter_easyloading/flutter_easyloading.dart';
|
||||||
@ -35,11 +36,23 @@ import '../../../blue/blue_manage.dart';
|
|||||||
import '../../../blue/io_protocol/io_openLock.dart';
|
import '../../../blue/io_protocol/io_openLock.dart';
|
||||||
import '../../../blue/io_protocol/io_referEventRecordTime.dart';
|
import '../../../blue/io_protocol/io_referEventRecordTime.dart';
|
||||||
import '../../../blue/io_reply.dart';
|
import '../../../blue/io_reply.dart';
|
||||||
|
import '../../../blue/io_sender.dart';
|
||||||
import '../../../blue/io_tool/io_tool.dart';
|
import '../../../blue/io_tool/io_tool.dart';
|
||||||
import '../../../blue/io_tool/manager_event_bus.dart';
|
import '../../../blue/io_tool/manager_event_bus.dart';
|
||||||
import '../../../blue/sender_manage.dart';
|
import '../../../blue/sender_manage.dart';
|
||||||
import '../../../network/api_repository.dart';
|
import '../../../network/api_repository.dart';
|
||||||
|
import '../../../network/start_chart_api.dart';
|
||||||
import '../../../talk/other/audio_player_manager.dart';
|
import '../../../talk/other/audio_player_manager.dart';
|
||||||
|
import '../../../talk/starChart/constant/message_type_constant.dart';
|
||||||
|
import '../../../talk/starChart/constant/payload_type_constant.dart';
|
||||||
|
import '../../../talk/starChart/constant/protocol_flag_constant.dart';
|
||||||
|
import '../../../talk/starChart/entity/scp_message.dart';
|
||||||
|
import '../../../talk/starChart/exception/start_chart_message_exception.dart';
|
||||||
|
import '../../../talk/starChart/handle/impl/udp_ble_passthrough_handler.dart';
|
||||||
|
import '../../../talk/starChart/handle/impl/udp_remote_un_lock_handler.dart';
|
||||||
|
import '../../../talk/starChart/handle/scp_message_handle.dart';
|
||||||
|
import '../../../talk/starChart/handle/scp_message_handler_factory.dart';
|
||||||
|
import '../../../talk/udp/udp_reciverData.dart';
|
||||||
import '../../../tools/baseGetXController.dart';
|
import '../../../tools/baseGetXController.dart';
|
||||||
import '../../../tools/commonDataManage.dart';
|
import '../../../tools/commonDataManage.dart';
|
||||||
import '../../../tools/dateTool.dart';
|
import '../../../tools/dateTool.dart';
|
||||||
@ -207,8 +220,9 @@ class LockDetailLogic extends BaseGetXController {
|
|||||||
signKey: signKeyDataList,
|
signKey: signKeyDataList,
|
||||||
privateKey: getPrivateKeyList,
|
privateKey: getPrivateKeyList,
|
||||||
);
|
);
|
||||||
// 只有接听状态时才可以重发开门指令
|
// 重发开门指令
|
||||||
if (StartChartManage().talkStatus.status == TalkStatus.answeredSuccessfully) {
|
if (StartChartManage().talkStatus.status == TalkStatus.answeredSuccessfully ||
|
||||||
|
StartChartManage().lockPeerId.isNotEmpty) {
|
||||||
sendStarChartOpenLockMessage(reply);
|
sendStarChartOpenLockMessage(reply);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -689,57 +703,74 @@ class LockDetailLogic extends BaseGetXController {
|
|||||||
|
|
||||||
// 远程开锁
|
// 远程开锁
|
||||||
Future<void> remoteOpenLock() async {
|
Future<void> remoteOpenLock() async {
|
||||||
|
final catEyeConfig = state.keyInfos.value.lockSetting?.catEyeConfig ?? [];
|
||||||
|
// 支持猫眼功能时,才需要判断是否是省电模式
|
||||||
|
if (state.keyInfos.value.lockFeature?.isSupportCatEye == 1 && catEyeConfig[0].catEyeMode == 0) {
|
||||||
|
showToast('猫眼设置为省电模式时无法进行远程开锁,请在猫眼设置中切换为其他模式'.tr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
final LockListInfoItemEntity currentKeyInfo = CommonDataManage().currentKeyInfo;
|
final LockListInfoItemEntity currentKeyInfo = CommonDataManage().currentKeyInfo;
|
||||||
|
|
||||||
var lockId = currentKeyInfo.lockId ?? 0;
|
var lockId = currentKeyInfo.lockId ?? 0;
|
||||||
var remoteUnlock = currentKeyInfo.lockSetting?.remoteUnlock ?? 0;
|
var remoteUnlock = currentKeyInfo.lockSetting?.remoteUnlock ?? 0;
|
||||||
|
|
||||||
final lockPeerId = StartChartManage().lockPeerId;
|
var lockPeerId = StartChartManage().lockPeerId;
|
||||||
final LockListInfoGroupEntity? lockListInfoGroupEntity = await Storage.getLockMainListData();
|
|
||||||
|
|
||||||
//检查蓝牙连接状态
|
if (lockPeerId.isEmpty) {
|
||||||
final connectedDevices = await FlutterBluePlus.connectedDevices;
|
final network = currentKeyInfo.network;
|
||||||
final isDeviceConnected = connectedDevices.any((device) =>
|
if (network != null && network.peerId != null && network.peerId!.isNotEmpty) {
|
||||||
device.remoteId.str == BlueManage().connectDeviceName);
|
lockPeerId = network.peerId!;
|
||||||
|
StartChartManage().lockPeerId = lockPeerId;
|
||||||
if (!isDeviceConnected) {
|
}
|
||||||
AppLog.log('蓝牙已断开,尝试重新连接');
|
|
||||||
// 蓝牙断开,需要重新连接并获取新的token
|
|
||||||
await _reconnectAndRefreshToken();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lockListInfoGroupEntity != null) {
|
|
||||||
lockListInfoGroupEntity!.groupList?.forEach((element) {
|
|
||||||
final lockList = element.lockList;
|
|
||||||
if (lockList != null && lockList.length != 0) {
|
|
||||||
for (var lockInfo in lockList) {
|
|
||||||
final peerId = lockInfo.network?.peerId;
|
|
||||||
if (peerId != null && peerId != '') {
|
|
||||||
if (peerId == lockPeerId) {
|
|
||||||
lockId = lockInfo.lockId ?? 0;
|
|
||||||
remoteUnlock = lockInfo.lockSetting?.remoteUnlock ?? 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (remoteUnlock == 1) {
|
if (remoteUnlock == 1) {
|
||||||
// 发送蓝牙透传开锁
|
try {
|
||||||
await _sendUnlockViaBluetooth();
|
if (lockPeerId.isEmpty) {
|
||||||
// 发送远程开锁api
|
AppLog.log('远程服务未连接,无法进行远程开锁');
|
||||||
final LoginEntity entity = await ApiRepository.to.remoteOpenLock(lockId: lockId.toString(), timeOut: 60);
|
return;
|
||||||
if (entity.errorCode!.codeIsSuccessful) {
|
}
|
||||||
showToast('已开锁'.tr);
|
|
||||||
StartChartManage().lockListPeerId = [];
|
final response = await StartChartApi.to.analyzeInformationOtherEnd(peerId: lockPeerId);
|
||||||
|
if (response.statusCode == 200) {
|
||||||
|
AppLog.log('成功分析对端信息');
|
||||||
|
} else {
|
||||||
|
AppLog.log('分析对端信息失败,状态码: ${response.statusCode}');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 判断是否为WiFi锁
|
||||||
|
final network = currentKeyInfo.network;
|
||||||
|
if (network != null && (network.peerId != null && network.peerId!.isNotEmpty)){
|
||||||
|
// 发送蓝牙透传开锁指令
|
||||||
|
await _sendUnlockViaBluetooth();
|
||||||
|
} else {
|
||||||
|
// 发送远程开锁API
|
||||||
|
final LoginEntity entity = await ApiRepository.to.remoteOpenLock(lockId: lockId.toString(), timeOut: 60);
|
||||||
|
if (entity.errorCode!.codeIsSuccessful) {
|
||||||
|
showToast('已开锁'.tr);
|
||||||
|
StartChartManage().lockListPeerId = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
AppLog.log('远程开锁失败: $e');
|
||||||
|
showToast('远程开锁失败'.tr);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
AppLog.log('该锁的远程开锁功能未启用');
|
||||||
|
showToast('该锁的远程开锁功能未启用'.tr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 新增方法:通过蓝牙透传发送开锁命令
|
// 通过蓝牙透传发送开锁命令
|
||||||
Future<void> _sendUnlockViaBluetooth() async {
|
Future<void> _sendUnlockViaBluetooth() async {
|
||||||
try {
|
try {
|
||||||
|
// 验证当前连接的设备是否为目标设备
|
||||||
|
final String targetDeviceName = state.keyInfos.value.bluetooth!.bluetoothDeviceName!;
|
||||||
|
final String currentConnectedDevice = BlueManage().connectDeviceName;
|
||||||
|
|
||||||
|
if (targetDeviceName != currentConnectedDevice) {
|
||||||
|
AppLog.log('目标设备与当前连接设备不匹配,目标: $targetDeviceName, 当前: $currentConnectedDevice');
|
||||||
|
}
|
||||||
// 获取必要的密钥信息
|
// 获取必要的密钥信息
|
||||||
final List<String>? privateKey = await Storage.getStringList(saveBluePrivateKey);
|
final List<String>? privateKey = await Storage.getStringList(saveBluePrivateKey);
|
||||||
final List<int> privateKeyList = changeStringListToIntList(privateKey!);
|
final List<int> privateKeyList = changeStringListToIntList(privateKey!);
|
||||||
@ -750,10 +781,23 @@ class LockDetailLogic extends BaseGetXController {
|
|||||||
final List<String>? token = await Storage.getStringList(saveBlueToken);
|
final List<String>? token = await Storage.getStringList(saveBlueToken);
|
||||||
final List<int> tokenList = changeStringListToIntList(token!);
|
final List<int> tokenList = changeStringListToIntList(token!);
|
||||||
|
|
||||||
|
// 获取连接的设备名称
|
||||||
|
final String bluetoothDeviceName = BlueManage().connectDeviceName;
|
||||||
|
if (bluetoothDeviceName.isEmpty) {
|
||||||
|
throw Exception('未找到连接的蓝牙设备');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取用户ID
|
||||||
|
final String? userID = await Storage.getUid();
|
||||||
|
if (userID == null || userID.isEmpty) {
|
||||||
|
throw Exception('未找到用户ID');
|
||||||
|
}
|
||||||
|
AppLog.log('用户ID: $userID');
|
||||||
|
|
||||||
// 构建开锁命令
|
// 构建开锁命令
|
||||||
final OpenLockCommand openLockCommand = OpenLockCommand(
|
final OpenLockCommand openLockCommand = OpenLockCommand(
|
||||||
lockID: BlueManage().connectDeviceName,
|
lockID: bluetoothDeviceName,
|
||||||
userID: await Storage.getUid(),
|
userID: userID,
|
||||||
openMode: state.openDoorModel,
|
openMode: state.openDoorModel,
|
||||||
openTime: getUTCNetTime(),
|
openTime: getUTCNetTime(),
|
||||||
onlineToken: state.lockNetToken,
|
onlineToken: state.lockNetToken,
|
||||||
@ -762,151 +806,20 @@ class LockDetailLogic extends BaseGetXController {
|
|||||||
signKey: signKeyList,
|
signKey: signKeyList,
|
||||||
privateKey: privateKeyList,
|
privateKey: privateKeyList,
|
||||||
);
|
);
|
||||||
|
AppLog.log('构建开锁命令成功');
|
||||||
|
|
||||||
// 包装命令数据
|
// 包装命令数据
|
||||||
final List<int> messageDetail = openLockCommand.packageData();
|
final List<int> messageDetail = openLockCommand.packageData();
|
||||||
|
|
||||||
// 通过蓝牙透传发送开锁命令
|
// 发送蓝牙透传开锁命令
|
||||||
StartChartManage().sendRemoteUnLockMessage(
|
StartChartManage().sendRemoteUnLockMessage(
|
||||||
bluetoothDeviceName: BlueManage().connectDeviceName,
|
bluetoothDeviceName: bluetoothDeviceName,
|
||||||
openLockCommand: messageDetail,
|
openLockCommand: messageDetail,
|
||||||
);
|
);
|
||||||
|
AppLog.log('蓝牙透传开锁命令已发送到设备: $bluetoothDeviceName');
|
||||||
AppLog.log('通过蓝牙透传发送远程开锁命令');
|
|
||||||
|
|
||||||
// 监听开锁结果,处理token不一致的情况
|
|
||||||
_listenForOpenLockReply(tokenList);
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
AppLog.log('蓝牙透传开锁异常: $e');
|
AppLog.log('蓝牙透传开锁异常: $e');
|
||||||
showToast('蓝牙透传开锁失败'.tr);
|
rethrow;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 监听开锁回复,处理token验证
|
|
||||||
void _listenForOpenLockReply(List<int> originalToken) {
|
|
||||||
StreamSubscription<Reply>? subscription;
|
|
||||||
// 设置监听器处理开锁回复
|
|
||||||
subscription = EventBusManager().eventBus!.on<Reply>().listen((Reply reply) async {
|
|
||||||
if (reply is OpenDoorReply) {
|
|
||||||
final int status = reply.data[6];
|
|
||||||
|
|
||||||
// 如果是token不一致的情况(状态码0x06)
|
|
||||||
if (status == 0x06) {
|
|
||||||
AppLog.log('token不一致,使用新token重新开锁');
|
|
||||||
|
|
||||||
// 提取新的token
|
|
||||||
final List<int> newToken = reply.data.sublist(2, 6);
|
|
||||||
|
|
||||||
// 保存新token到存储
|
|
||||||
final List<String> saveStrList = changeIntListToStringList(newToken);
|
|
||||||
Storage.setStringList(saveBlueToken, saveStrList);
|
|
||||||
|
|
||||||
// 使用新token重新发送开锁命令
|
|
||||||
await _reSendUnlockWithNewToken(newToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 取消监听
|
|
||||||
subscription?.cancel();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// 设置超时机制,避免监听器一直存在
|
|
||||||
Timer(const Duration(seconds: 10), () {
|
|
||||||
subscription?.cancel();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 使用新token重新发送开锁命令
|
|
||||||
Future<void> _reSendUnlockWithNewToken(List<int> newToken) async {
|
|
||||||
try {
|
|
||||||
// 获取必要的密钥信息
|
|
||||||
final List<String>? privateKey = await Storage.getStringList(saveBluePrivateKey);
|
|
||||||
final List<int> privateKeyList = changeStringListToIntList(privateKey!);
|
|
||||||
|
|
||||||
final List<String>? signKey = await Storage.getStringList(saveBlueSignKey);
|
|
||||||
final List<int> signKeyList = changeStringListToIntList(signKey!);
|
|
||||||
|
|
||||||
// 构建新的开锁命令
|
|
||||||
final OpenLockCommand openLockCommand = OpenLockCommand(
|
|
||||||
lockID: BlueManage().connectDeviceName,
|
|
||||||
userID: await Storage.getUid(),
|
|
||||||
openMode: state.openDoorModel,
|
|
||||||
openTime: getUTCNetTime(),
|
|
||||||
onlineToken: state.lockNetToken,
|
|
||||||
token: newToken,
|
|
||||||
needAuthor: 1,
|
|
||||||
signKey: signKeyList,
|
|
||||||
privateKey: privateKeyList,
|
|
||||||
);
|
|
||||||
|
|
||||||
// 包装命令数据
|
|
||||||
final List<int> messageDetail = openLockCommand.packageData();
|
|
||||||
|
|
||||||
// 通过蓝牙透传发送开锁命令
|
|
||||||
StartChartManage().sendRemoteUnLockMessage(
|
|
||||||
bluetoothDeviceName: BlueManage().connectDeviceName,
|
|
||||||
openLockCommand: messageDetail,
|
|
||||||
);
|
|
||||||
|
|
||||||
AppLog.log('使用新token重新发送开锁命令');
|
|
||||||
} catch (e) {
|
|
||||||
AppLog.log('使用新token重新开锁异常: $e');
|
|
||||||
showToast('重新开锁失败'.tr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 新增方法:重新连接蓝牙并刷新token
|
|
||||||
Future<void> _reconnectAndRefreshToken() async {
|
|
||||||
try {
|
|
||||||
// 重新连接蓝牙
|
|
||||||
await BlueManage().blueSendData(
|
|
||||||
state.keyInfos.value.bluetooth!.bluetoothDeviceName!,
|
|
||||||
(BluetoothConnectionState deviceConnectionState) async {
|
|
||||||
if (deviceConnectionState == BluetoothConnectionState.connected) {
|
|
||||||
AppLog.log('蓝牙重新连接成功');
|
|
||||||
// 获取新的token
|
|
||||||
await _refreshLockToken();
|
|
||||||
} else if (deviceConnectionState == BluetoothConnectionState.disconnected) {
|
|
||||||
AppLog.log('蓝牙重新连接失败');
|
|
||||||
showToast('蓝牙连接失败,请重试'.tr);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
);
|
|
||||||
} catch (e) {
|
|
||||||
AppLog.log('蓝牙重连异常: $e');
|
|
||||||
showToast('蓝牙连接异常,请重试'.tr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 新增方法:刷新锁token
|
|
||||||
Future<void> _refreshLockToken() async {
|
|
||||||
try {
|
|
||||||
final List<String>? token = await Storage.getStringList(saveBlueToken);
|
|
||||||
final List<int> tokenList = changeStringListToIntList(token!);
|
|
||||||
|
|
||||||
final List<String>? privateKey = await Storage.getStringList(saveBluePrivateKey);
|
|
||||||
final List<int> privateKeyList = changeStringListToIntList(privateKey!);
|
|
||||||
|
|
||||||
final List<String>? signKey = await Storage.getStringList(saveBlueSignKey);
|
|
||||||
final List<int> signKeyList = changeStringListToIntList(signKey!);
|
|
||||||
|
|
||||||
// 发送获取新token的命令
|
|
||||||
IoSenderManage.senderOpenLock(
|
|
||||||
lockID: BlueManage().connectDeviceName,
|
|
||||||
userID: await Storage.getUid(),
|
|
||||||
openMode: state.openDoorModel,
|
|
||||||
openTime: getUTCNetTime(),
|
|
||||||
onlineToken: state.lockNetToken,
|
|
||||||
token: tokenList,
|
|
||||||
needAuthor: 1,
|
|
||||||
signKey: signKeyList,
|
|
||||||
privateKey: privateKeyList,
|
|
||||||
);
|
|
||||||
|
|
||||||
// 等待一段时间让token更新完成
|
|
||||||
await Future.delayed(Duration(milliseconds: 500));
|
|
||||||
} catch (e) {
|
|
||||||
AppLog.log('刷新token异常: $e');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -695,9 +695,9 @@ class _LockDetailPageState extends State<LockDetailPage> with TickerProviderStat
|
|||||||
child: GestureDetector(
|
child: GestureDetector(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
ShowCupertinoAlertView().isToRemoteUnLockAlert(remoteUnlockAction: () {
|
ShowCupertinoAlertView().isToRemoteUnLockAlert(remoteUnlockAction: () {
|
||||||
if (state.keyInfos.value.hasGateway != 1) {
|
// if (state.keyInfos.value.hasGateway != 1) {
|
||||||
logic.showToast('附近没有可用网关'.tr);
|
// logic.showToast('附近没有可用网关'.tr);
|
||||||
}
|
// }
|
||||||
logic.remoteOpenLock();
|
logic.remoteOpenLock();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|||||||
@ -191,7 +191,7 @@ class ConfiguringWifiLogic extends BaseGetXController {
|
|||||||
state.lockSetInfoData.value?.lockBasicInfo?.networkInfo?.wifiName =
|
state.lockSetInfoData.value?.lockBasicInfo?.networkInfo?.wifiName =
|
||||||
wifiName;
|
wifiName;
|
||||||
state.lockSetInfoData.value?.lockBasicInfo?.networkInfo?.rssi =
|
state.lockSetInfoData.value?.lockBasicInfo?.networkInfo?.rssi =
|
||||||
rssi as int?;
|
rssi;
|
||||||
|
|
||||||
/// 配网成功后,赋值锁的peerId
|
/// 配网成功后,赋值锁的peerId
|
||||||
StartChartManage().lockPeerId = peerId;
|
StartChartManage().lockPeerId = peerId;
|
||||||
|
|||||||
@ -79,14 +79,6 @@ class _ConfiguringWifiPageState extends State<ConfiguringWifiPage>
|
|||||||
SizedBox(
|
SizedBox(
|
||||||
height: 20.h,
|
height: 20.h,
|
||||||
),
|
),
|
||||||
Text(
|
|
||||||
'请确保网络是2.4GHz Wi-Fi'.tr,
|
|
||||||
style: TextStyle(
|
|
||||||
color: AppColors.blackColor,
|
|
||||||
fontSize: 20.sp,
|
|
||||||
fontWeight: FontWeight.w500,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1074,6 +1074,7 @@ class StartChartManage {
|
|||||||
void _handleUdpResultData(ScpMessage scpMessage) {
|
void _handleUdpResultData(ScpMessage scpMessage) {
|
||||||
final int payloadType = scpMessage.PayloadType ?? 0;
|
final int payloadType = scpMessage.PayloadType ?? 0;
|
||||||
final int messageType = scpMessage.MessageType ?? 0;
|
final int messageType = scpMessage.MessageType ?? 0;
|
||||||
|
AppLog.log('payloadType:$payloadType,messageType:$messageType');
|
||||||
// 添加开锁回应的日志打印
|
// 添加开锁回应的日志打印
|
||||||
if (payloadType == PayloadTypeConstant.remoteUnlock) {
|
if (payloadType == PayloadTypeConstant.remoteUnlock) {
|
||||||
AppLog.log('收到蓝牙设备回应消息,${scpMessage.PayloadType}');
|
AppLog.log('收到蓝牙设备回应消息,${scpMessage.PayloadType}');
|
||||||
|
|||||||
@ -58,6 +58,12 @@ class TalkViewNativeDecodeLogic extends BaseGetXController {
|
|||||||
List<int>? _cachedPps;
|
List<int>? _cachedPps;
|
||||||
bool _waitingForCompleteIFrame = false;
|
bool _waitingForCompleteIFrame = false;
|
||||||
|
|
||||||
|
/// 状态变更防抖时间(毫秒)
|
||||||
|
static const int STATUS_DEBOUNCE_TIME = 500;
|
||||||
|
|
||||||
|
/// 上次状态变更时间戳
|
||||||
|
int _lastStatusChangeTime = 0;
|
||||||
|
|
||||||
int _frameProcessCount = 0;
|
int _frameProcessCount = 0;
|
||||||
int _lastFrameProcessTime = 0;
|
int _lastFrameProcessTime = 0;
|
||||||
double _actualFps = 0.0;
|
double _actualFps = 0.0;
|
||||||
@ -833,6 +839,14 @@ class TalkViewNativeDecodeLogic extends BaseGetXController {
|
|||||||
/// 监听对讲状态
|
/// 监听对讲状态
|
||||||
void _startListenTalkStatus() {
|
void _startListenTalkStatus() {
|
||||||
state.startChartTalkStatus.statusStream.listen((talkStatus) {
|
state.startChartTalkStatus.statusStream.listen((talkStatus) {
|
||||||
|
// 防抖处理:检查距离上次状态变更的时间间隔
|
||||||
|
final int currentTime = DateTime.now().millisecondsSinceEpoch;
|
||||||
|
if (currentTime - _lastStatusChangeTime < STATUS_DEBOUNCE_TIME) {
|
||||||
|
AppLog.log('状态变更过于频繁,忽略此次变更: $talkStatus');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 更新上次状态变更时间
|
||||||
|
_lastStatusChangeTime = currentTime;
|
||||||
state.talkStatus.value = talkStatus;
|
state.talkStatus.value = talkStatus;
|
||||||
switch (talkStatus) {
|
switch (talkStatus) {
|
||||||
case TalkStatus.rejected:
|
case TalkStatus.rejected:
|
||||||
@ -865,13 +879,9 @@ class TalkViewNativeDecodeLogic extends BaseGetXController {
|
|||||||
final PcmArrayInt16 fromList = PcmArrayInt16.fromList(encodedData);
|
final PcmArrayInt16 fromList = PcmArrayInt16.fromList(encodedData);
|
||||||
FlutterPcmSound.feed(fromList);
|
FlutterPcmSound.feed(fromList);
|
||||||
if (!state.isPlaying.value) {
|
if (!state.isPlaying.value) {
|
||||||
AppLog.log('play');
|
|
||||||
FlutterPcmSound.play();
|
FlutterPcmSound.play();
|
||||||
state.isPlaying.value = true;
|
state.isPlaying.value = true;
|
||||||
}
|
}
|
||||||
} else if (state.isOpenVoice.isFalse) {
|
|
||||||
FlutterPcmSound.pause();
|
|
||||||
state.isPlaying.value = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -39,29 +39,32 @@ class _TalkViewNativeDecodePageState extends State<TalkViewNativeDecodePage> wit
|
|||||||
final TalkViewNativeDecodeState state = Get.find<TalkViewNativeDecodeLogic>().state;
|
final TalkViewNativeDecodeState state = Get.find<TalkViewNativeDecodeLogic>().state;
|
||||||
final startChartManage = StartChartManage();
|
final startChartManage = StartChartManage();
|
||||||
|
|
||||||
|
late AnimationController _animationController; // 改为本地变量
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
|
||||||
state.animationController = AnimationController(
|
_animationController = AnimationController( // 使用本地变量
|
||||||
vsync: this, // 确保使用的TickerProvider是当前Widget
|
vsync: this,
|
||||||
duration: const Duration(seconds: 1),
|
duration: const Duration(seconds: 1),
|
||||||
);
|
);
|
||||||
|
|
||||||
state.animationController.repeat();
|
state.animationController = _animationController; // 同步到状态
|
||||||
// 添加帧回调以优化动画性能
|
|
||||||
|
_animationController.repeat();
|
||||||
|
|
||||||
SchedulerBinding.instance.addPostFrameCallback((_) {
|
SchedulerBinding.instance.addPostFrameCallback((_) {
|
||||||
// 确保动画在合适的帧率下运行
|
_animationController.duration = const Duration(milliseconds: 500);
|
||||||
state.animationController.duration = const Duration(milliseconds: 500);
|
|
||||||
});
|
});
|
||||||
//动画开始、结束、向前移动或向后移动时会调用StatusListener
|
|
||||||
state.animationController.addStatusListener((AnimationStatus status) {
|
_animationController.addStatusListener((AnimationStatus status) {
|
||||||
if (status == AnimationStatus.completed) {
|
if (status == AnimationStatus.completed) {
|
||||||
state.animationController.reset();
|
_animationController.reset();
|
||||||
state.animationController.forward();
|
_animationController.forward();
|
||||||
} else if (status == AnimationStatus.dismissed) {
|
} else if (status == AnimationStatus.dismissed) {
|
||||||
state.animationController.reset();
|
_animationController.reset();
|
||||||
state.animationController.forward();
|
_animationController.forward();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -360,9 +363,12 @@ class _TalkViewNativeDecodePageState extends State<TalkViewNativeDecodePage> wit
|
|||||||
state.isLongPressing.value = false;
|
state.isLongPressing.value = false;
|
||||||
},
|
},
|
||||||
onClick: () async {
|
onClick: () async {
|
||||||
|
// 只有在被动呼叫等待接听状态下才允许接听操作
|
||||||
if (state.talkStatus.value == TalkStatus.passiveCallWaitingAnswer) {
|
if (state.talkStatus.value == TalkStatus.passiveCallWaitingAnswer) {
|
||||||
// 接听
|
// 确保不是监控模式下调用
|
||||||
logic.initiateAnswerCommand();
|
if (!state.isMonitoringMode()) {
|
||||||
|
logic.initiateAnswerCommand();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@ -393,6 +399,10 @@ class _TalkViewNativeDecodePageState extends State<TalkViewNativeDecodePage> wit
|
|||||||
}
|
}
|
||||||
|
|
||||||
String getAnswerBtnImg() {
|
String getAnswerBtnImg() {
|
||||||
|
// 如果是监控模式,始终显示对讲按钮
|
||||||
|
if (state.isMonitoringMode.value) {
|
||||||
|
return 'images/main/icon_lockDetail_monitoringUnTalkback.png';
|
||||||
|
}
|
||||||
switch (state.talkStatus.value) {
|
switch (state.talkStatus.value) {
|
||||||
case TalkStatus.passiveCallWaitingAnswer:
|
case TalkStatus.passiveCallWaitingAnswer:
|
||||||
return 'images/main/icon_lockDetail_monitoringAnswerCalls.png';
|
return 'images/main/icon_lockDetail_monitoringAnswerCalls.png';
|
||||||
@ -405,6 +415,10 @@ class _TalkViewNativeDecodePageState extends State<TalkViewNativeDecodePage> wit
|
|||||||
}
|
}
|
||||||
|
|
||||||
String getAnswerBtnName() {
|
String getAnswerBtnName() {
|
||||||
|
// 如果是监控模式,显示对讲相关文本
|
||||||
|
if (state.isMonitoringMode.value) {
|
||||||
|
return '长按说话'.tr;
|
||||||
|
}
|
||||||
switch (state.talkStatus.value) {
|
switch (state.talkStatus.value) {
|
||||||
case TalkStatus.passiveCallWaitingAnswer:
|
case TalkStatus.passiveCallWaitingAnswer:
|
||||||
return '接听'.tr;
|
return '接听'.tr;
|
||||||
@ -506,8 +520,11 @@ class _TalkViewNativeDecodePageState extends State<TalkViewNativeDecodePage> wit
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
state.animationController.dispose();
|
|
||||||
CallTalk().finishAVData();
|
CallTalk().finishAVData();
|
||||||
|
|
||||||
|
// 只处理本地的 animation controller
|
||||||
|
_animationController.dispose();
|
||||||
|
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -129,4 +129,7 @@ class TalkViewNativeDecodeState {
|
|||||||
|
|
||||||
// 是否拉伸至全屏
|
// 是否拉伸至全屏
|
||||||
RxBool isFullScreen = false.obs;
|
RxBool isFullScreen = false.obs;
|
||||||
|
|
||||||
|
//添加监控模式标识
|
||||||
|
final RxBool isMonitoringMode = false.obs;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user