APP远程遥控推出页面释放权限集成-待测试

This commit is contained in:
2026-04-16 10:49:45 +08:00
parent c45f8ee867
commit 407bcf026c
5 changed files with 102 additions and 9 deletions

View File

@@ -70,4 +70,47 @@ class RemoteHttpDatasource {
return false;
}
}
///app退出远程控制后释放权限
Future<bool> releaseRemoteControlViaHttp( String platform) async {
_logger.logWithLevel("app退出远程控制后释放权限 开始");
final user = await _userStorage.getUser();
if (user == null) {
return false;
}
final token = user.token;
final response = await _dio.post(
'/forward/device/releaseControl',
options: Options(
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer ${token}',
},
),
data: {'platform': "app"});
try {
final responseData = response.data as Map<String, dynamic>;
//debugPrint("📊 [HTTP 响应] 完整数据:$responseData");
_logger.log("releaseRemoteControlViaHttp 响应] 完整数据:$responseData");
// 🔥 关键:先获取响应的 data 字段,再获取 remoteControl
final dataField = responseData['data'] as Map<String, dynamic>?;
if (dataField != null) {
final bool hasRemoteControl = dataField['remoteControl'] as bool? ?? false;
//debugPrint("✅ [HTTP 响应] remoteControl=$hasRemoteControl");
_logger.log("releaseRemoteControlViaHttp响应] remoteControl=$hasRemoteControl");
// 🔥 直接返回 remoteControl 的布尔值
return hasRemoteControl;
} else {
//debugPrint("❌ [HTTP 响应] 缺少 data 字段");
_logger.log("❌ [HTTP 响应] 缺少 data 字段");
return false;
}
} catch (e) {
// debugPrint('❌ [RemoteHttp] 解析响应失败:$e');
_logger.log('❌ [RemoteHttp] 解析响应失败:$e');
return false;
}
}
}

View File

@@ -35,8 +35,6 @@ class RemoteControlRepositoryImpl implements RemoteControlRepository {
void sendControlMachineCmd(MachineControlStatusEntity status) {
// 1. 调用算法:将摇杆坐标 (x, y) 转换为左右轮电机转速
final speeds = _diffSteer.calculate(status.originX, status.originY);
//debugPrint('🎮 [摇杆数据] originX: ${status.originX}, originY: ${status.originY}');
_logger.logWithLevel('⚙️ [电机速度] left: ${speeds['left']}, right: ${speeds['right']}');
@@ -54,15 +52,18 @@ class RemoteControlRepositoryImpl implements RemoteControlRepository {
ignition: status.ignitionStatus,
emergency: status.isEmergency ? 1 : 0,
);
debugPrint('📦 [发送数据] payload: ${payload}');
debugPrint('📦 [发送数据] emergency 字节值:${payload[7]}');
//debugPrint('📦 [发送数据] payload: ${payload}');
_logger.logWithLevel('📦 [发送数据] payload: ${payload}');
//debugPrint('📦 [发送数据] emergency 字节值:${payload[7]}');
_logger.logWithLevel('📦 [发送数据] emergency 字节值:${payload[7]}');
// 3. 调用 TcpClient:发送指令。
// TcpClient.sendRaw 会自动帮你加上 [0xAB, 0xAA] 头和 [0xAA, 0xAB] 尾
_tcpClient.sendRaw(
MachineProtocolConstants.cmdRemoteControl, // 这里通常是 0x00
payload,
);
debugPrint('✅ [TCP] 指令已发送');
//debugPrint('✅ [TCP] 指令已发送');
_logger.logWithLevel('✅ [TCP] 指令已发送');
}
@override
@@ -91,4 +92,9 @@ class RemoteControlRepositoryImpl implements RemoteControlRepository {
_remoteTcp.sendSwitchControlResponse(false, deviceId);
}
}
///app退出远程控制后释放权限
@override
Future<bool> releasePermission(String platform) async {
return await _remoteHttp.releaseRemoteControlViaHttp(platform);
}
}

View File

@@ -20,4 +20,7 @@ abstract class RemoteControlRepository {
/// 新增:响应控制权限 同意和拒绝(发送 0x05 指令)
void respondPermission(bool bool, String deviceId);
///APP 推出远程控制页面后释放权限
Future<bool> releasePermission(String platform);
}

View File

@@ -229,7 +229,15 @@ class RemoteControlCubit extends Cubit<RemoteControlState> {
void startControlLoop() {
_timer?.cancel();
_timer = Timer.periodic(const Duration(milliseconds: 100), (timer) {
// 核心调用:直接把 state 里的实体丢给 repository
// 🔥 安全检查:无权限或急停时不发送
if (!state.hasPermission || state.isEmergency) {
debugPrint('⚠️ [定时器] 跳过发送 - hasPermission=${state.hasPermission}, isEmergency=${state.isEmergency}');
return;
}
debugPrint('⏰ [定时器] 发送控制指令 - originX=${state.controlEntity.originX}, originY=${state.controlEntity.originY}');
_logger.logWithLevel('真实的发送的实体 - originX: ${state.controlEntity.originX}, originY: ${state.controlEntity.originY}');
_repository.sendControlMachineCmd(state.controlEntity);
});
emit(state.copyWith(status: RemoteControlStatus.controlling));
@@ -264,16 +272,36 @@ class RemoteControlCubit extends Cubit<RemoteControlState> {
}
void updateOriginY(int y) {
debugPrint('📥 [updateOriginY] 收到参数 y=$y');
final updatedEntity = state.controlEntity.copyWith(
y: y,
);
debugPrint('📤 [updateOriginY] 创建 updatedEntity.y=${updatedEntity.originY}');
emit(state.copyWith(controlEntity: updatedEntity));
debugPrint('✅ [updateOriginY] emit 完成,当前 state.controlEntity.originY=${state.controlEntity.originY}');
// 🔥 关键修复:如果归零,立即发送停止指令,使用更新后的实体
if (y == 0) {
_logger.logWithLevel('🛑 [updateOriginY] 检测到归零,立即发送停止指令');
debugPrint('🛑 [updateOriginY] 发送 updatedEntity: originX=${updatedEntity.originX}, originY=${updatedEntity.originY}');
_repository.sendControlMachineCmd(updatedEntity);
}
}
void updateOriginX(int x) {
debugPrint('📥 [updateOriginX] 收到参数 x=$x');
final updatedEntity = state.controlEntity.copyWith(
x: x,
);
debugPrint('📤 [updateOriginX] 创建 updatedEntity.x=${updatedEntity.originX}');
emit(state.copyWith(controlEntity: updatedEntity));
debugPrint('✅ [updateOriginX] emit 完成,当前 state.controlEntity.originX=${state.controlEntity.originX}');
// 🔥 关键修复:如果归零,立即发送停止指令,使用更新后的实体
if (x == 0) {
_logger.logWithLevel('🛑 [updateOriginX] 检测到归零,立即发送停止指令');
debugPrint('🛑 [updateOriginX] 发送 updatedEntity: originX=${updatedEntity.originX}, originY=${updatedEntity.originY}');
_repository.sendControlMachineCmd(updatedEntity);
}
}
// 5. 停止控制循环
@@ -416,6 +444,10 @@ class RemoteControlCubit extends Cubit<RemoteControlState> {
return 9999;
}
}
//app退出远程遥控界面释放权限
Future<bool> releasePermission(String platform) async {
return await _repository.releasePermission(platform);
}

View File

@@ -28,11 +28,13 @@ class RemoteControlPage extends StatefulWidget {
class _RemoteControlPageState extends State<RemoteControlPage> {
String _videoStreamUrl = "";
late RemoteControlCubit _cubit;
DevicesCubit? _devicesCubit;
@override
void didChangeDependencies() {
super.didChangeDependencies();
_cubit = context.read<RemoteControlCubit>();
_devicesCubit = context.read<DevicesCubit>();
}
@override
void initState() {
@@ -53,9 +55,16 @@ class _RemoteControlPageState extends State<RemoteControlPage> {
@override
void dispose() {
// 释放远程控制权限
// _cubit.releasePermission("app");
//print("远程控制要推出啦");
final deviceState = _devicesCubit?.state;
if (deviceState?.selectedDevice != null) {
_cubit.releasePermission("app");
}
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge);
// context.read<RemoteControlCubit>().stopControlLoop();
_cubit.stopControlLoop();
super.dispose();
}
@@ -138,7 +147,7 @@ class _RemoteControlPageState extends State<RemoteControlPage> {
width: sideAreaWidth,
child: Align(
alignment: Alignment.bottomCenter,
child: LeftJoystickArea(isLocked: remoteState.isLocked, width: sideAreaWidth * 0.5 * 0.7),
child: LeftJoystickArea(isLocked: remoteState.isLocked, width: sideAreaWidth * 0.45),
),
),
@@ -156,7 +165,7 @@ class _RemoteControlPageState extends State<RemoteControlPage> {
width: sideAreaWidth,
child: Align(
alignment: Alignment.bottomCenter,
child: RightJoystickArea(isLocked: remoteState.isLocked, width: sideAreaWidth * 0.5 * 0.7),
child: RightJoystickArea(isLocked: remoteState.isLocked, width: sideAreaWidth * 0.45),
),
),
],