fix:完善对讲流程、增加蓝牙透传消息指令

This commit is contained in:
liyi 2025-01-08 09:14:29 +08:00
parent c16c9be4c6
commit 92fcf4a4fa
29 changed files with 581 additions and 192 deletions

View File

@ -12,7 +12,7 @@ import 'package:star_lock/mine/about/debug/debug_tool.dart';
import 'package:star_lock/network/api_provider.dart'; import 'package:star_lock/network/api_provider.dart';
import 'package:star_lock/network/api_repository.dart'; import 'package:star_lock/network/api_repository.dart';
import 'package:star_lock/network/start_chart_api.dart'; import 'package:star_lock/network/start_chart_api.dart';
import 'package:star_lock/talk/startChart/appLifecycle_observer.dart'; import 'package:star_lock/talk/startChart/status/appLifecycle_observer.dart';
import 'package:star_lock/tools/bugly/bugly_tool.dart'; import 'package:star_lock/tools/bugly/bugly_tool.dart';
import 'package:star_lock/tools/device_info_service.dart'; import 'package:star_lock/tools/device_info_service.dart';
import 'package:star_lock/tools/platform_info_services.dart'; import 'package:star_lock/tools/platform_info_services.dart';

View File

@ -21,7 +21,7 @@ class CatEyeSetLogic extends BaseGetXController {
} }
} }
// //
Future<void> updateLightScreenTimeConfig() async { Future<void> updateLightScreenTimeConfig() async {
final VersionUndateEntity entity = await ApiRepository.to.updateLightScreenTimeConfig( final VersionUndateEntity entity = await ApiRepository.to.updateLightScreenTimeConfig(
lockId: state.lockSetInfoData.value.lockId!, lockId: state.lockSetInfoData.value.lockId!,
@ -112,4 +112,6 @@ class CatEyeSetLogic extends BaseGetXController {
} }
return entity; return entity;
} }
} }

View File

@ -1,9 +1,14 @@
import 'package:flutter_blue_plus/flutter_blue_plus.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:star_lock/blue/blue_manage.dart';
import 'package:star_lock/blue/io_tool/io_tool.dart';
import 'package:star_lock/blue/sender_manage.dart';
import 'package:star_lock/common/XSConstantMacro/XSConstantMacro.dart'; import 'package:star_lock/common/XSConstantMacro/XSConstantMacro.dart';
import 'package:star_lock/main/lockDetail/lockSet/catEyeSet/catEyeWorkMode/catEyeWorkMode_state.dart'; import 'package:star_lock/main/lockDetail/lockSet/catEyeSet/catEyeWorkMode/catEyeWorkMode_state.dart';
import 'package:star_lock/main/lockDetail/lockSet/lockSet/lockSetInfo_entity.dart'; import 'package:star_lock/main/lockDetail/lockSet/lockSet/lockSetInfo_entity.dart';
import 'package:star_lock/network/api_repository.dart'; import 'package:star_lock/network/api_repository.dart';
import 'package:star_lock/tools/baseGetXController.dart'; import 'package:star_lock/tools/baseGetXController.dart';
import 'package:star_lock/tools/storage.dart';
import 'package:star_lock/versionUndate/versionUndate_entity.dart'; import 'package:star_lock/versionUndate/versionUndate_entity.dart';
class CatEyeWorkModeLogic extends BaseGetXController { class CatEyeWorkModeLogic extends BaseGetXController {
@ -11,7 +16,8 @@ class CatEyeWorkModeLogic extends BaseGetXController {
// //
Future<void> updateCatEyeModeConfig() async { Future<void> updateCatEyeModeConfig() async {
final VersionUndateEntity entity = await ApiRepository.to.updateCatEyeModeConfig( final VersionUndateEntity entity =
await ApiRepository.to.updateCatEyeModeConfig(
lockId: state.lockSetInfoData.value.lockId!, lockId: state.lockSetInfoData.value.lockId!,
catEyeConfig: [ catEyeConfig: [
<String, Object>{ <String, Object>{
@ -53,9 +59,47 @@ class CatEyeWorkModeLogic extends BaseGetXController {
} }
} }
///
void _handlerBleData() {
BlueManage().blueSendData(BlueManage().connectDeviceName,
(BluetoothConnectionState connectionState) async {
if (connectionState == BluetoothConnectionState.connected) {
final List<String>? privateKey =
await Storage.getStringList(saveBluePrivateKey);
final List<int> getPrivateKeyList =
changeStringListToIntList(privateKey!);
final List<String>? token = await Storage.getStringList(saveBlueToken);
final List<int> getTokenList = changeStringListToIntList(token!);
final List<String>? publicKey =
await Storage.getStringList(saveBluePublicKey);
final List<int> getPublicKeyList =
changeStringListToIntList(publicKey!);
List<int> featureData = [];
IoSenderManage.setSupportFunctionsWithParametersCommand(
keyID: state.lockSetInfoData.value.lockBasicInfo!.keyId.toString(),
userID: await Storage.getUid(),
featureBit: 33,
featureParaLength: 1,
featureData: featureData,
token: getTokenList,
needAuthor: 1,
publicKey: getPublicKeyList,
privateKey: getPrivateKeyList);
} else if (connectionState == BluetoothConnectionState.disconnected) {
dismissEasyLoading();
cancelBlueConnetctToastTimer();
}
});
}
// //
Future<void> getLockSettingInfoData() async { Future<void> getLockSettingInfoData() async {
final LockSetInfoEntity entity = await ApiRepository.to.getLockSettingInfoData( final LockSetInfoEntity entity =
await ApiRepository.to.getLockSettingInfoData(
lockId: state.lockSetInfoData.value.lockId.toString(), lockId: state.lockSetInfoData.value.lockId.toString(),
); );
if (entity.errorCode!.codeIsSuccessful) { if (entity.errorCode!.codeIsSuccessful) {

View File

@ -105,10 +105,11 @@ class ConfiguringWifiLogic extends BaseGetXController {
serversList.add(type2); serversList.add(type2);
} }
final StarChartRegisterNodeEntity? registerNodeEntity = //
await Storage.getStarChartRegisterNodeInfo(); final loginData = await Storage.getLoginData();
// app用户的peerId // app用户的peerId
String appPeerId = registerNodeEntity?.peer?.id ?? ''; String appPeerId = loginData?.starchart?.starchartId ?? '';
final List<String> uidList = <String>[Storage.getUid().toString()]; final List<String> uidList = <String>[Storage.getUid().toString()];
IoSenderManage.senderConfiguringWifiCommand( IoSenderManage.senderConfiguringWifiCommand(
@ -201,10 +202,11 @@ class ConfiguringWifiLogic extends BaseGetXController {
final String? uidStr = await Storage.getUid(); final String? uidStr = await Storage.getUid();
final List<String> uidList = <String>[uidStr.toString()]; final List<String> uidList = <String>[uidStr.toString()];
final StarChartRegisterNodeEntity? registerNodeEntity = //
await Storage.getStarChartRegisterNodeInfo(); final loginData = await Storage.getLoginData();
// app用户的peerId // app用户的peerId
String appPeerId = registerNodeEntity?.peer?.id ?? ''; String appPeerId = loginData?.starchart?.starchartId ?? '';
IoSenderManage.senderConfiguringWifiCommand( IoSenderManage.senderConfiguringWifiCommand(
keyID: state.lockSetInfoData.value.lockBasicInfo!.keyId.toString(), keyID: state.lockSetInfoData.value.lockBasicInfo!.keyId.toString(),
userID: await Storage.getUid(), userID: await Storage.getUid(),

File diff suppressed because one or more lines are too long

View File

@ -6,6 +6,7 @@ import 'package:star_lock/talk/startChart/constant/payload_type_constant.dart';
import 'package:star_lock/talk/startChart/constant/protocol_flag_constant.dart'; import 'package:star_lock/talk/startChart/constant/protocol_flag_constant.dart';
import 'package:star_lock/talk/startChart/constant/udp_constant.dart'; import 'package:star_lock/talk/startChart/constant/udp_constant.dart';
import 'package:star_lock/talk/startChart/entity/scp_message.dart'; import 'package:star_lock/talk/startChart/entity/scp_message.dart';
import 'package:star_lock/talk/startChart/proto/ble_message.pb.dart';
import 'package:star_lock/talk/startChart/proto/gateway_reset.pb.dart'; import 'package:star_lock/talk/startChart/proto/gateway_reset.pb.dart';
import 'package:star_lock/talk/startChart/proto/generic.pb.dart'; import 'package:star_lock/talk/startChart/proto/generic.pb.dart';
import 'package:star_lock/talk/startChart/proto/rbcu.pb.dart'; import 'package:star_lock/talk/startChart/proto/rbcu.pb.dart';
@ -386,7 +387,7 @@ class MessageCommand {
final payload = rbcuInfo.writeToBuffer(); final payload = rbcuInfo.writeToBuffer();
ScpMessage message = ScpMessage( ScpMessage message = ScpMessage(
ProtocolFlag: ProtocolFlagConstant.scp01, ProtocolFlag: ProtocolFlagConstant.scp01,
MessageType: MessageTypeConstant.Resp, MessageType: MessageTypeConstant.Req,
MessageId: MessageId, MessageId: MessageId,
SpTotal: 1, SpTotal: 1,
SpIndex: 1, SpIndex: 1,
@ -401,6 +402,40 @@ class MessageCommand {
return _hexToBytes(serializedBytesString); return _hexToBytes(serializedBytesString);
} }
//
static List<int> bleMessage({
required String FromPeerId,
required String ToPeerId,
required String bluetoothDeviceName,
required List<int> bleStructData,
int? MessageId,
int? timeout = 30,
int? IdleTimeout = 0,
}) {
final bleReq = BleReq(
bluetoothDeviceName: bluetoothDeviceName,
structData: bleStructData,
timeout: timeout,
idleTimeout: 0,
);
final payload = bleReq.writeToBuffer();
ScpMessage message = ScpMessage(
ProtocolFlag: ProtocolFlagConstant.scp01,
MessageType: MessageTypeConstant.Req,
MessageId: MessageId,
SpTotal: 1,
SpIndex: 1,
FromPeerId: FromPeerId,
ToPeerId: ToPeerId,
Payload: payload,
PayloadCRC: calculationCrc(Uint8List.fromList(payload)),
PayloadLength: payload.length,
PayloadType: PayloadTypeConstant.blePassthrough,
);
String serializedBytesString = message.serialize();
return _hexToBytes(serializedBytesString);
}
// 16 // 16
static List<int> _hexToBytes(String hex) { static List<int> _hexToBytes(String hex) {
final bytes = <int>[]; final bytes = <int>[];

View File

@ -2,6 +2,7 @@ import 'dart:convert';
import 'dart:typed_data'; import 'dart:typed_data';
import 'package:star_lock/app_settings/app_settings.dart'; import 'package:star_lock/app_settings/app_settings.dart';
import 'package:star_lock/talk/startChart/exception/start_chart_message_exception.dart'; import 'package:star_lock/talk/startChart/exception/start_chart_message_exception.dart';
import 'package:star_lock/talk/startChart/handle/impl/udp_heart_beat_handler.dart';
import 'package:star_lock/talk/startChart/handle/scp_message_handle.dart'; import 'package:star_lock/talk/startChart/handle/scp_message_handle.dart';
import 'package:star_lock/talk/startChart/handle/scp_message_handler_factory.dart'; import 'package:star_lock/talk/startChart/handle/scp_message_handler_factory.dart';

View File

@ -1,8 +1,11 @@
import 'dart:convert';
import 'dart:typed_data'; import 'dart:typed_data';
import 'package:flutter_easyloading/flutter_easyloading.dart'; import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:star_lock/appRouters.dart'; import 'package:star_lock/appRouters.dart';
import 'package:star_lock/app_settings/app_settings.dart';
import 'package:star_lock/talk/startChart/constant/message_type_constant.dart';
import 'package:star_lock/talk/startChart/entity/scp_message.dart'; import 'package:star_lock/talk/startChart/entity/scp_message.dart';
import 'package:star_lock/talk/startChart/handle/scp_message_base_handle.dart'; import 'package:star_lock/talk/startChart/handle/scp_message_base_handle.dart';
import 'package:star_lock/talk/startChart/handle/scp_message_handle.dart'; import 'package:star_lock/talk/startChart/handle/scp_message_handle.dart';
@ -16,13 +19,16 @@ class UdpBlePassThroughHandler extends ScpMessageBaseHandle
implements ScpMessageHandler { implements ScpMessageHandler {
@override @override
void handleReq(ScpMessage scpMessage) { void handleReq(ScpMessage scpMessage) {
final BleResp bleResp = scpMessage.Payload;
//TODO //TODO
} }
@override @override
void handleResp(ScpMessage scpMessage) { void handleResp(ScpMessage scpMessage) {
// TODO: final BleResp bleResp = scpMessage.Payload;
//
// if (bleResp.status == BleResp_StatusE.SUCCESS) {
AppLog.log('收到蓝牙消息回复:${bleResp.structData}');
// }
} }
@override @override
@ -41,8 +47,17 @@ class UdpBlePassThroughHandler extends ScpMessageBaseHandle
int? spTotal, int? spTotal,
int? spIndex, int? spIndex,
int? messageId}) { int? messageId}) {
final BleResp bleResp = BleResp(); if (messageType == MessageTypeConstant.Resp) {
bleResp.mergeFromBuffer(byte); final BleResp bleResp = BleResp();
return bleResp; bleResp.mergeFromBuffer(byte);
return bleResp;
} else if (messageType == MessageTypeConstant.Req) {
final BleReq talkExpect = BleReq();
talkExpect.mergeFromBuffer(byte);
return talkExpect;
} else {
String payload = utf8.decode(byte);
return payload;
}
} }
} }

View File

@ -46,16 +46,20 @@ class UdpRbcuInfoHandler extends ScpMessageBaseHandle
@override @override
void handleReq(ScpMessage scpMessage) { void handleReq(ScpMessage scpMessage) {
final RbcuInfo rbcuInfo = scpMessage.Payload(); final RbcuInfo rbcuInfo = scpMessage.Payload;
if (rbcuInfo.isResp) { if (rbcuInfo.isResp) {
// //
_handleResultRbcuInfo(rbcuInfo); _handleResultRbcuInfo(rbcuInfo);
} else {
//
startChartManage.replyRbcuInfoMessage(ToPeerId: scpMessage.FromPeerId!);
} }
replySuccessMessage(scpMessage);
} }
@override @override
void handleResp(ScpMessage scpMessage) { void handleResp(ScpMessage scpMessage) {
final GenericResp genericResp = scpMessage.Payload(); final GenericResp genericResp = scpMessage.Payload;
if (checkGenericRespSuccess(genericResp)) { if (checkGenericRespSuccess(genericResp)) {
// //
startChartManage.stopSendingRbcuInfoMessages(); startChartManage.stopSendingRbcuInfoMessages();
@ -65,5 +69,6 @@ class UdpRbcuInfoHandler extends ScpMessageBaseHandle
/// rbcuInfo消息 /// rbcuInfo消息
void _handleResultRbcuInfo(RbcuInfo rbcuInfo) { void _handleResultRbcuInfo(RbcuInfo rbcuInfo) {
P2pManage().communicationObjectRbcuInfo = rbcuInfo; P2pManage().communicationObjectRbcuInfo = rbcuInfo;
startChartManage.stopSendingRbcuInfoMessages();
} }
} }

View File

@ -12,25 +12,21 @@ import 'package:star_lock/talk/startChart/proto/gateway_reset.pb.dart';
import 'package:star_lock/talk/startChart/proto/generic.pb.dart'; import 'package:star_lock/talk/startChart/proto/generic.pb.dart';
import 'package:star_lock/talk/startChart/proto/talk_data.pb.dart'; import 'package:star_lock/talk/startChart/proto/talk_data.pb.dart';
import 'package:star_lock/talk/startChart/proto/talk_expect.pb.dart'; import 'package:star_lock/talk/startChart/proto/talk_expect.pb.dart';
import 'package:star_lock/talk/startChart/views/talkView/talk_view_logic.dart';
import 'package:star_lock/talk/startChart/views/talkView/talk_view_state.dart'; import 'package:star_lock/talk/startChart/views/talkView/talk_view_state.dart';
import '../../start_chart_manage.dart'; import '../../start_chart_manage.dart';
class UdpTalkExpectHandler extends ScpMessageBaseHandle class UdpTalkExpectHandler extends ScpMessageBaseHandle
implements ScpMessageHandler { implements ScpMessageHandler {
final TalkViewState talkViewState = TalkViewState(); final TalkViewState talkViewState = Get.put(TalkViewLogic()).state;
@override @override
void handleReq(ScpMessage scpMessage) { void handleReq(ScpMessage scpMessage) {
// //
final TalkExpectReq talkExpect = scpMessage.Payload; final TalkExpectReq talkExpect = scpMessage.Payload;
print('收到预期音视频数据请求:$talkExpect');
// //
replySuccessMessage(scpMessage); replySuccessMessage(scpMessage);
//
// startChartManage.startTalkDataTimer();
} }
@override @override
@ -38,10 +34,13 @@ class UdpTalkExpectHandler extends ScpMessageBaseHandle
// //
final TalkExpectResp talkExpectResp = scpMessage.Payload; final TalkExpectResp talkExpectResp = scpMessage.Payload;
if (talkExpectResp != null) { if (talkExpectResp != null) {
print('收到预期音视频数据回复'); // print('收到预期音视频数据回复,scpMessage:$scpMessage');
// //
startChartManage.stopTalkExpectMessageTimer(); startChartManage.stopTalkExpectMessageTimer();
talkViewState.rotateAngle.value = talkExpectResp.rotate ?? 0; talkViewState.rotateAngle.value = talkExpectResp.rotate ?? 0;
//
// x秒内没有收到通话保持则执行的操作;
talkePingOverTimeTimerManager.start();
} }
} }

View File

@ -15,17 +15,17 @@ class UdpTalkHangUpHandler extends ScpMessageBaseHandle
implements ScpMessageHandler { implements ScpMessageHandler {
@override @override
void handleReq(ScpMessage scpMessage) { void handleReq(ScpMessage scpMessage) {
if (talkStatus.status != TalkStatus.answeredSuccessfully) { // if (talkStatus.status != TalkStatus.answeredSuccessfully) {
// // //
return; // return;
} // }
print('收到通话中挂断请求');
// //
replySuccessMessage(scpMessage); replySuccessMessage(scpMessage);
talkStatus.setHangingUpDuring(); talkStatus.setHangingUpDuring();
stopRingtone(); stopRingtone();
StartChartManage().stopTalkExpectMessageTimer(); StartChartManage().stopTalkExpectMessageTimer();
StartChartManage().stopTalkPingMessageTimer(); StartChartManage().stopTalkPingMessageTimer();
} }
@override @override

View File

@ -15,15 +15,13 @@ class UdpTalkPingHandler extends ScpMessageBaseHandle
void handleReq(ScpMessage scpMessage) { void handleReq(ScpMessage scpMessage) {
// , // ,
replySuccessMessage(scpMessage); replySuccessMessage(scpMessage);
talkePingOverTimeTimerManager.renew();
} }
@override @override
void handleResp(ScpMessage scpMessage) { void handleResp(ScpMessage scpMessage) {
//
// print('收到通话保持回复');
final GenericResp genericResp = scpMessage.Payload; final GenericResp genericResp = scpMessage.Payload;
if (checkGenericRespSuccess(genericResp)) { if (checkGenericRespSuccess(genericResp)) {
//
talkePingOverTimeTimerManager.renew(); talkePingOverTimeTimerManager.renew();
} }
} }

View File

@ -20,6 +20,8 @@ class UdpTalkRequestHandler extends ScpMessageBaseHandle
implements ScpMessageHandler { implements ScpMessageHandler {
@override @override
void handleReq(ScpMessage scpMessage) async { void handleReq(ScpMessage scpMessage) async {
//
replySuccessMessage(scpMessage);
// //
final loginData = await Storage.getLoginData(); final loginData = await Storage.getLoginData();
if (loginData == null || if (loginData == null ||
@ -28,11 +30,8 @@ class UdpTalkRequestHandler extends ScpMessageBaseHandle
// //
return; return;
} }
//
replySuccessMessage(scpMessage);
// //
final TalkReq talkReq = scpMessage.Payload; final TalkReq talkReq = scpMessage.Payload;
startChartManage.FromPeerId = scpMessage.ToPeerId!; startChartManage.FromPeerId = scpMessage.ToPeerId!;
startChartManage.ToPeerId = scpMessage.FromPeerId!; startChartManage.ToPeerId = scpMessage.FromPeerId!;
// //
@ -64,8 +63,6 @@ class UdpTalkRequestHandler extends ScpMessageBaseHandle
_showTalkRequestNotification(talkObjectName: talkObjectName); _showTalkRequestNotification(talkObjectName: talkObjectName);
// //
talkStatus.setWaitingAnswer(); talkStatus.setWaitingAnswer();
//
_handleStartTalkPing();
// //
talkeRequestOverTimeTimerManager.start(); talkeRequestOverTimeTimerManager.start();
// //
@ -123,12 +120,4 @@ class UdpTalkRequestHandler extends ScpMessageBaseHandle
// //
startChartManage.sendOnlyImageVideoTalkExpectData(); startChartManage.sendOnlyImageVideoTalkExpectData();
} }
// x秒内是否收到通话保持
void _handleStartTalkPing() {
//
startChartManage.startTalkPingMessageTimer();
// x秒内没有收到通话保持则执行的操作
talkePingOverTimeTimerManager.start();
}
} }

View File

@ -5,7 +5,8 @@ import 'package:get/get.dart';
import 'package:star_lock/talk/startChart/constant/talk_constant.dart'; import 'package:star_lock/talk/startChart/constant/talk_constant.dart';
import 'package:star_lock/talk/startChart/constant/talk_status.dart'; import 'package:star_lock/talk/startChart/constant/talk_status.dart';
import 'package:star_lock/talk/startChart/start_chart_manage.dart'; import 'package:star_lock/talk/startChart/start_chart_manage.dart';
import 'package:star_lock/talk/startChart/start_chart_talk_status.dart'; import 'package:star_lock/talk/startChart/status/start_chart_talk_status.dart';
class TalkDataOverTimeTimerManager { class TalkDataOverTimeTimerManager {
// //

View File

@ -5,7 +5,7 @@ import 'package:get/get.dart';
import 'package:star_lock/talk/startChart/constant/talk_constant.dart'; import 'package:star_lock/talk/startChart/constant/talk_constant.dart';
import 'package:star_lock/talk/startChart/constant/talk_status.dart'; import 'package:star_lock/talk/startChart/constant/talk_status.dart';
import 'package:star_lock/talk/startChart/start_chart_manage.dart'; import 'package:star_lock/talk/startChart/start_chart_manage.dart';
import 'package:star_lock/talk/startChart/start_chart_talk_status.dart'; import 'package:star_lock/talk/startChart/status/start_chart_talk_status.dart';
class TalkePingOverTimeTimerManager { class TalkePingOverTimeTimerManager {
// //
@ -41,6 +41,8 @@ class TalkePingOverTimeTimerManager {
// //
void start() { void start() {
//
_timer?.cancel();
_timer = Timer(timeout, onTimeout); _timer = Timer(timeout, onTimeout);
} }

View File

@ -5,7 +5,7 @@ import 'package:get/get.dart';
import 'package:star_lock/talk/startChart/constant/talk_constant.dart'; import 'package:star_lock/talk/startChart/constant/talk_constant.dart';
import 'package:star_lock/talk/startChart/constant/talk_status.dart'; import 'package:star_lock/talk/startChart/constant/talk_status.dart';
import 'package:star_lock/talk/startChart/start_chart_manage.dart'; import 'package:star_lock/talk/startChart/start_chart_manage.dart';
import 'package:star_lock/talk/startChart/start_chart_talk_status.dart'; import 'package:star_lock/talk/startChart/status/start_chart_talk_status.dart';
class TalkeRequestOverTimeTimerManager { class TalkeRequestOverTimeTimerManager {
// //
@ -31,6 +31,7 @@ class TalkeRequestOverTimeTimerManager {
EasyLoading.showToast('通话未接通,以挂断', duration: 2000.milliseconds); EasyLoading.showToast('通话未接通,以挂断', duration: 2000.milliseconds);
// //
StartChartManage().sendTalkRejectMessage(); StartChartManage().sendTalkRejectMessage();
talkStatus.setInitializationCompleted();
Get.back(); Get.back();
} }
} }

View File

@ -22,7 +22,8 @@ import 'package:star_lock/talk/startChart/handle/other/talke_request_over_time_t
import 'package:star_lock/talk/startChart/proto/generic.pb.dart'; import 'package:star_lock/talk/startChart/proto/generic.pb.dart';
import 'package:star_lock/talk/startChart/proto/talk_data.pb.dart'; import 'package:star_lock/talk/startChart/proto/talk_data.pb.dart';
import 'package:star_lock/talk/startChart/start_chart_manage.dart'; import 'package:star_lock/talk/startChart/start_chart_manage.dart';
import 'package:star_lock/talk/startChart/start_chart_talk_status.dart';
import 'package:star_lock/talk/startChart/status/start_chart_talk_status.dart';
class ScpMessageBaseHandle { class ScpMessageBaseHandle {
/// 使 TimerManager /// 使 TimerManager

View File

@ -1,5 +1,6 @@
import 'package:star_lock/talk/startChart/constant/payload_type_constant.dart'; import 'package:star_lock/talk/startChart/constant/payload_type_constant.dart';
import 'package:star_lock/talk/startChart/handle/impl/udp_ble_passthrough_handler.dart'; import 'package:star_lock/talk/startChart/handle/impl/udp_ble_passthrough_handler.dart';
import 'package:star_lock/talk/startChart/handle/impl/udp_rbcuInfo_handler.dart';
import 'package:star_lock/talk/startChart/handle/impl/udp_talk_request_handler.dart'; import 'package:star_lock/talk/startChart/handle/impl/udp_talk_request_handler.dart';
import 'package:star_lock/talk/startChart/handle/impl/udp_echo_test_handler.dart'; import 'package:star_lock/talk/startChart/handle/impl/udp_echo_test_handler.dart';
import 'package:star_lock/talk/startChart/handle/impl/udp_gateway_reset_handler.dart'; import 'package:star_lock/talk/startChart/handle/impl/udp_gateway_reset_handler.dart';
@ -55,7 +56,7 @@ class ScpMessageHandlerFactory {
case PayloadTypeConstant.talkHangup: case PayloadTypeConstant.talkHangup:
return UdpTalkHangUpHandler(); return UdpTalkHangUpHandler();
case PayloadTypeConstant.RbcuInfo: case PayloadTypeConstant.RbcuInfo:
return UdpTalkHangUpHandler(); return UdpRbcuInfoHandler();
default: default:
return UnKnowPayloadTypeHandler(); return UnKnowPayloadTypeHandler();
} }

View File

@ -1,14 +1,25 @@
import 'dart:async';
import 'dart:io';
import 'package:star_lock/talk/startChart/proto/rbcu.pb.dart'; import 'package:star_lock/talk/startChart/proto/rbcu.pb.dart';
class P2pManage { class P2pManage {
//
static const String testMessage = 'Hello'; //
static const int localPort = 0; // 0
static const Duration connectionTimeout = Duration(seconds: 5); //
static const List<String> localNetworkPrefixes = [
'192.168.',
'10.',
'172.'
]; // IP
RbcuInfo? communicationObjectRbcuInfo; RbcuInfo? communicationObjectRbcuInfo;
void init() {
void init(){ //
} }
// address IP // address IP
List<Map<String, String>> parseRemoteAddresses() { List<Map<String, String>> parseRemoteAddresses() {
final addresses = communicationObjectRbcuInfo?.address ?? []; final addresses = communicationObjectRbcuInfo?.address ?? [];
@ -18,4 +29,80 @@ class P2pManage {
}).toList(); }).toList();
} }
// IP
bool _isLocalNetworkIp(String ip) {
for (final prefix in localNetworkPrefixes) {
if (ip.startsWith(prefix)) {
// 172.16.x.x 172.31.x.x
if (prefix == '172.') {
final secondOctet = int.tryParse(ip.split('.')[1]) ?? 0;
if (secondOctet >= 16 && secondOctet <= 31) {
return true;
}
} else {
return true;
}
}
}
return false;
}
// UDP
Future<void> createUdpConnection() async {
final addresses = parseRemoteAddresses();
// 使 IP
addresses.sort((a, b) {
final isALocal = _isLocalNetworkIp(a['ip']!);
final isBLocal = _isLocalNetworkIp(b['ip']!);
if (isALocal && !isBLocal) return -1; // a IP
if (!isALocal && isBLocal) return 1; // b IP
return 0; //
});
//
for (final addr in addresses) {
final ip = addr['ip']!;
final port = int.parse(addr['port']!);
try {
final socket = await RawDatagramSocket.bind(
InternetAddress.anyIPv4, localPort); //
//
final testData = testMessage.codeUnits;
socket.send(testData, InternetAddress(ip), port);
//
final completer = Completer<void>();
//
socket.listen((event) {
if (event == RawSocketEvent.read) {
final datagram = socket.receive();
if (datagram != null) {
final response = String.fromCharCodes(datagram.data);
print('收到来自 $ip:$port 的响应: $response');
completer.complete(); // Future
}
}
});
//
try {
await completer.future.timeout(connectionTimeout);
print('成功连接到 $ip:$port');
return; // 退
} on TimeoutException {
print('连接到 $ip:$port 超时');
} finally {
socket.close(); // socket
}
} catch (e) {
print('连接到 $ip:$port 失败: $e');
}
}
print('无法连接到任何地址');
}
} }

View File

@ -17,18 +17,27 @@ import 'ble_message.pbenum.dart';
export 'ble_message.pbenum.dart'; export 'ble_message.pbenum.dart';
///
class BleReq extends $pb.GeneratedMessage { class BleReq extends $pb.GeneratedMessage {
factory BleReq({ factory BleReq({
$core.int? timeout,
$core.String? bluetoothDeviceName, $core.String? bluetoothDeviceName,
$core.List<$core.int>? structData, $core.List<$core.int>? structData,
$core.int? idleTimeout,
}) { }) {
final $result = create(); final $result = create();
if (timeout != null) {
$result.timeout = timeout;
}
if (bluetoothDeviceName != null) { if (bluetoothDeviceName != null) {
$result.bluetoothDeviceName = bluetoothDeviceName; $result.bluetoothDeviceName = bluetoothDeviceName;
} }
if (structData != null) { if (structData != null) {
$result.structData = structData; $result.structData = structData;
} }
if (idleTimeout != null) {
$result.idleTimeout = idleTimeout;
}
return $result; return $result;
} }
BleReq._() : super(); BleReq._() : super();
@ -36,8 +45,10 @@ class BleReq extends $pb.GeneratedMessage {
factory BleReq.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); factory BleReq.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'BleReq', package: const $pb.PackageName(_omitMessageNames ? '' : 'main'), createEmptyInstance: create) static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'BleReq', package: const $pb.PackageName(_omitMessageNames ? '' : 'main'), createEmptyInstance: create)
..a<$core.int>(1, _omitFieldNames ? '' : 'Timeout', $pb.PbFieldType.OU3, protoName: 'Timeout')
..aOS(2, _omitFieldNames ? '' : 'bluetoothDeviceName', protoName: 'bluetoothDeviceName') ..aOS(2, _omitFieldNames ? '' : 'bluetoothDeviceName', protoName: 'bluetoothDeviceName')
..a<$core.List<$core.int>>(3, _omitFieldNames ? '' : 'StructData', $pb.PbFieldType.OY, protoName: 'StructData') ..a<$core.List<$core.int>>(3, _omitFieldNames ? '' : 'StructData', $pb.PbFieldType.OY, protoName: 'StructData')
..a<$core.int>(6, _omitFieldNames ? '' : 'IdleTimeout', $pb.PbFieldType.OU3, protoName: 'IdleTimeout')
..hasRequiredFields = false ..hasRequiredFields = false
; ;
@ -62,25 +73,45 @@ class BleReq extends $pb.GeneratedMessage {
static BleReq getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<BleReq>(create); static BleReq getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<BleReq>(create);
static BleReq? _defaultInstance; static BleReq? _defaultInstance;
/// ++
@$pb.TagNumber(1)
$core.int get timeout => $_getIZ(0);
@$pb.TagNumber(1)
set timeout($core.int v) { $_setUnsignedInt32(0, v); }
@$pb.TagNumber(1)
$core.bool hasTimeout() => $_has(0);
@$pb.TagNumber(1)
void clearTimeout() => clearField(1);
/// mac地址 /// mac地址
@$pb.TagNumber(2) @$pb.TagNumber(2)
$core.String get bluetoothDeviceName => $_getSZ(0); $core.String get bluetoothDeviceName => $_getSZ(1);
@$pb.TagNumber(2) @$pb.TagNumber(2)
set bluetoothDeviceName($core.String v) { $_setString(0, v); } set bluetoothDeviceName($core.String v) { $_setString(1, v); }
@$pb.TagNumber(2) @$pb.TagNumber(2)
$core.bool hasBluetoothDeviceName() => $_has(0); $core.bool hasBluetoothDeviceName() => $_has(1);
@$pb.TagNumber(2) @$pb.TagNumber(2)
void clearBluetoothDeviceName() => clearField(2); void clearBluetoothDeviceName() => clearField(2);
/// ///
@$pb.TagNumber(3) @$pb.TagNumber(3)
$core.List<$core.int> get structData => $_getN(1); $core.List<$core.int> get structData => $_getN(2);
@$pb.TagNumber(3) @$pb.TagNumber(3)
set structData($core.List<$core.int> v) { $_setBytes(1, v); } set structData($core.List<$core.int> v) { $_setBytes(2, v); }
@$pb.TagNumber(3) @$pb.TagNumber(3)
$core.bool hasStructData() => $_has(1); $core.bool hasStructData() => $_has(2);
@$pb.TagNumber(3) @$pb.TagNumber(3)
void clearStructData() => clearField(3); void clearStructData() => clearField(3);
/// 0
@$pb.TagNumber(6)
$core.int get idleTimeout => $_getIZ(3);
@$pb.TagNumber(6)
set idleTimeout($core.int v) { $_setUnsignedInt32(3, v); }
@$pb.TagNumber(6)
$core.bool hasIdleTimeout() => $_has(3);
@$pb.TagNumber(6)
void clearIdleTimeout() => clearField(6);
} }
class BleResp extends $pb.GeneratedMessage { class BleResp extends $pb.GeneratedMessage {
@ -103,7 +134,7 @@ class BleResp extends $pb.GeneratedMessage {
static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'BleResp', package: const $pb.PackageName(_omitMessageNames ? '' : 'main'), createEmptyInstance: create) static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'BleResp', package: const $pb.PackageName(_omitMessageNames ? '' : 'main'), createEmptyInstance: create)
..e<BleResp_StatusE>(1, _omitFieldNames ? '' : 'Status', $pb.PbFieldType.OE, protoName: 'Status', defaultOrMaker: BleResp_StatusE.SUCCESS, valueOf: BleResp_StatusE.valueOf, enumValues: BleResp_StatusE.values) ..e<BleResp_StatusE>(1, _omitFieldNames ? '' : 'Status', $pb.PbFieldType.OE, protoName: 'Status', defaultOrMaker: BleResp_StatusE.SUCCESS, valueOf: BleResp_StatusE.valueOf, enumValues: BleResp_StatusE.values)
..a<$core.List<$core.int>>(4, _omitFieldNames ? '' : 'StructData', $pb.PbFieldType.OY, protoName: 'StructData') ..a<$core.List<$core.int>>(2, _omitFieldNames ? '' : 'StructData', $pb.PbFieldType.OY, protoName: 'StructData')
..hasRequiredFields = false ..hasRequiredFields = false
; ;
@ -138,15 +169,15 @@ class BleResp extends $pb.GeneratedMessage {
@$pb.TagNumber(1) @$pb.TagNumber(1)
void clearStatus() => clearField(1); void clearStatus() => clearField(1);
/// ///
@$pb.TagNumber(4) @$pb.TagNumber(2)
$core.List<$core.int> get structData => $_getN(1); $core.List<$core.int> get structData => $_getN(1);
@$pb.TagNumber(4) @$pb.TagNumber(2)
set structData($core.List<$core.int> v) { $_setBytes(1, v); } set structData($core.List<$core.int> v) { $_setBytes(1, v); }
@$pb.TagNumber(4) @$pb.TagNumber(2)
$core.bool hasStructData() => $_has(1); $core.bool hasStructData() => $_has(1);
@$pb.TagNumber(4) @$pb.TagNumber(2)
void clearStructData() => clearField(4); void clearStructData() => clearField(2);
} }

View File

@ -18,16 +18,16 @@ class BleResp_StatusE extends $pb.ProtobufEnum {
static const BleResp_StatusE SUCCESS = BleResp_StatusE._(0, _omitEnumNames ? '' : 'SUCCESS'); static const BleResp_StatusE SUCCESS = BleResp_StatusE._(0, _omitEnumNames ? '' : 'SUCCESS');
static const BleResp_StatusE FAIL = BleResp_StatusE._(1, _omitEnumNames ? '' : 'FAIL'); static const BleResp_StatusE FAIL = BleResp_StatusE._(1, _omitEnumNames ? '' : 'FAIL');
static const BleResp_StatusE NOT_FOUND = BleResp_StatusE._(2, _omitEnumNames ? '' : 'NOT_FOUND'); static const BleResp_StatusE NOT_FOUND = BleResp_StatusE._(2, _omitEnumNames ? '' : 'NOT_FOUND');
static const BleResp_StatusE CANNOT_CONNECT = BleResp_StatusE._(3, _omitEnumNames ? '' : 'CANNOT_CONNECT'); static const BleResp_StatusE CONNECT_FAIL = BleResp_StatusE._(3, _omitEnumNames ? '' : 'CONNECT_FAIL');
static const BleResp_StatusE CANNOT_SEND = BleResp_StatusE._(4, _omitEnumNames ? '' : 'CANNOT_SEND'); static const BleResp_StatusE SEND_FAIL = BleResp_StatusE._(4, _omitEnumNames ? '' : 'SEND_FAIL');
static const BleResp_StatusE TIMEOUT = BleResp_StatusE._(5, _omitEnumNames ? '' : 'TIMEOUT'); static const BleResp_StatusE TIMEOUT = BleResp_StatusE._(5, _omitEnumNames ? '' : 'TIMEOUT');
static const $core.List<BleResp_StatusE> values = <BleResp_StatusE> [ static const $core.List<BleResp_StatusE> values = <BleResp_StatusE> [
SUCCESS, SUCCESS,
FAIL, FAIL,
NOT_FOUND, NOT_FOUND,
CANNOT_CONNECT, CONNECT_FAIL,
CANNOT_SEND, SEND_FAIL,
TIMEOUT, TIMEOUT,
]; ];

View File

@ -19,20 +19,23 @@ const BleReq$json = {
'2': [ '2': [
{'1': 'bluetoothDeviceName', '3': 2, '4': 1, '5': 9, '10': 'bluetoothDeviceName'}, {'1': 'bluetoothDeviceName', '3': 2, '4': 1, '5': 9, '10': 'bluetoothDeviceName'},
{'1': 'StructData', '3': 3, '4': 1, '5': 12, '10': 'StructData'}, {'1': 'StructData', '3': 3, '4': 1, '5': 12, '10': 'StructData'},
{'1': 'Timeout', '3': 1, '4': 1, '5': 13, '10': 'Timeout'},
{'1': 'IdleTimeout', '3': 6, '4': 1, '5': 13, '10': 'IdleTimeout'},
], ],
}; };
/// Descriptor for `BleReq`. Decode as a `google.protobuf.DescriptorProto`. /// Descriptor for `BleReq`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List bleReqDescriptor = $convert.base64Decode( final $typed_data.Uint8List bleReqDescriptor = $convert.base64Decode(
'CgZCbGVSZXESMAoTYmx1ZXRvb3RoRGV2aWNlTmFtZRgCIAEoCVITYmx1ZXRvb3RoRGV2aWNlTm' 'CgZCbGVSZXESMAoTYmx1ZXRvb3RoRGV2aWNlTmFtZRgCIAEoCVITYmx1ZXRvb3RoRGV2aWNlTm'
'FtZRIeCgpTdHJ1Y3REYXRhGAMgASgMUgpTdHJ1Y3REYXRh'); 'FtZRIeCgpTdHJ1Y3REYXRhGAMgASgMUgpTdHJ1Y3REYXRhEhgKB1RpbWVvdXQYASABKA1SB1Rp'
'bWVvdXQSIAoLSWRsZVRpbWVvdXQYBiABKA1SC0lkbGVUaW1lb3V0');
@$core.Deprecated('Use bleRespDescriptor instead') @$core.Deprecated('Use bleRespDescriptor instead')
const BleResp$json = { const BleResp$json = {
'1': 'BleResp', '1': 'BleResp',
'2': [ '2': [
{'1': 'Status', '3': 1, '4': 1, '5': 14, '6': '.main.BleResp.StatusE', '10': 'Status'}, {'1': 'Status', '3': 1, '4': 1, '5': 14, '6': '.main.BleResp.StatusE', '10': 'Status'},
{'1': 'StructData', '3': 4, '4': 1, '5': 12, '10': 'StructData'}, {'1': 'StructData', '3': 2, '4': 1, '5': 12, '10': 'StructData'},
], ],
'4': [BleResp_StatusE$json], '4': [BleResp_StatusE$json],
}; };
@ -44,8 +47,8 @@ const BleResp_StatusE$json = {
{'1': 'SUCCESS', '2': 0}, {'1': 'SUCCESS', '2': 0},
{'1': 'FAIL', '2': 1}, {'1': 'FAIL', '2': 1},
{'1': 'NOT_FOUND', '2': 2}, {'1': 'NOT_FOUND', '2': 2},
{'1': 'CANNOT_CONNECT', '2': 3}, {'1': 'CONNECT_FAIL', '2': 3},
{'1': 'CANNOT_SEND', '2': 4}, {'1': 'SEND_FAIL', '2': 4},
{'1': 'TIMEOUT', '2': 5}, {'1': 'TIMEOUT', '2': 5},
], ],
}; };
@ -53,7 +56,7 @@ const BleResp_StatusE$json = {
/// Descriptor for `BleResp`. Decode as a `google.protobuf.DescriptorProto`. /// Descriptor for `BleResp`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List bleRespDescriptor = $convert.base64Decode( final $typed_data.Uint8List bleRespDescriptor = $convert.base64Decode(
'CgdCbGVSZXNwEi0KBlN0YXR1cxgBIAEoDjIVLm1haW4uQmxlUmVzcC5TdGF0dXNFUgZTdGF0dX' 'CgdCbGVSZXNwEi0KBlN0YXR1cxgBIAEoDjIVLm1haW4uQmxlUmVzcC5TdGF0dXNFUgZTdGF0dX'
'MSHgoKU3RydWN0RGF0YRgEIAEoDFIKU3RydWN0RGF0YSJhCgdTdGF0dXNFEgsKB1NVQ0NFU1MQ' 'MSHgoKU3RydWN0RGF0YRgCIAEoDFIKU3RydWN0RGF0YSJdCgdTdGF0dXNFEgsKB1NVQ0NFU1MQ'
'ABIICgRGQUlMEAESDQoJTk9UX0ZPVU5EEAISEgoOQ0FOTk9UX0NPTk5FQ1QQAxIPCgtDQU5OT1' 'ABIICgRGQUlMEAESDQoJTk9UX0ZPVU5EEAISEAoMQ09OTkVDVF9GQUlMEAMSDQoJU0VORF9GQU'
'RfU0VORBAEEgsKB1RJTUVPVVQQBQ=='); 'lMEAQSCwoHVElNRU9VVBAF');

View File

@ -3,26 +3,29 @@ package main;
option go_package = "./spb"; option go_package = "./spb";
// //
message BleReq { message BleReq {
// mac地址 // mac地址
string bluetoothDeviceName = 2; string bluetoothDeviceName = 2;
// //
bytes StructData = 3; bytes StructData = 3;
// ++
uint32 Timeout = 1;
// 0
uint32 IdleTimeout = 6;
} }
message BleResp { message BleResp {
// //
enum StatusE { enum StatusE {
SUCCESS = 0; SUCCESS = 0; //
FAIL = 1; FAIL = 1; //
NOT_FOUND = 2; NOT_FOUND = 2; //
CANNOT_CONNECT = 3; CONNECT_FAIL = 3; //
CANNOT_SEND = 4; SEND_FAIL = 4; //
TIMEOUT = 5; TIMEOUT = 5; //
} }
// //
StatusE Status = 1; StatusE Status = 1;
// //
bytes StructData = 4; bytes StructData = 2;
} }

View File

@ -29,7 +29,7 @@ import 'package:star_lock/talk/startChart/proto/rbcu.pb.dart';
import 'package:star_lock/talk/startChart/proto/talk_data.pb.dart'; import 'package:star_lock/talk/startChart/proto/talk_data.pb.dart';
import 'package:star_lock/talk/startChart/proto/talk_expect.pb.dart'; import 'package:star_lock/talk/startChart/proto/talk_expect.pb.dart';
import 'package:star_lock/talk/startChart/proto/talk_expect.pbserver.dart'; import 'package:star_lock/talk/startChart/proto/talk_expect.pbserver.dart';
import 'package:star_lock/talk/startChart/start_chart_talk_status.dart'; import 'package:star_lock/talk/startChart/status/start_chart_talk_status.dart';
import 'package:star_lock/tools/baseGetXController.dart'; import 'package:star_lock/tools/baseGetXController.dart';
import 'package:star_lock/tools/deviceInfo_utils.dart'; import 'package:star_lock/tools/deviceInfo_utils.dart';
import 'package:star_lock/tools/storage.dart'; import 'package:star_lock/tools/storage.dart';
@ -221,7 +221,8 @@ class StartChartManage {
} }
// RbcuInfo // RbcuInfo
void _sendRbcuInfoMessage() async { void _sendRbcuInfoMessage(
{required String ToPeerId, bool isResp = false}) async {
final uuid = _uuid.v1(); final uuid = _uuid.v1();
final int timestamp = DateTime.now().millisecondsSinceEpoch; final int timestamp = DateTime.now().millisecondsSinceEpoch;
final Int64 int64Timestamp = Int64(timestamp); // 使 final Int64 int64Timestamp = Int64(timestamp); // 使
@ -252,7 +253,7 @@ class StartChartManage {
name: uuid, name: uuid,
address: address, address: address,
time: int64Timestamp, time: int64Timestamp,
isResp: false, isResp: isResp,
); );
final message = MessageCommand.genericRbcuInfoMessage( final message = MessageCommand.genericRbcuInfoMessage(
ToPeerId: ToPeerId, ToPeerId: ToPeerId,
@ -264,12 +265,12 @@ class StartChartManage {
} }
// //
void startSendingRbcuInfoMessages() { void startSendingRbcuInfoMessages({required String ToPeerId}) {
// 1 _sendRbcuInfoMessage // 1 _sendRbcuInfoMessage
rbcuInfoTimer ??= rbcuInfoTimer ??=
Timer.periodic(Duration(seconds: _defaultIntervalTime), (timer) { Timer.periodic(Duration(seconds: _defaultIntervalTime), (timer) {
// RbcuInfo // RbcuInfo
_sendRbcuInfoMessage(); _sendRbcuInfoMessage(ToPeerId: ToPeerId);
}); });
} }
@ -279,6 +280,11 @@ class StartChartManage {
rbcuInfoTimer = null; rbcuInfoTimer = null;
} }
// RbcuInfo
void replyRbcuInfoMessage({required String ToPeerId}) {
_sendRbcuInfoMessage(ToPeerId: ToPeerId, isResp: true);
}
// 线 // 线
Future<void> _sendOnlineMessage() async { Future<void> _sendOnlineMessage() async {
if (isOnlineStartChartServer) { if (isOnlineStartChartServer) {
@ -329,7 +335,7 @@ class StartChartManage {
MessageCommand.getNextMessageId(ToPeerId, increment: false); MessageCommand.getNextMessageId(ToPeerId, increment: false);
// //
final message = MessageCommand.talkDataMessage( final message = MessageCommand.talkDataMessage(
ToPeerId: ToPeerId, ToPeerId: 'D78Fo4CjNzUXz8DxuUhLtcRpnGFXhSzhzs191XzhJttS',
FromPeerId: FromPeerId, FromPeerId: FromPeerId,
payload: packet, payload: packet,
SpTotal: totalPackets, SpTotal: totalPackets,
@ -891,8 +897,36 @@ class StartChartManage {
talkExpect: talkExpectReq); talkExpect: talkExpectReq);
} }
///
void sendRemoteUnLockMessage({
required String bluetoothDeviceName,
required List<int> openLockCommand,
}) {
sendBleMessage(
bluetoothDeviceName: bluetoothDeviceName,
bleStructData: openLockCommand,
);
}
///
void sendBleMessage({
required String bluetoothDeviceName,
required List<int> bleStructData,
}) {
// 线
final message = MessageCommand.bleMessage(
FromPeerId: FromPeerId,
ToPeerId: ToPeerId,
MessageId: MessageCommand.getNextMessageId(ToPeerId, increment: true),
bluetoothDeviceName: bluetoothDeviceName,
bleStructData: bleStructData,
);
_sendMessage(message: message);
}
/// ///
void destruction() async { void destruction() async {
sendTalkHangupMessage();
isOnlineStartChartServer = false; isOnlineStartChartServer = false;
stopHeartbeat(); stopHeartbeat();
stopTalkExpectMessageTimer(); stopTalkExpectMessageTimer();

View File

@ -25,7 +25,7 @@ class AppLifecycleObserver extends WidgetsBindingObserver {
void onAppPaused() { void onAppPaused() {
// //
print('App has entered the background.'); print('App has entered the background.');
StartChartManage().destruction(); // StartChartManage().destruction();
} }
void onAppResumed() { void onAppResumed() {

View File

@ -16,6 +16,13 @@ import 'package:image_gallery_saver/image_gallery_saver.dart';
import 'package:path_provider/path_provider.dart'; import 'package:path_provider/path_provider.dart';
import 'package:permission_handler/permission_handler.dart'; import 'package:permission_handler/permission_handler.dart';
import 'package:star_lock/app_settings/app_settings.dart'; import 'package:star_lock/app_settings/app_settings.dart';
import 'package:star_lock/blue/blue_manage.dart';
import 'package:star_lock/blue/io_protocol/io_openLock.dart';
import 'package:star_lock/blue/io_tool/io_tool.dart';
import 'package:star_lock/main/lockDetail/lockDetail/lockDetail_logic.dart';
import 'package:star_lock/main/lockDetail/lockDetail/lockDetail_state.dart';
import 'package:star_lock/main/lockDetail/lockDetail/lockNetToken_entity.dart';
import 'package:star_lock/network/api_repository.dart';
import 'package:star_lock/talk/startChart/constant/talk_status.dart'; import 'package:star_lock/talk/startChart/constant/talk_status.dart';
import 'package:star_lock/talk/startChart/proto/talk_data.pb.dart'; import 'package:star_lock/talk/startChart/proto/talk_data.pb.dart';
@ -24,12 +31,16 @@ import 'package:star_lock/talk/startChart/proto/talk_expect.pb.dart';
import 'package:star_lock/talk/startChart/start_chart_manage.dart'; import 'package:star_lock/talk/startChart/start_chart_manage.dart';
import 'package:star_lock/talk/startChart/views/talkView/talk_view_state.dart'; import 'package:star_lock/talk/startChart/views/talkView/talk_view_state.dart';
import 'package:star_lock/talk/udp/udp_manage.dart';
import 'package:star_lock/talk/udp/udp_senderManage.dart';
import 'package:star_lock/tools/bugly/bugly_tool.dart';
import 'package:star_lock/tools/storage.dart';
import '../../../../tools/baseGetXController.dart'; import '../../../../tools/baseGetXController.dart';
class TalkViewLogic extends BaseGetXController { class TalkViewLogic extends BaseGetXController {
final TalkViewState state = TalkViewState(); final TalkViewState state = TalkViewState();
final LockDetailState lockDetailState = Get.find<LockDetailLogic>().state;
Timer? _syncTimer; // Timer? _syncTimer; //
int _startTime = 0; // int _startTime = 0; //
final int bufferSize = 20; // final int bufferSize = 20; //
@ -258,7 +269,61 @@ class TalkViewLogic extends BaseGetXController {
} }
/// ///
udpOpenDoorAction(List<int> list) async {} udpOpenDoorAction() async {
final List<String>? privateKey =
await Storage.getStringList(saveBluePrivateKey);
final List<int> getPrivateKeyList = changeStringListToIntList(privateKey!);
final List<String>? signKey = await Storage.getStringList(saveBlueSignKey);
final List<int> signKeyDataList = changeStringListToIntList(signKey!);
final List<String>? token = await Storage.getStringList(saveBlueToken);
final List<int> getTokenList = changeStringListToIntList(token!);
await _getLockNetToken();
final OpenLockCommand openLockCommand = OpenLockCommand(
lockID: BlueManage().connectDeviceName,
userID: await Storage.getUid(),
openMode: lockDetailState.openDoorModel,
openTime: _getUTCNetTime(),
onlineToken: lockDetailState.lockNetToken,
token: getTokenList,
needAuthor: 1,
signKey: signKeyDataList,
privateKey: getPrivateKeyList,
);
final messageDetail = openLockCommand.messageDetail();
//
StartChartManage().sendRemoteUnLockMessage(
bluetoothDeviceName: BlueManage().connectDeviceName,
openLockCommand: messageDetail,
);
showToast('已发送开门通知');
}
int _getUTCNetTime() {
if (lockDetailState.isHaveNetwork) {
return DateTime.now().millisecondsSinceEpoch ~/ 1000 +
lockDetailState.differentialTime;
} else {
return 0;
}
}
// token
Future<void> _getLockNetToken() async {
final LockNetTokenEntity entity = await ApiRepository.to.getLockNetToken(
lockId: lockDetailState.keyInfos.value.lockId.toString());
if (entity.errorCode!.codeIsSuccessful) {
lockDetailState.lockNetToken = entity.data!.token!.toString();
AppLog.log('从服务器获取联网token:${lockDetailState.lockNetToken}');
} else {
BuglyTool.uploadException(
message: '点击了需要联网开锁', detail: '点击了需要联网开锁 获取连网token失败', upload: true);
showToast('网络访问失败,请检查网络是否正常'.tr, something: () {});
}
}
/// ///
Future<bool> getPermissionStatus() async { Future<bool> getPermissionStatus() async {
@ -285,6 +350,55 @@ class TalkViewLogic extends BaseGetXController {
} }
} }
Future<void> requestPermissions() async {
//
var storageStatus = await Permission.storage.request();
//
var microphoneStatus = await Permission.microphone.request();
if (storageStatus.isGranted && microphoneStatus.isGranted) {
print("Permissions granted");
} else {
print("Permissions denied");
//
if (await Permission.storage.isPermanentlyDenied) {
openAppSettings(); //
}
}
}
Future<void> startRecording() async {
requestPermissions();
if (state.isRecordingScreen.value) {
showToast('录屏已开始,请勿重复点击');
}
bool start = await FlutterScreenRecording.startRecordScreen(
"Screen Recording", //
titleNotification: "Recording in progress", //
messageNotification: "Tap to stop recording", //
);
if (start) {
state.isRecordingScreen.value = true;
}
}
Future<void> stopRecording() async {
String path = await FlutterScreenRecording.stopRecordScreen;
print("Recording saved to: $path");
//
bool? success = await GallerySaver.saveVideo(path);
if (success == true) {
print("Video saved to gallery");
} else {
print("Failed to save video to gallery");
}
showToast('录屏结束,已保存到系统相册');
state.isRecordingScreen.value = false;
}
@override @override
void onReady() { void onReady() {
super.onReady(); super.onReady();
@ -310,12 +424,16 @@ class TalkViewLogic extends BaseGetXController {
// //
_initAudioRecorder(); _initAudioRecorder();
requestPermissions();
} }
@override @override
void onClose() { void onClose() {
_stopPlayG711Data(); _stopPlayG711Data();
state.listData.value = Uint8List(0); state.listData.value = Uint8List(0);
state.audioBuffer.clear();
state.videoBuffer.clear();
_syncTimer?.cancel(); _syncTimer?.cancel();
_syncTimer = null; _syncTimer = null;
} }
@ -387,32 +505,6 @@ class TalkViewLogic extends BaseGetXController {
} }
} }
///
Future<void> startRecording() async {
getPermissionStatus();
bool started =
await FlutterScreenRecording.startRecordScreenAndAudio("Recording");
if (started) {
state.isRecordingScreen.value = true;
}
}
///
Future<void> stopRecording() async {
String path = await FlutterScreenRecording.stopRecordScreen;
if (path != null) {
state.isRecordingScreen.value = false;
//
// await GallerySaver.saveVideo(path).then((bool? success) {});
//
await ImageGallerySaver.saveFile(path);
showToast('录屏已保存到相册'.tr);
} else {
state.isRecordingScreen.value = false;
print("Recording failed");
}
}
/// ///
void _initAudioRecorder() { void _initAudioRecorder() {
state.voiceProcessor = VoiceProcessor.instance; state.voiceProcessor = VoiceProcessor.instance;

View File

@ -1,6 +1,8 @@
import 'dart:async'; import 'dart:async';
import 'dart:convert'; import 'dart:convert';
import 'dart:io'; import 'dart:io';
import 'dart:math';
import 'dart:ui';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
@ -15,6 +17,7 @@ import 'package:star_lock/talk/startChart/constant/talk_status.dart';
import 'package:star_lock/talk/startChart/views/talkView/talk_view_logic.dart'; import 'package:star_lock/talk/startChart/views/talkView/talk_view_logic.dart';
import 'package:star_lock/talk/startChart/views/talkView/talk_view_state.dart'; import 'package:star_lock/talk/startChart/views/talkView/talk_view_state.dart';
import 'package:star_lock/talk/udp/udp_manage.dart';
import '../../../../app_settings/app_colors.dart'; import '../../../../app_settings/app_colors.dart';
import '../../../../tools/showTFView.dart'; import '../../../../tools/showTFView.dart';
@ -35,6 +38,7 @@ class _TalkViewPageState extends State<TalkViewPage>
void initState() { void initState() {
super.initState(); super.initState();
state.listData.value = Uint8List(0);
// //
// state.autoBackTimer = Timer(const Duration(seconds: 30), Get.back); // state.autoBackTimer = Timer(const Duration(seconds: 30), Get.back);
@ -65,43 +69,61 @@ class _TalkViewPageState extends State<TalkViewPage>
alignment: Alignment.center, alignment: Alignment.center,
children: <Widget>[ children: <Widget>[
Obx( Obx(
() => state.listData.value.isEmpty () {
? Image.asset( final screenWidth = MediaQuery.of(context).size.width;
'images/main/monitorBg.png', final screenHeight = MediaQuery.of(context).size.height;
width: ScreenUtil().screenWidth,
height: ScreenUtil().screenHeight, final logicalWidth = MediaQuery.of(context).size.width;
fit: BoxFit.cover, final logicalHeight = MediaQuery.of(context).size.height;
) final devicePixelRatio = MediaQuery.of(context).devicePixelRatio;
: Container(
decoration: state.isRecordingScreen.value //
? BoxDecoration( final physicalWidth = logicalWidth * devicePixelRatio;
border: Border.all(color: Colors.red, width: 1)) final physicalHeight = logicalHeight * devicePixelRatio;
: BoxDecoration(),
child: PopScope( //
final rotatedImageWidth = 480; //
final rotatedImageHeight = 864; //
//
final scaleWidth = physicalWidth / rotatedImageWidth;
final scaleHeight = physicalHeight / rotatedImageHeight;
final scale = max(scaleWidth, scaleHeight); //
return state.listData.value.isEmpty
? Image.asset(
'images/main/monitorBg.png',
width: screenWidth,
height: screenHeight,
fit: BoxFit.cover,
)
: PopScope(
canPop: false, canPop: false,
child: RepaintBoundary( child: RepaintBoundary(
key: state.globalKey, key: state.globalKey,
child: RotatedBox( child: Transform.rotate(
quarterTurns: 1, // 90 1 angle:
child: Image.memory( state.rotateAngle.value * (pi / 180), // 90
state.listData.value, child: Transform.scale(
gaplessPlayback: true, scale: scale, //
width: 1.sw, child: Image.memory(
height: 1.sh, state.listData.value,
fit: BoxFit.cover, gaplessPlayback: true,
filterQuality: FilterQuality.high, fit: BoxFit.cover,
errorBuilder: ( filterQuality: FilterQuality.high,
BuildContext context, errorBuilder: (
Object error, BuildContext context,
StackTrace? stackTrace, Object error,
) { StackTrace? stackTrace,
return Container(color: Colors.transparent); ) {
}, return Container(color: Colors.transparent);
},
),
), ),
), ),
), ),
), );
), },
), ),
Obx(() => state.listData.value.isEmpty Obx(() => state.listData.value.isEmpty
? Positioned( ? Positioned(
@ -200,13 +222,12 @@ class _TalkViewPageState extends State<TalkViewPage>
GestureDetector( GestureDetector(
onTap: () async { onTap: () async {
logic.showToast('功能暂未开放'.tr); logic.showToast('功能暂未开放'.tr);
// if (state.talkStatus.value == TalkStatus.answeredSuccessfully) { // if (
// state.talkStatus.value == TalkStatus.answeredSuccessfully) {
// if (state.isRecordingScreen.value) { // if (state.isRecordingScreen.value) {
// await logic.stopRecording(); // await logic.stopRecording();
// print('停止录屏');
// } else { // } else {
// await logic.startRecording(); // await logic.startRecording();
// print('开始录屏');
// } // }
// } // }
}, },
@ -276,7 +297,14 @@ class _TalkViewPageState extends State<TalkViewPage>
'images/main/icon_lockDetail_monitoringUnlock.png', 'images/main/icon_lockDetail_monitoringUnlock.png',
'开锁', '开锁',
AppColors.mainColor, AppColors.mainColor,
onClick: () {}, onClick: () {
if (UDPManage().remoteUnlock == 1) {
logic.udpOpenDoorAction();
// showDeletPasswordAlertDialog(context);
} else {
logic.showToast('请在锁设置中开启远程开锁'.tr);
}
},
) )
]); ]);
} }
@ -342,7 +370,7 @@ class _TalkViewPageState extends State<TalkViewPage>
context: context, context: context,
builder: (BuildContext context) { builder: (BuildContext context) {
return ShowTFView( return ShowTFView(
title: '请输入位数字开锁密码'.tr, title: '请输入6位数字开锁密码'.tr,
tipTitle: '', tipTitle: '',
controller: state.passwordTF, controller: state.passwordTF,
inputFormatters: <TextInputFormatter>[ inputFormatters: <TextInputFormatter>[
@ -350,22 +378,23 @@ class _TalkViewPageState extends State<TalkViewPage>
FilteringTextInputFormatter.allow(RegExp('[0-9]')), FilteringTextInputFormatter.allow(RegExp('[0-9]')),
], ],
sureClick: () async { sureClick: () async {
// // //
// if (state.passwordTF.text.isEmpty) { // if (state.passwordTF.text.isEmpty) {
// logic.showToast('请输入开锁密码'.tr); // logic.showToast('请输入开锁密码'.tr);
// return; // return;
// } // }
//
// // List<int> numbers = state.passwordTF.text.split('').map((char) => int.parse(char)).toList(); // List<int> numbers = state.passwordTF.text.split('').map((char) => int.parse(char)).toList();
// // //
// // lockID // lockID
// List<int> numbers = <int>[]; // final List<int> numbers = <int>[];
// List<int> lockIDData = utf8.encode(state.passwordTF.text); // final List<int> lockIDData = utf8.encode(state.passwordTF.text);
// numbers.addAll(lockIDData); // numbers.addAll(lockIDData);
// // topBytes = getFixedLengthList(lockIDData, 20 - lockIDData.length); // // topBytes = getFixedLengthList(lockIDData, 20 - lockIDData.length);
// for (int i = 0; i < 6 - lockIDData.length; i++) { // for (int i = 0; i < 6 - lockIDData.length; i++) {
// numbers.add(0); // numbers.add(0);
// } // }
logic.udpOpenDoorAction();
}, },
cancelClick: () { cancelClick: () {
Get.back(); Get.back();
@ -409,6 +438,8 @@ class _TalkViewPageState extends State<TalkViewPage>
state.animationController.dispose(); state.animationController.dispose();
state.realTimePicTimer.cancel(); state.realTimePicTimer.cancel();
state.autoBackTimer.cancel(); state.autoBackTimer.cancel();
state.videoBuffer.clear();
state.listData.value = Uint8List(0);
CallTalk().finishAVData(); CallTalk().finishAVData();
super.dispose(); super.dispose();
} }

View File

@ -10,7 +10,7 @@ import 'package:network_info_plus/network_info_plus.dart';
import 'package:star_lock/talk/startChart/constant/talk_status.dart'; import 'package:star_lock/talk/startChart/constant/talk_status.dart';
import 'package:star_lock/talk/startChart/handle/other/talk_data_repository.dart'; import 'package:star_lock/talk/startChart/handle/other/talk_data_repository.dart';
import 'package:star_lock/talk/startChart/proto/talk_data.pb.dart'; import 'package:star_lock/talk/startChart/proto/talk_data.pb.dart';
import 'package:star_lock/talk/startChart/start_chart_talk_status.dart'; import 'package:star_lock/talk/startChart/status/start_chart_talk_status.dart';
import '../../../../tools/storage.dart'; import '../../../../tools/storage.dart';