Files
flutterApp/lib/features/remote_control/presentation/bloc/remote_control_cubit.dart

198 lines
6.4 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import 'dart:async';
import 'dart:convert';
import 'dart:ffi';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:maibu_satabot_v2/features/remote_control/data/models/running_status_model.dart';
import 'package:maibu_satabot_v2/features/remote_control/presentation/bloc/remote_control_state.dart';
import '../../../../core/network/net_message_dispatcher.dart';
import '../../domain/entities/machine_control_status_entity.dart';
import '../../domain/repositories/remote_control_repository.dart';
import '../../domain/usecase/remote_control_usecase.dart';
class RemoteControlCubit extends Cubit<RemoteControlState> {
final RemoteControlRepository _repository;
final RequestControlPermissionUseCase _requestControlPermissionUseCase;
Timer? _timer;
StreamSubscription? _kickOutSub; // 新增:用于管理监听生命周期
final NetMessageDispatcher dispatcher;
RemoteControlCubit(this._repository, this._requestControlPermissionUseCase, this.dispatcher)
: super(
RemoteControlState(
controlEntity: MachineControlStatusEntity(),
runningStatusModel: RunningStatusModel(),
),
) {
_initPacketListener();
}
// 1. 初始化回包监听 (如 0x12 权限)
// void _initPacketListener() {
// _repository.responseStream.listen((packet) {
// if (packet.command == 0x12) {
// // 根据负载判断是否有权限,更新状态
// emit(state.copyWith(hasPermission: true));
// }
// });
// }
void _initPacketListener() {
print('>>> [RemoteControl] begin 初始化 0x12 监听器');
_kickOutSub?.cancel(); // 防止重复监听
_kickOutSub = dispatcher.onCommand(0x12).listen((packet) {
print('>>> [RemoteControl] 收到 0x12 原始包,payload 长度=${packet.payload.length}');
try {
// 🔥 关键:手动去掉最后 2 个 CRC 字节
String jsonString;
if (packet.payload.length > 2) {
jsonString = utf8.decode(packet.payload.sublist(0, packet.payload.length - 2));
} else {
jsonString = utf8.decode(packet.payload);
}
print('>>> [RemoteControl] 去除 CRC 后的 JSON: $jsonString');
final jsonMap = jsonDecode(jsonString);
final respond = jsonMap['request'] ?? '';
print('>>> [RemoteControl] ✅ 响应结果:$respond');
// 🔥 当 Web 端推送 switch_control 权限时,更新状态触发弹窗
if (respond == 'switch_control') {
print('>>> [RemoteControl] ✅ 获得控制权 (respond=switch_control),准备打开弹窗');
emit(state.copyWith(hasPermission: true, showPermissionRequestDialog: true));
} else if (respond == 'have_logged_in') {
// 如果是异地登录,也显示弹窗提示
print('>>> [RemoteControl] ⚠️ 检测到异地登录');
emit(state.copyWith(showPermissionRequestDialog: true));
}
} catch (e) {
print('>>> [RemoteControl] ❌ 解析失败:$e');
}
});
print('>>> [RemoteControl] ✅ 0x12 监听器已建立完成');
}
// 2. 开启 100ms 控制循环 (在进入遥控页面或点击“开始”时调用)
void startControlLoop() {
_timer?.cancel();
_timer = Timer.periodic(const Duration(milliseconds: 100), (timer) {
// 核心调用:直接把 state 里的实体丢给 repository
_repository.sendControlMachineCmd(state.controlEntity);
});
emit(state.copyWith(status: RemoteControlStatus.controlling));
}
// 3. 更新摇杆数据
void updateJoystick(double x, double y) {
final updatedEntity = state.controlEntity.copyWith(
x: x.toInt(),
y: y.toInt(),
);
emit(state.copyWith(controlEntity: updatedEntity));
}
// 4. 更新功能开关 (比如割刀速度、灯光、点火等)
void updateFunction({int? mower, int? lift, int? ignition, bool? emergency}) {
final updatedEntity = state.controlEntity.copyWith(
mower: mower,
lift: lift,
ignition: ignition,
emergency: emergency,
);
emit(state.copyWith(controlEntity: updatedEntity));
}
void updateOriginY(int y) {
final updatedEntity = state.controlEntity.copyWith(
y: y,
);
emit(state.copyWith(controlEntity: updatedEntity));
}
void updateOriginX(int x) {
final updatedEntity = state.controlEntity.copyWith(
x: x,
);
emit(state.copyWith(controlEntity: updatedEntity));
}
// 5. 停止控制循环
void stopControlLoop() {
_timer?.cancel();
_timer = null;
emit(state.copyWith(status: RemoteControlStatus.initial));
}
void toggleLock() {}
void togglePermissionDialog(bool show) {
emit(state.copyWith(showPermissionRequestDialog: show));
}
void requestControlPermission() {
// 1. 关闭弹窗
emit(state.copyWith(showPermissionRequestDialog: false));
// 2. 这里执行你发送 0x12 指令的逻辑
// _sendProtocolData(0x12, ...);
}
void toggleLeftPip() => emit(state.copyWith(showLeftPip: !state.showLeftPip));
void toggleRightPip() =>
emit(state.copyWith(showRightPip: !state.showRightPip));
@override
Future<void> close() {
_timer?.cancel(); // 退出页面时务必销毁定时器
return super.close();
}
void updateChassisLift(int i) {}
void updateEmergency(bool bool) {}
void respondPermission(bool bool) {}
void requestControlPermissionS(String deviceName, String deviceId) async {
// 1. 关闭弹窗
emit(state.copyWith(showPermissionRequestDialog: false));
// 2. 调用 UseCase
final result = await _requestControlPermissionUseCase(
RequestControlPermissionParams(
deviceName: deviceName,
deviceId: deviceId,
),
);
// 3. 处理结果
result.fold(
(failure) {
print('❌ [RemoteControl] 请求控制权限失败:${failure.message}');
// 可以在这里显示错误提示或重新打开弹窗
emit(state.copyWith(showPermissionRequestDialog: true));
},
(success) {
// 更新状态
print('✅ [RemoteControl] 请求控制权限成功:$success');
///处理result
if(success){
emit(state.copyWith(hasPermission: true));
}else{
emit(state.copyWith(hasPermission: false));
}
print('✅ c:$success');
// 权限申请已发送,等待 0x12 回包更新状态
},
);
}
}