Merge branch 'feature/my' of http://1.95.137.212:57001/APP/FlutterApp into feature/my
This commit is contained in:
@@ -82,6 +82,7 @@ Future<void> init() async {
|
||||
sl<TcpClient>(),
|
||||
sl<RoutePlanningRepository>(),
|
||||
sl<PathPlanningService>(),
|
||||
getAppState: () => sl<DevicesCubit>().state.appState,
|
||||
));
|
||||
|
||||
/// 1.2 --- 本地存储 (LocalStorage) ---
|
||||
|
||||
@@ -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 - 可以发送下一个指令');
|
||||
|
||||
@@ -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");
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -15,4 +15,6 @@ abstract class RoutePlanningRepository {
|
||||
Future<void> pauseRPWork();
|
||||
/// Resume
|
||||
Future<void> resumeRPWork();
|
||||
/// Get current app state
|
||||
getCurrentAppState() {}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
];
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ class PathPlanningService {
|
||||
|
||||
/// 🔥 存:生成路径后立即存储
|
||||
void updateQueue(List<DeviceAddPathPointModel> locations) {
|
||||
debugPrint('进入[PathPlanningService]updateQueue方法尝试更新空队列');
|
||||
if (locations.isEmpty) {
|
||||
debugPrint('⚠️ [PathPlanningService] 尝试更新空队列');
|
||||
return;
|
||||
|
||||
@@ -1424,11 +1424,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));
|
||||
@@ -1439,8 +1440,8 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
||||
setState(() {
|
||||
_workStatus = WorkStatus.paused;
|
||||
});
|
||||
context.read<DevicesCubit>().updateAppState(AppState.none);
|
||||
await context.read<DevicesCubit>().pauseRoutePlanning();
|
||||
|
||||
debugPrint('暂停作业:${_selectedPlot!.plotName}');
|
||||
}
|
||||
|
||||
@@ -1448,9 +1449,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, '作业已停止');
|
||||
}
|
||||
|
||||
/// 继续作业
|
||||
@@ -1458,7 +1461,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) {
|
||||
|
||||
Reference in New Issue
Block a user