1.优化注册切出去再回来问题
2.视频对讲优化 3.图传-视频对讲切出去再回来无法接听 4.优化远程开锁--使用蓝牙透传--判断蓝牙状态
This commit is contained in:
parent
d3969b6ba5
commit
b97d7006b3
@ -1,13 +1,8 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:star_lock/flavors.dart';
|
||||
import 'package:star_lock/login/login/starLock_login_state.dart';
|
||||
import 'package:star_lock/talk/starChart/handle/impl/udp_talk_ping_handler.dart';
|
||||
import 'package:star_lock/talk/starChart/star_chart_manage.dart';
|
||||
import 'package:star_lock/tools/appFirstEnterHandle.dart';
|
||||
import 'package:star_lock/tools/storage.dart';
|
||||
import 'package:star_lock/tools/wechat/customer_tool.dart';
|
||||
@ -16,7 +11,6 @@ import '../../appRouters.dart';
|
||||
import '../../app_settings/app_colors.dart';
|
||||
import '../../common/XSConstantMacro/XSConstantMacro.dart';
|
||||
import '../../tools/commonItem.dart';
|
||||
import '../../tools/jverify_one_click_login.dart';
|
||||
import '../../tools/submitBtn.dart';
|
||||
import '../../tools/tf_loginInput.dart';
|
||||
import '../../tools/titleAppBar.dart';
|
||||
@ -193,6 +187,7 @@ class _StarLockLoginPageState extends State<StarLockLoginPage> {
|
||||
inputFormatters: <TextInputFormatter>[
|
||||
LengthLimitingTextInputFormatter(20),
|
||||
]),
|
||||
_agreentWidget(),
|
||||
SizedBox(height: 50.w),
|
||||
Obx(() => SubmitBtn(
|
||||
btnName: '登录'.tr,
|
||||
@ -234,7 +229,7 @@ class _StarLockLoginPageState extends State<StarLockLoginPage> {
|
||||
|
||||
Widget _agreentWidget() {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
Obx(() => GestureDetector(
|
||||
onTap: () {
|
||||
|
||||
@ -25,10 +25,10 @@ import 'starLock_register_state.dart';
|
||||
class StarLockRegisterLogic extends BaseGetXController {
|
||||
final StarLockRegisterState state = StarLockRegisterState();
|
||||
|
||||
late Timer _timer;
|
||||
Timer? _timer;
|
||||
|
||||
void _startTimer() {
|
||||
_timer = Timer.periodic(1.seconds, (Timer timer) {
|
||||
_timer = Timer.periodic(const Duration(seconds: 1), (Timer timer) {
|
||||
if (state.currentSecond > 1) {
|
||||
state.currentSecond--;
|
||||
} else {
|
||||
@ -40,7 +40,8 @@ class StarLockRegisterLogic extends BaseGetXController {
|
||||
}
|
||||
|
||||
void _cancelTimer() {
|
||||
_timer.cancel();
|
||||
_timer?.cancel();
|
||||
_timer = null;
|
||||
// _timer = null;
|
||||
}
|
||||
|
||||
@ -162,4 +163,27 @@ class StarLockRegisterLogic extends BaseGetXController {
|
||||
|
||||
await checkIpAction();
|
||||
}
|
||||
|
||||
void clearInputData() {
|
||||
// 清除手机号/邮箱输入框
|
||||
state.phoneOrEmailController.clear();
|
||||
state.phoneOrEmailStr.value = '';
|
||||
|
||||
// 清除密码输入框
|
||||
state.pwdController.clear();
|
||||
state.pwd.value = '';
|
||||
|
||||
// 清除确认密码输入框
|
||||
state.sureController.clear();
|
||||
state.surePwd.value = '';
|
||||
|
||||
// 清除验证码输入框
|
||||
state.codeController.clear();
|
||||
state.verificationCode.value = '';
|
||||
|
||||
// 安全地重置验证码倒计时
|
||||
_cancelTimer();
|
||||
state.currentSecond = state.totalSeconds;
|
||||
state.resetResend();
|
||||
}
|
||||
}
|
||||
|
||||
@ -89,7 +89,12 @@ class _StarLockRegisterPageState extends State<StarLockRegisterPage> {
|
||||
children: <Widget>[
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
// 切换到手机号输入前先清除数据
|
||||
if (!state.isIphoneType.value) {
|
||||
logic.clearInputData();
|
||||
}
|
||||
state.isIphoneType.value = true;
|
||||
FocusScope.of(context).unfocus();
|
||||
},
|
||||
child: Obx(
|
||||
() => Container(
|
||||
@ -113,6 +118,11 @@ class _StarLockRegisterPageState extends State<StarLockRegisterPage> {
|
||||
Expanded(
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
// 切换到邮箱输入前先清除数据
|
||||
if (state.isIphoneType.value) {
|
||||
logic.clearInputData();
|
||||
FocusScope.of(context).unfocus();
|
||||
}
|
||||
state.isIphoneType.value = false;
|
||||
},
|
||||
child: Obx(
|
||||
|
||||
@ -696,6 +696,18 @@ class LockDetailLogic extends BaseGetXController {
|
||||
|
||||
final lockPeerId = StartChartManage().lockPeerId;
|
||||
final LockListInfoGroupEntity? lockListInfoGroupEntity = await Storage.getLockMainListData();
|
||||
|
||||
//检查蓝牙连接状态
|
||||
final connectedDevices = await FlutterBluePlus.connectedDevices;
|
||||
final isDeviceConnected = connectedDevices.any((device) =>
|
||||
device.remoteId.str == BlueManage().connectDeviceName);
|
||||
|
||||
if (!isDeviceConnected) {
|
||||
AppLog.log('蓝牙已断开,尝试重新连接');
|
||||
// 蓝牙断开,需要重新连接并获取新的token
|
||||
await _reconnectAndRefreshToken();
|
||||
}
|
||||
|
||||
if (lockListInfoGroupEntity != null) {
|
||||
lockListInfoGroupEntity!.groupList?.forEach((element) {
|
||||
final lockList = element.lockList;
|
||||
@ -712,7 +724,11 @@ class LockDetailLogic extends BaseGetXController {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (remoteUnlock == 1) {
|
||||
// 发送蓝牙透传开锁
|
||||
await _sendUnlockViaBluetooth();
|
||||
// 发送远程开锁api
|
||||
final LoginEntity entity = await ApiRepository.to.remoteOpenLock(lockId: lockId.toString(), timeOut: 60);
|
||||
if (entity.errorCode!.codeIsSuccessful) {
|
||||
showToast('已开锁'.tr);
|
||||
@ -721,6 +737,179 @@ class LockDetailLogic extends BaseGetXController {
|
||||
}
|
||||
}
|
||||
|
||||
// 新增方法:通过蓝牙透传发送开锁命令
|
||||
Future<void> _sendUnlockViaBluetooth() 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 List<String>? token = await Storage.getStringList(saveBlueToken);
|
||||
final List<int> tokenList = changeStringListToIntList(token!);
|
||||
|
||||
// 构建开锁命令
|
||||
final OpenLockCommand openLockCommand = OpenLockCommand(
|
||||
lockID: BlueManage().connectDeviceName,
|
||||
userID: await Storage.getUid(),
|
||||
openMode: state.openDoorModel,
|
||||
openTime: getUTCNetTime(),
|
||||
onlineToken: state.lockNetToken,
|
||||
token: tokenList,
|
||||
needAuthor: 1,
|
||||
signKey: signKeyList,
|
||||
privateKey: privateKeyList,
|
||||
);
|
||||
|
||||
// 包装命令数据
|
||||
final List<int> messageDetail = openLockCommand.packageData();
|
||||
|
||||
// 通过蓝牙透传发送开锁命令
|
||||
StartChartManage().sendRemoteUnLockMessage(
|
||||
bluetoothDeviceName: BlueManage().connectDeviceName,
|
||||
openLockCommand: messageDetail,
|
||||
);
|
||||
|
||||
AppLog.log('通过蓝牙透传发送远程开锁命令');
|
||||
|
||||
// 监听开锁结果,处理token不一致的情况
|
||||
_listenForOpenLockReply(tokenList);
|
||||
} catch (e) {
|
||||
AppLog.log('蓝牙透传开锁异常: $e');
|
||||
showToast('蓝牙透传开锁失败'.tr);
|
||||
}
|
||||
}
|
||||
|
||||
// 监听开锁回复,处理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');
|
||||
}
|
||||
}
|
||||
|
||||
/// 锁设置里面开启关闭考勤刷新锁详情
|
||||
void initLockSetOpenOrCloseCheckInRefreshLockDetailWithAttendanceAction() {
|
||||
// 蓝牙协议通知传输跟蓝牙之外的数据传输类不一样 eventBus
|
||||
|
||||
@ -161,6 +161,18 @@ class StartChartManage {
|
||||
await reportInformation();
|
||||
}
|
||||
|
||||
// 优化连接建立
|
||||
Future<void> establishConnection({required String ToPeerId}) async {
|
||||
// 提前预加载必要资源
|
||||
await init(); // 确保基础服务已初始化
|
||||
|
||||
// 并行执行地址交换和打洞
|
||||
await Future.wait([
|
||||
startSendingRbcuInfoMessages(ToPeerId: ToPeerId),
|
||||
startSendingRbcuProbeTMessages(),
|
||||
] as Iterable<Future>);
|
||||
}
|
||||
|
||||
/// 客户端注册
|
||||
Future<void> _clientRegister(LoginData? loginData) async {
|
||||
if (loginData?.starchart?.starchartId != null) {
|
||||
@ -457,7 +469,7 @@ class StartChartManage {
|
||||
// 启动定时器持续发送对讲请求
|
||||
talkRequestTimer ??= Timer.periodic(
|
||||
Duration(
|
||||
seconds: _defaultIntervalTime,
|
||||
milliseconds: 500,
|
||||
),
|
||||
(Timer timer) async {
|
||||
AppLog.log('发送对讲请求:${ToPeerId}');
|
||||
@ -719,7 +731,14 @@ class StartChartManage {
|
||||
FromPeerId: FromPeerId,
|
||||
MessageId: MessageCommand.getNextMessageId(ToPeerId, increment: true),
|
||||
);
|
||||
await _sendMessage(message: message);
|
||||
try {
|
||||
await _sendMessage(message: message);
|
||||
} catch (e) {
|
||||
// 记录日志但不中断程序执行
|
||||
AppLog.log('发送挂断消息失败: $e');
|
||||
// 不抛出异常,避免应用崩溃
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 发送通话中挂断消息
|
||||
@ -800,9 +819,16 @@ class StartChartManage {
|
||||
// 发送消息
|
||||
Future<void> _sendMessage({required List<int> message}) async {
|
||||
var result = await _udpSocket?.send(message, InternetAddress(remoteHost), remotePort);
|
||||
if (result != message.length) {
|
||||
throw StartChartMessageException('❌Udp send data error----> $result ${message.length}');
|
||||
// _udpSocket = null;
|
||||
// 在对讲管理类中完善异常处理
|
||||
try {
|
||||
// UDP发送逻辑
|
||||
} catch (e) {
|
||||
// 记录错误但不影响主流程
|
||||
if (result != message.length) {
|
||||
throw StartChartMessageException('❌Udp send data error----> $result ${message.length}');
|
||||
// _udpSocket = null;
|
||||
}
|
||||
print('对讲消息发送失败: $e');
|
||||
}
|
||||
|
||||
//ToDo: 增加对讲调试、正式可删除
|
||||
|
||||
@ -68,9 +68,10 @@ class AppLifecycleObserver extends WidgetsBindingObserver {
|
||||
status == TalkStatus.proactivelyCallWaitingAnswer ||
|
||||
status == TalkStatus.answeredSuccessfully ||
|
||||
status == TalkStatus.uninitialized) {
|
||||
Get.back();
|
||||
// Get.back(); // 避免返回上一页的操作,避免影响注册页
|
||||
}
|
||||
StartChartManage().destruction();
|
||||
// 不进行对讲资源清理,避免切出去回来无法接听
|
||||
// StartChartManage().destruction();
|
||||
_readMessageRefreshUIEvent?.cancel();
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user