package com.tuoheng.machine.config; import com.tuoheng.machine.events.DroneEvent; import com.tuoheng.machine.platform.factory.PlatformStrategyFactory; import com.tuoheng.machine.platform.strategy.DronePlatformStrategy; import com.tuoheng.machine.status.DroneState; import lombok.extern.slf4j.Slf4j; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.statemachine.StateMachine; import org.springframework.statemachine.config.StateMachineBuilder; import org.springframework.statemachine.config.StateMachineFactory; import java.util.EnumSet; import java.util.UUID; /** * 无人机状态机配置(多平台支持版本) * 通过PlatformStrategyFactory动态获取平台特定的Guard、Action和Listener */ @Configuration @Slf4j public class DroneMachineConfig { @Bean(name = "droneStateMachineFactory") public StateMachineFactory droneStateMachineFactory( PlatformStrategyFactory platformStrategyFactory) throws Exception { return new StateMachineFactory() { @Override public StateMachine getStateMachine() { return null; } @Override public StateMachine getStateMachine(String machineId) { try { // 根据无人机SN获取平台策略 DronePlatformStrategy strategy = platformStrategyFactory.getDroneStrategy(machineId); StateMachineBuilder.Builder builder = StateMachineBuilder.builder(); configureStateMachine(builder, strategy); configureStates(builder); configureTransitions(builder, strategy); StateMachine stateMachine = builder.build(); stateMachine.getExtendedState().getVariables().put("machineId", machineId); return stateMachine; } catch (Exception e) { log.error("创建DRONE状态机失败 - 机器ID: {}", machineId, e); throw new RuntimeException("Failed to create drone state machine for: " + machineId, e); } } @Override public StateMachine getStateMachine(UUID uuid) { return null; } }; } private void configureStateMachine( StateMachineBuilder.Builder builder, DronePlatformStrategy strategy) throws Exception { builder.configureConfiguration() .withConfiguration() .autoStartup(true) .listener(strategy.getListener()); } private void configureStates(StateMachineBuilder.Builder builder) throws Exception { builder.configureStates() .withStates() .initial(DroneState.UNKNOWN) .states(EnumSet.of( DroneState.UNKNOWN, DroneState.OFFLINE, DroneState.PREPARING, DroneState.FLYING_PARENT, DroneState.RETURNING_PARENT, DroneState.POINTING_PARENT )) // 飞行阶段子状态 .and() .withStates() .parent(DroneState.FLYING_PARENT) .initial(DroneState.FLYING) .states(EnumSet.of( DroneState.FLYING, DroneState.EMERGENCY_STOP, DroneState.ARRIVED )) // 返航阶段子状态 .and() .withStates() .parent(DroneState.RETURNING_PARENT) .initial(DroneState.RETURNING) .states(EnumSet.of( DroneState.RETURNING, DroneState.RETURN_EMERGENCY_STOP, DroneState.RETURN_COMPLETED )) // 指点操作子状态 .and() .withStates() .parent(DroneState.POINTING_PARENT) .initial(DroneState.POINT_PREPARING) .states(EnumSet.of( DroneState.POINT_PREPARING, DroneState.POINT_FLYING, DroneState.POINT_COMPLETED, DroneState.POINT_CANCELLED )); } private void configureTransitions( StateMachineBuilder.Builder builder, DronePlatformStrategy strategy) throws Exception { builder.configureTransitions() // ========== 从 UNKNOWN 到所有状态的转换(服务器重启后状态同步) ========== // UNKNOWN -> OFFLINE .withExternal() .source(DroneState.UNKNOWN) .target(DroneState.OFFLINE) .event(DroneEvent.DRONE_OFFLINE) .and() // UNKNOWN -> PREPARING .withExternal() .source(DroneState.UNKNOWN) .target(DroneState.PREPARING) .event(DroneEvent.START_PREPARE) .and() // UNKNOWN -> FLYING_PARENT .withExternal() .source(DroneState.UNKNOWN) .target(DroneState.FLYING_PARENT) .event(DroneEvent.START_FLYING) .and() // UNKNOWN -> RETURNING_PARENT .withExternal() .source(DroneState.UNKNOWN) .target(DroneState.RETURNING_PARENT) .event(DroneEvent.START_RETURN) .and() // ========== 基本状态转换 ========== // OFFLINE -> PREPARING .withExternal() .source(DroneState.OFFLINE) .target(DroneState.PREPARING) .event(DroneEvent.START_PREPARE) .action(strategy.getStartPrepareAction()) .and() // PREPARING -> FLYING_PARENT .withExternal() .source(DroneState.PREPARING) .target(DroneState.FLYING_PARENT) .event(DroneEvent.PREPARE_COMPLETED) .action(strategy.getPrepareCompletedAction()) .and() // ========== 飞行阶段内部转换 ========== // FLYING -> EMERGENCY_STOP .withExternal() .source(DroneState.FLYING) .target(DroneState.EMERGENCY_STOP) .event(DroneEvent.EMERGENCY_STOP) .action(strategy.getEmergencyStopAction()) .and() // EMERGENCY_STOP -> FLYING (恢复飞行) .withExternal() .source(DroneState.EMERGENCY_STOP) .target(DroneState.FLYING) .event(DroneEvent.RESUME_FLYING) .action(strategy.getResumeFlyingAction()) .and() // FLYING -> ARRIVED .withExternal() .source(DroneState.FLYING) .target(DroneState.ARRIVED) .event(DroneEvent.ARRIVE) .action(strategy.getArriveAction()) .and() // 注意:EMERGENCY_STOP 不能直接到 ARRIVED(根据注释限制) // ========== 飞行阶段 -> 指点操作 ========== // FLYING -> POINTING_PARENT .withExternal() .source(DroneState.FLYING) .target(DroneState.POINTING_PARENT) .event(DroneEvent.START_POINTING) .action(strategy.getStartPointingAction()) .guard(strategy.getCanPointGuard()) .and() // EMERGENCY_STOP -> POINTING_PARENT .withExternal() .source(DroneState.EMERGENCY_STOP) .target(DroneState.POINTING_PARENT) .event(DroneEvent.START_POINTING) .action(strategy.getStartPointingAction()) .guard(strategy.getCanPointGuard()) .and() // ARRIVED -> POINTING_PARENT .withExternal() .source(DroneState.ARRIVED) .target(DroneState.POINTING_PARENT) .event(DroneEvent.START_POINTING) .action(strategy.getStartPointingAction()) .guard(strategy.getCanPointGuard()) .and() // ========== 飞行阶段 -> 返航 ========== // FLYING -> RETURNING_PARENT .withExternal() .source(DroneState.FLYING) .target(DroneState.RETURNING_PARENT) .event(DroneEvent.START_RETURN) .action(strategy.getStartReturnAction()) .and() // EMERGENCY_STOP -> RETURNING_PARENT .withExternal() .source(DroneState.EMERGENCY_STOP) .target(DroneState.RETURNING_PARENT) .event(DroneEvent.START_RETURN) .action(strategy.getStartReturnAction()) .and() // ARRIVED -> RETURNING_PARENT .withExternal() .source(DroneState.ARRIVED) .target(DroneState.RETURNING_PARENT) .event(DroneEvent.START_RETURN) .action(strategy.getStartReturnAction()) .and() // ========== 返航阶段内部转换 ========== // RETURNING -> RETURN_EMERGENCY_STOP .withExternal() .source(DroneState.RETURNING) .target(DroneState.RETURN_EMERGENCY_STOP) .event(DroneEvent.RETURN_EMERGENCY_STOP) .action(strategy.getReturnEmergencyStopAction()) .and() // RETURN_EMERGENCY_STOP -> RETURNING (恢复返航) .withExternal() .source(DroneState.RETURN_EMERGENCY_STOP) .target(DroneState.RETURNING) .event(DroneEvent.RESUME_RETURN) .action(strategy.getResumeReturnAction()) .and() // RETURNING -> RETURN_COMPLETED .withExternal() .source(DroneState.RETURNING) .target(DroneState.RETURN_COMPLETED) .event(DroneEvent.RETURN_COMPLETED) .action(strategy.getReturnCompletedAction()) .and() // 注意:返航中不能指点(根据注释限制) // 注意:RETURN_COMPLETED 不能回退到 RETURNING 或 RETURN_EMERGENCY_STOP(根据注释限制) // ========== 返航急停 -> 指点操作 ========== // RETURN_EMERGENCY_STOP -> POINTING_PARENT (一键起飞和航线飞行都可以指点) .withExternal() .source(DroneState.RETURN_EMERGENCY_STOP) .target(DroneState.POINTING_PARENT) .event(DroneEvent.START_POINTING) .action(strategy.getStartPointingAction()) .guard(strategy.getCanPointGuard()) .and() // ========== 指点操作内部转换 ========== // POINT_PREPARING -> POINT_FLYING .withExternal() .source(DroneState.POINT_PREPARING) .target(DroneState.POINT_FLYING) .event(DroneEvent.POINT_PREPARE_COMPLETED) .action(strategy.getPointPrepareCompletedAction()) .and() // POINT_FLYING -> POINT_COMPLETED .withExternal() .source(DroneState.POINT_FLYING) .target(DroneState.POINT_COMPLETED) .event(DroneEvent.POINT_FLYING_COMPLETED) .action(strategy.getPointFlyingCompletedAction()) .and() // 任何指点阶段 -> POINT_CANCELLED .withExternal() .source(DroneState.POINT_PREPARING) .target(DroneState.POINT_CANCELLED) .event(DroneEvent.CANCEL_POINT) .action(strategy.getCancelPointAction()) .and() .withExternal() .source(DroneState.POINT_FLYING) .target(DroneState.POINT_CANCELLED) .event(DroneEvent.CANCEL_POINT) .action(strategy.getCancelPointAction()) .and() .withExternal() .source(DroneState.POINT_COMPLETED) .target(DroneState.POINT_CANCELLED) .event(DroneEvent.CANCEL_POINT) .action(strategy.getCancelPointAction()) .and() // ========== 指点操作 -> 飞行/返航 ========== // POINT_COMPLETED -> FLYING .withExternal() .source(DroneState.POINT_COMPLETED) .target(DroneState.FLYING) .event(DroneEvent.POINT_TO_FLYING) .action(strategy.getPointToFlyingAction()) .and() // POINT_CANCELLED -> FLYING .withExternal() .source(DroneState.POINT_CANCELLED) .target(DroneState.FLYING) .event(DroneEvent.POINT_TO_FLYING) .action(strategy.getPointToFlyingAction()) .and() // POINT_COMPLETED -> RETURNING_PARENT .withExternal() .source(DroneState.POINT_COMPLETED) .target(DroneState.RETURNING_PARENT) .event(DroneEvent.POINT_TO_RETURN) .action(strategy.getPointToReturnAction()) .and() // POINT_CANCELLED -> RETURNING_PARENT .withExternal() .source(DroneState.POINT_CANCELLED) .target(DroneState.RETURNING_PARENT) .event(DroneEvent.POINT_TO_RETURN) .action(strategy.getPointToReturnAction()) .and() // POINT_COMPLETED -> RETURN_EMERGENCY_STOP .withExternal() .source(DroneState.POINT_COMPLETED) .target(DroneState.RETURN_EMERGENCY_STOP) .event(DroneEvent.RETURN_EMERGENCY_STOP) .action(strategy.getReturnEmergencyStopAction()) .and() // POINT_COMPLETED -> RETURN_COMPLETED .withExternal() .source(DroneState.POINT_COMPLETED) .target(DroneState.RETURN_COMPLETED) .event(DroneEvent.RETURN_COMPLETED) .action(strategy.getReturnCompletedAction()) .and() // ========== 离线处理 ========== // 任何状态 -> OFFLINE .withExternal() .source(DroneState.FLYING_PARENT) .target(DroneState.OFFLINE) .event(DroneEvent.DRONE_OFFLINE) .action(strategy.getOfflineAction()) .and() .withExternal() .source(DroneState.RETURNING_PARENT) .target(DroneState.OFFLINE) .event(DroneEvent.DRONE_OFFLINE) .action(strategy.getOfflineAction()) .and() .withExternal() .source(DroneState.POINTING_PARENT) .target(DroneState.OFFLINE) .event(DroneEvent.DRONE_OFFLINE) .action(strategy.getOfflineAction()); } }