完成路及规划的作业的开始工作成功.
完成路径规划的暂停功能的对接 完成路径规划的继续功能的对接 完成路径规划的停止功能的对接
This commit is contained in:
@@ -82,6 +82,7 @@ Future<void> init() async {
|
|||||||
sl<TcpClient>(),
|
sl<TcpClient>(),
|
||||||
sl<RoutePlanningRepository>(),
|
sl<RoutePlanningRepository>(),
|
||||||
sl<PathPlanningService>(),
|
sl<PathPlanningService>(),
|
||||||
|
getAppState: () => sl<DevicesCubit>().state.appState,
|
||||||
));
|
));
|
||||||
|
|
||||||
/// 1.2 --- 本地存储 (LocalStorage) ---
|
/// 1.2 --- 本地存储 (LocalStorage) ---
|
||||||
|
|||||||
@@ -13,13 +13,17 @@ class NetMessageDispatcher {
|
|||||||
final TcpClient tcpClient;
|
final TcpClient tcpClient;
|
||||||
final PathPlanningService _pathPlanningService;
|
final PathPlanningService _pathPlanningService;
|
||||||
final RoutePlanningRepository routePlanningRepository;
|
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) {
|
Stream<RawPacket> onCommand(int commandCode) {
|
||||||
return tcpClient.packetStream.where((p) => p.command == commandCode);
|
return tcpClient.packetStream.where((p) => p.command == commandCode);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 示例解析方法:将 0x02 指令解析为 String
|
/// 示例解析方法:将 0x02 指令解析为 String
|
||||||
@@ -59,9 +63,19 @@ class NetMessageDispatcher {
|
|||||||
/// 验证头部:data[0]=0xAB, data[1]=0xAA, data[2]=0x01
|
/// 验证头部:data[0]=0xAB, data[1]=0xAA, data[2]=0x01
|
||||||
/// 检查状态位:data[5] == 0x01 表示回复成功
|
/// 检查状态位:data[5] == 0x01 表示回复成功
|
||||||
Stream<RawPacket> onPathPlanningResponse() {
|
Stream<RawPacket> onPathPlanningResponse() {
|
||||||
|
|
||||||
|
|
||||||
debugPrint('[Dispatcher] 开始监听路径规划指令应答 (CMD: 0x01)');
|
debugPrint('[Dispatcher] 开始监听路径规划指令应答 (CMD: 0x01)');
|
||||||
|
|
||||||
return onCommand(0x01).where((packet) {
|
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>[
|
final fullData = <int>[
|
||||||
0xAB, 0xAA, 0x01,
|
0xAB, 0xAA, 0x01,
|
||||||
@@ -76,7 +90,6 @@ class NetMessageDispatcher {
|
|||||||
fullData[2] == 0x01) {
|
fullData[2] == 0x01) {
|
||||||
|
|
||||||
debugPrint('[Dispatcher] 下位机回复成功 - 完整数据包:${fullData.join(" ")}');
|
debugPrint('[Dispatcher] 下位机回复成功 - 完整数据包:${fullData.join(" ")}');
|
||||||
|
|
||||||
// 检查状态位 (索引 5 对应 payload 的第 2 个字节)
|
// 检查状态位 (索引 5 对应 payload 的第 2 个字节)
|
||||||
if (fullData.length > 5 && fullData[5] == 0x01) {
|
if (fullData.length > 5 && fullData[5] == 0x01) {
|
||||||
debugPrint('✅ [Dispatcher] 状态位验证通过:0x01 - 可以发送下一个指令');
|
debugPrint('✅ [Dispatcher] 状态位验证通过:0x01 - 可以发送下一个指令');
|
||||||
|
|||||||
@@ -267,16 +267,22 @@ class TcpClient {
|
|||||||
void sendPathPoint(RoutePlanSendEntity routePlanSendEntity) {
|
void sendPathPoint(RoutePlanSendEntity routePlanSendEntity) {
|
||||||
if (_socket == null) return;
|
if (_socket == null) return;
|
||||||
final payload = routePlanSendEntity.toBytes();
|
final payload = routePlanSendEntity.toBytes();
|
||||||
final packet = sendRaw(0x01, payload); // 第1种的测试 声明指令结构和类型0x01 为命令类型
|
print("sendPathPoint-0x01开始发送路径点数据");
|
||||||
//_socket!.add(payload);//第二种的测试
|
sendRaw(0x01, payload); // 第1种的测试 声明指令结构和类型0x01 为命令类型
|
||||||
|
// _socket!.add(payload);//第二种的测试
|
||||||
|
print("底层发送指令完成");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void sendDeviceStateChange(RoutePlanSendEntity routePlanSendEntity) {
|
void sendDeviceStateChange(RoutePlanSendEntity routePlanSendEntity) {
|
||||||
if (_socket == null) return;
|
if (_socket == null) return;
|
||||||
final payload = routePlanSendEntity.toBytes();
|
final payload = routePlanSendEntity.toBytes();
|
||||||
_socket!.add(payload);
|
//_socket!.add(payload);
|
||||||
// final packet = sendRaw(0x02, payload);
|
sendRaw(0x02, payload);
|
||||||
|
var counts = routePlanSendEntity.pointCounts;
|
||||||
|
var string = routePlanSendEntity.toString();
|
||||||
|
print("sendDeviceStateChange 底层发送指令完成,数据:$counts");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ import '../models/route_plan_send_entity.dart';
|
|||||||
class RoutePlanningRepositoryImpl implements RoutePlanningRepository {
|
class RoutePlanningRepositoryImpl implements RoutePlanningRepository {
|
||||||
final TcpClient tcp;
|
final TcpClient tcp;
|
||||||
late PathPlanner _planner;
|
late PathPlanner _planner;
|
||||||
|
// 🔥 新增:存储 AppState 的引用
|
||||||
|
dynamic _appState;
|
||||||
|
|
||||||
RoutePlanningRepositoryImpl({required this.tcp}) { // ✅ 加 {required} 和类型注解
|
RoutePlanningRepositoryImpl({required this.tcp}) { // ✅ 加 {required} 和类型注解
|
||||||
_planner = PathPlanner(tcp);
|
_planner = PathPlanner(tcp);
|
||||||
@@ -15,6 +17,7 @@ class RoutePlanningRepositoryImpl implements RoutePlanningRepository {
|
|||||||
@override
|
@override
|
||||||
Future<void> startRoutePlanning(Queue<DeviceAddPathPointModel> locationQueue) async {
|
Future<void> startRoutePlanning(Queue<DeviceAddPathPointModel> locationQueue) async {
|
||||||
// 直接传入 DeviceAddPathPointModel 列表(无需转换)
|
// 直接传入 DeviceAddPathPointModel 列表(无需转换)
|
||||||
|
print("[底层开始发送指令了]");
|
||||||
final List<DeviceAddPathPointModel> locations = locationQueue.toList();
|
final List<DeviceAddPathPointModel> locations = locationQueue.toList();
|
||||||
_planner.startRoutePlanning(locations);
|
_planner.startRoutePlanning(locations);
|
||||||
}
|
}
|
||||||
@@ -36,6 +39,15 @@ class RoutePlanningRepositoryImpl implements RoutePlanningRepository {
|
|||||||
// TODO: implement stopRoutePlanning
|
// TODO: implement stopRoutePlanning
|
||||||
_planner.stopRoutePlanning();
|
_planner.stopRoutePlanning();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
getCurrentAppState() {
|
||||||
|
// TODO: implement getCurrentAppState
|
||||||
|
return _appState;
|
||||||
|
}
|
||||||
|
void setAppState(dynamic state) {
|
||||||
|
_appState = state;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// PathPlanner
|
// PathPlanner
|
||||||
@@ -47,6 +59,7 @@ class PathPlanner {
|
|||||||
PathPlanner(this.tcpClient);
|
PathPlanner(this.tcpClient);
|
||||||
|
|
||||||
void sendNextLocation() {
|
void sendNextLocation() {
|
||||||
|
print("[在发送指令sendNextLocation方法中]");
|
||||||
if (isStart && locationQueue.isEmpty) {
|
if (isStart && locationQueue.isEmpty) {
|
||||||
isStart = false;
|
isStart = false;
|
||||||
print("[track]");
|
print("[track]");
|
||||||
@@ -71,7 +84,9 @@ class PathPlanner {
|
|||||||
void startRoutePlanning(List<DeviceAddPathPointModel> locations) {
|
void startRoutePlanning(List<DeviceAddPathPointModel> locations) {
|
||||||
locationQueue.addAll(locations);
|
locationQueue.addAll(locations);
|
||||||
isStart = true;
|
isStart = true;
|
||||||
|
print("[发送指令要转换类型了完成]");
|
||||||
sendNextLocation();
|
sendNextLocation();
|
||||||
|
|
||||||
}
|
}
|
||||||
/// 暂停
|
/// 暂停
|
||||||
void pauseRPWork() {
|
void pauseRPWork() {
|
||||||
|
|||||||
@@ -15,4 +15,6 @@ abstract class RoutePlanningRepository {
|
|||||||
Future<void> pauseRPWork();
|
Future<void> pauseRPWork();
|
||||||
/// Resume
|
/// Resume
|
||||||
Future<void> resumeRPWork();
|
Future<void> resumeRPWork();
|
||||||
|
/// Get current app state
|
||||||
|
getCurrentAppState() {}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -351,13 +351,20 @@ class DevicesCubit extends Cubit<DevicesState> {
|
|||||||
|
|
||||||
// 开始路径规划
|
// 开始路径规划
|
||||||
Future<void> startRoutePlanning(Queue<DeviceAddPathPointModel> locationQueue) async {
|
Future<void> startRoutePlanning(Queue<DeviceAddPathPointModel> locationQueue) async {
|
||||||
|
print("cubit层开始路径规划");
|
||||||
// 清空全局 Service 中的队列
|
// 清空全局 Service 中的队列
|
||||||
// _routePlanningUseCase.clearLocationQueue();
|
// _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));
|
emit(state.copyWith(isLoading: true));
|
||||||
//传入全局的Service 中路径规划队列
|
//传入全局的Service 中路径规划队列
|
||||||
Queue<DeviceAddPathPointModel> queue = _pathPlanningService.getQueue() ;
|
Queue<DeviceAddPathPointModel> queue = _pathPlanningService.getQueue() ;
|
||||||
|
print('📦 从 Service 获取的队列长度:${queue.length}');
|
||||||
final result = await _routePlanningUseCase.startRoutePlanning(queue);
|
final result = await _routePlanningUseCase.startRoutePlanning(queue);
|
||||||
result.fold(
|
result.fold(
|
||||||
(failure) => emit(state.copyWith(isLoading: false, errorMessage: failure.message ?? '路径规划启动失败')),
|
(failure) => emit(state.copyWith(isLoading: false, errorMessage: failure.message ?? '路径规划启动失败')),
|
||||||
@@ -386,4 +393,9 @@ class DevicesCubit extends Cubit<DevicesState> {
|
|||||||
final result = await _routePlanningUseCase.stopRoutePlanning();
|
final result = await _routePlanningUseCase.stopRoutePlanning();
|
||||||
result.fold((failure) => emit(state.copyWith(isLoading: false, errorMessage: failure.message ?? '停止失败')), (_) => emit(state.copyWith(isLoading: false)));
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ class DevicesState extends Equatable {
|
|||||||
DeviceOperationType? operationType,
|
DeviceOperationType? operationType,
|
||||||
List<Map<String, dynamic>>? pathData,
|
List<Map<String, dynamic>>? pathData,
|
||||||
List<DeviceAddPathPointModel>? generatedPath,
|
List<DeviceAddPathPointModel>? generatedPath,
|
||||||
|
AppState? appState,
|
||||||
}) {
|
}) {
|
||||||
return DevicesState(
|
return DevicesState(
|
||||||
devices: devices ?? this.devices,
|
devices: devices ?? this.devices,
|
||||||
@@ -68,6 +69,7 @@ class DevicesState extends Equatable {
|
|||||||
workRecords: workRecords ?? this.workRecords,
|
workRecords: workRecords ?? this.workRecords,
|
||||||
operationType: operationType ?? this.operationType, // 更新操作类型
|
operationType: operationType ?? this.operationType, // 更新操作类型
|
||||||
generatedPath: generatedPath ?? this.generatedPath, // 更新生成的路径数据
|
generatedPath: generatedPath ?? this.generatedPath, // 更新生成的路径数据
|
||||||
|
appState: appState ?? this.appState, // 更新应用状态
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,5 +82,6 @@ class DevicesState extends Equatable {
|
|||||||
pathData,
|
pathData,
|
||||||
operationType,
|
operationType,
|
||||||
generatedPath,
|
generatedPath,
|
||||||
|
appState,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ class PathPlanningService {
|
|||||||
|
|
||||||
/// 🔥 存:生成路径后立即存储
|
/// 🔥 存:生成路径后立即存储
|
||||||
void updateQueue(List<DeviceAddPathPointModel> locations) {
|
void updateQueue(List<DeviceAddPathPointModel> locations) {
|
||||||
|
debugPrint('进入[PathPlanningService]updateQueue方法尝试更新空队列');
|
||||||
if (locations.isEmpty) {
|
if (locations.isEmpty) {
|
||||||
debugPrint('⚠️ [PathPlanningService] 尝试更新空队列');
|
debugPrint('⚠️ [PathPlanningService] 尝试更新空队列');
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -1421,11 +1421,12 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
|||||||
// 步骤2:将 List 转换为 Queue(队列)
|
// 步骤2:将 List 转换为 Queue(队列)
|
||||||
final Queue<work_area_model.DeviceAddPathPointModel> pathQueue = Queue.from(startWorkList);
|
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);
|
await context.read<DevicesCubit>().startRoutePlanning(pathQueue);
|
||||||
|
context.read<DevicesCubit>().updateAppState(AppState.routePlanning);
|
||||||
debugPrint('开始作业:${_selectedPlot!.plotName},路径数据:$gcjPathPoints');
|
|
||||||
|
|
||||||
// 可选:显示作业提示
|
// 可选:显示作业提示
|
||||||
ToastUtils.showSuccess(context, '作业已开始');
|
ToastUtils.showSuccess(context, '作业已开始');
|
||||||
//ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('作业已开始'), backgroundColor: Colors.green));
|
//ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('作业已开始'), backgroundColor: Colors.green));
|
||||||
@@ -1436,8 +1437,8 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
|||||||
setState(() {
|
setState(() {
|
||||||
_workStatus = WorkStatus.paused;
|
_workStatus = WorkStatus.paused;
|
||||||
});
|
});
|
||||||
|
context.read<DevicesCubit>().updateAppState(AppState.none);
|
||||||
await context.read<DevicesCubit>().pauseRoutePlanning();
|
await context.read<DevicesCubit>().pauseRoutePlanning();
|
||||||
|
|
||||||
debugPrint('暂停作业:${_selectedPlot!.plotName}');
|
debugPrint('暂停作业:${_selectedPlot!.plotName}');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1445,9 +1446,11 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
|||||||
setState(() {
|
setState(() {
|
||||||
_workStatus = WorkStatus.idle;
|
_workStatus = WorkStatus.idle;
|
||||||
});
|
});
|
||||||
|
context.read<DevicesCubit>().updateAppState(AppState.none);
|
||||||
await context.read<DevicesCubit>().stopRoutePlanning();
|
await context.read<DevicesCubit>().stopRoutePlanning();
|
||||||
|
//修改App的状态
|
||||||
debugPrint('停止作业:${_selectedPlot!.plotName}');
|
debugPrint('停止作业:${_selectedPlot!.plotName}');
|
||||||
ToastUtils.showError(context, '作业已停止');
|
///ToastUtils.showError(context, '作业已停止');
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 继续作业
|
/// 继续作业
|
||||||
@@ -1455,7 +1458,9 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
|||||||
setState(() {
|
setState(() {
|
||||||
_workStatus = WorkStatus.working;
|
_workStatus = WorkStatus.working;
|
||||||
});
|
});
|
||||||
|
context.read<DevicesCubit>().updateAppState(AppState.routePlanning);
|
||||||
await context.read<DevicesCubit>().resumeRoutePlanning();
|
await context.read<DevicesCubit>().resumeRoutePlanning();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _showDeleteConfirmDialog(PlotData plot, Function(PlotData) onDelete) {
|
void _showDeleteConfirmDialog(PlotData plot, Function(PlotData) onDelete) {
|
||||||
|
|||||||
Reference in New Issue
Block a user