完成路及规划的作业的开始工作成功.

完成路径规划的暂停功能的对接
完成路径规划的继续功能的对接
完成路径规划的停止功能的对接
This commit is contained in:
2026-03-11 10:01:36 +08:00
parent 394348b231
commit b6e4189573
9 changed files with 71 additions and 13 deletions

View File

@@ -82,6 +82,7 @@ Future<void> init() async {
sl<TcpClient>(),
sl<RoutePlanningRepository>(),
sl<PathPlanningService>(),
getAppState: () => sl<DevicesCubit>().state.appState,
));
/// 1.2 --- 本地存储 (LocalStorage) ---

View File

@@ -13,13 +13,17 @@ class NetMessageDispatcher {
final TcpClient tcpClient;
final PathPlanningService _pathPlanningService;
final RoutePlanningRepository routePlanningRepository;
// 🔥 修改:使用回调函数获取 AppState
final Function? getAppState;
NetMessageDispatcher(this.tcpClient, this.routePlanningRepository, this._pathPlanningService);
NetMessageDispatcher(this.tcpClient, this.routePlanningRepository, this._pathPlanningService, {this.getAppState});
/// 过滤特定指令的流
Stream<RawPacket> onCommand(int commandCode) {
return tcpClient.packetStream.where((p) => p.command == commandCode);
}
/// 示例解析方法:将 0x02 指令解析为 String
@@ -59,9 +63,19 @@ class NetMessageDispatcher {
/// 验证头部:data[0]=0xAB, data[1]=0xAA, data[2]=0x01
/// 检查状态位:data[5] == 0x01 表示回复成功
Stream<RawPacket> onPathPlanningResponse() {
debugPrint('[Dispatcher] 开始监听路径规划指令应答 (CMD: 0x01)');
return onCommand(0x01).where((packet) {
// 🔥 修改:使用回调检查 AppState
if (getAppState != null) {
final currentState = getAppState!();
if (currentState.toString() == 'AppState.none') {
debugPrint('⚠️ [Dispatcher] 当前 AppState 为 none,停止处理路径规划指令');
return false;
}
}
// 构造完整数据包用于验证
final fullData = <int>[
0xAB, 0xAA, 0x01,
@@ -76,7 +90,6 @@ class NetMessageDispatcher {
fullData[2] == 0x01) {
debugPrint('[Dispatcher] 下位机回复成功 - 完整数据包:${fullData.join(" ")}');
// 检查状态位 (索引 5 对应 payload 的第 2 个字节)
if (fullData.length > 5 && fullData[5] == 0x01) {
debugPrint('✅ [Dispatcher] 状态位验证通过:0x01 - 可以发送下一个指令');

View File

@@ -267,16 +267,22 @@ class TcpClient {
void sendPathPoint(RoutePlanSendEntity routePlanSendEntity) {
if (_socket == null) return;
final payload = routePlanSendEntity.toBytes();
final packet = sendRaw(0x01, payload); // 第1种的测试 声明指令结构和类型0x01 为命令类型
//_socket!.add(payload);//第二种的测试
print("sendPathPoint-0x01开始发送路径点数据");
sendRaw(0x01, payload); // 第1种的测试 声明指令结构和类型0x01 为命令类型
// _socket!.add(payload);//第二种的测试
print("底层发送指令完成");
}
void sendDeviceStateChange(RoutePlanSendEntity routePlanSendEntity) {
if (_socket == null) return;
final payload = routePlanSendEntity.toBytes();
_socket!.add(payload);
// final packet = sendRaw(0x02, payload);
//_socket!.add(payload);
sendRaw(0x02, payload);
var counts = routePlanSendEntity.pointCounts;
var string = routePlanSendEntity.toString();
print("sendDeviceStateChange 底层发送指令完成,数据:$counts");
}

View File

@@ -8,6 +8,8 @@ import '../models/route_plan_send_entity.dart';
class RoutePlanningRepositoryImpl implements RoutePlanningRepository {
final TcpClient tcp;
late PathPlanner _planner;
// 🔥 新增:存储 AppState 的引用
dynamic _appState;
RoutePlanningRepositoryImpl({required this.tcp}) { // ✅ 加 {required} 和类型注解
_planner = PathPlanner(tcp);
@@ -15,6 +17,7 @@ class RoutePlanningRepositoryImpl implements RoutePlanningRepository {
@override
Future<void> startRoutePlanning(Queue<DeviceAddPathPointModel> locationQueue) async {
// 直接传入 DeviceAddPathPointModel 列表(无需转换)
print("[底层开始发送指令了]");
final List<DeviceAddPathPointModel> locations = locationQueue.toList();
_planner.startRoutePlanning(locations);
}
@@ -36,6 +39,15 @@ class RoutePlanningRepositoryImpl implements RoutePlanningRepository {
// TODO: implement stopRoutePlanning
_planner.stopRoutePlanning();
}
@override
getCurrentAppState() {
// TODO: implement getCurrentAppState
return _appState;
}
void setAppState(dynamic state) {
_appState = state;
}
}
// PathPlanner
@@ -47,6 +59,7 @@ class PathPlanner {
PathPlanner(this.tcpClient);
void sendNextLocation() {
print("[在发送指令sendNextLocation方法中]");
if (isStart && locationQueue.isEmpty) {
isStart = false;
print("[track]");
@@ -71,7 +84,9 @@ class PathPlanner {
void startRoutePlanning(List<DeviceAddPathPointModel> locations) {
locationQueue.addAll(locations);
isStart = true;
print("[发送指令要转换类型了完成]");
sendNextLocation();
}
/// 暂停
void pauseRPWork() {

View File

@@ -15,4 +15,6 @@ abstract class RoutePlanningRepository {
Future<void> pauseRPWork();
/// Resume
Future<void> resumeRPWork();
/// Get current app state
getCurrentAppState() {}
}

View File

@@ -351,13 +351,20 @@ class DevicesCubit extends Cubit<DevicesState> {
// 开始路径规划
Future<void> startRoutePlanning(Queue<DeviceAddPathPointModel> locationQueue) async {
print("cubit层开始路径规划");
// 清空全局 Service 中的队列
// _routePlanningUseCase.clearLocationQueue();
_pathPlanningService.updateQueue(locationQueue as List<DeviceAddPathPointModel>);
final List<DeviceAddPathPointModel> pathList = locationQueue.toList();
print('✅ 队列转换为 List,长度:${pathList.length}');
_pathPlanningService.updateQueue(pathList);
print('✅ 队列更新成功');
// 开始路径规划
emit(state.copyWith(isLoading: true));
//传入全局的Service 中路径规划队列
Queue<DeviceAddPathPointModel> queue = _pathPlanningService.getQueue() ;
print('📦 从 Service 获取的队列长度:${queue.length}');
final result = await _routePlanningUseCase.startRoutePlanning(queue);
result.fold(
(failure) => emit(state.copyWith(isLoading: false, errorMessage: failure.message ?? '路径规划启动失败')),
@@ -386,4 +393,9 @@ class DevicesCubit extends Cubit<DevicesState> {
final result = await _routePlanningUseCase.stopRoutePlanning();
result.fold((failure) => emit(state.copyWith(isLoading: false, errorMessage: failure.message ?? '停止失败')), (_) => emit(state.copyWith(isLoading: false)));
}
void updateAppState(AppState appState) {
emit(state.copyWith(appState: appState));
(_routePlanningUseCase as dynamic).repository.setAppState(appState);
}
}

View File

@@ -56,6 +56,7 @@ class DevicesState extends Equatable {
DeviceOperationType? operationType,
List<Map<String, dynamic>>? pathData,
List<DeviceAddPathPointModel>? generatedPath,
AppState? appState,
}) {
return DevicesState(
devices: devices ?? this.devices,
@@ -68,6 +69,7 @@ class DevicesState extends Equatable {
workRecords: workRecords ?? this.workRecords,
operationType: operationType ?? this.operationType, // 更新操作类型
generatedPath: generatedPath ?? this.generatedPath, // 更新生成的路径数据
appState: appState ?? this.appState, // 更新应用状态
);
}
@@ -80,5 +82,6 @@ class DevicesState extends Equatable {
pathData,
operationType,
generatedPath,
appState,
];
}

View File

@@ -17,6 +17,7 @@ class PathPlanningService {
/// 🔥 存:生成路径后立即存储
void updateQueue(List<DeviceAddPathPointModel> locations) {
debugPrint('进入[PathPlanningService]updateQueue方法尝试更新空队列');
if (locations.isEmpty) {
debugPrint('⚠️ [PathPlanningService] 尝试更新空队列');
return;

View File

@@ -1421,11 +1421,12 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
// 步骤2:将 List 转换为 Queue(队列)
final Queue<work_area_model.DeviceAddPathPointModel> pathQueue = Queue.from(startWorkList);
// 步骤3:调用 Cubit 方法(类型匹配)
debugPrint('🚀 开始作业:${_selectedPlot?.plotName ?? "未命名"},路径点数量:${pathQueue.length}');
debugPrint('第一个点 WGS84: ${pathQueue.first.latitude}, ${pathQueue.first.longitude}');
// 步骤 3:调用 Cubit 方法(类型匹配)
await context.read<DevicesCubit>().startRoutePlanning(pathQueue);
debugPrint('开始作业:${_selectedPlot!.plotName},路径数据:$gcjPathPoints');
context.read<DevicesCubit>().updateAppState(AppState.routePlanning);
// 可选:显示作业提示
ToastUtils.showSuccess(context, '作业已开始');
//ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('作业已开始'), backgroundColor: Colors.green));
@@ -1436,8 +1437,8 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
setState(() {
_workStatus = WorkStatus.paused;
});
context.read<DevicesCubit>().updateAppState(AppState.none);
await context.read<DevicesCubit>().pauseRoutePlanning();
debugPrint('暂停作业:${_selectedPlot!.plotName}');
}
@@ -1445,9 +1446,11 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
setState(() {
_workStatus = WorkStatus.idle;
});
context.read<DevicesCubit>().updateAppState(AppState.none);
await context.read<DevicesCubit>().stopRoutePlanning();
//修改App的状态
debugPrint('停止作业:${_selectedPlot!.plotName}');
ToastUtils.showError(context, '作业已停止');
///ToastUtils.showError(context, '作业已停止');
}
/// 继续作业
@@ -1455,7 +1458,9 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
setState(() {
_workStatus = WorkStatus.working;
});
context.read<DevicesCubit>().updateAppState(AppState.routePlanning);
await context.read<DevicesCubit>().resumeRoutePlanning();
}
void _showDeleteConfirmDialog(PlotData plot, Function(PlotData) onDelete) {