From 22a81cff7eff9d4fb874f76f3b8d77123ffe605d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AD=99=E5=B0=8F=E4=BA=91?= Date: Tue, 16 Dec 2025 17:40:31 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../machine/config/AirportMachineConfig.java | 4 + .../machine/config/CoverMachineConfig.java | 3 + .../machine/config/DrcMachineConfig.java | 12 ++- .../machine/config/DroneMachineConfig.java | 3 + .../com/tuoheng/machine/events/DrcEvent.java | 4 +- .../impl/dji/action/drc/DjiExitAction.java | 8 +- .../impl/dji/guard/drc/DjiCanExitGuard.java | 4 +- .../impl/dji/listener/DjiDrcListener.java | 11 +++ .../machine/listener/DefaultDrcListener.java | 4 + .../machine/manager/AbsSystemManager.java | 4 +- src/main/resources/application.yml | 12 +++ .../tuoheng/machine/DrcStateMachineTest.java | 81 +++++++++++++------ 12 files changed, 114 insertions(+), 36 deletions(-) create mode 100644 src/main/resources/application.yml diff --git a/src/main/java/com/tuoheng/machine/config/AirportMachineConfig.java b/src/main/java/com/tuoheng/machine/config/AirportMachineConfig.java index 714754c..6613356 100644 --- a/src/main/java/com/tuoheng/machine/config/AirportMachineConfig.java +++ b/src/main/java/com/tuoheng/machine/config/AirportMachineConfig.java @@ -4,11 +4,13 @@ import com.tuoheng.machine.events.AirportEvent; import com.tuoheng.machine.platform.factory.PlatformStrategyFactory; import com.tuoheng.machine.platform.strategy.AirportPlatformStrategy; import com.tuoheng.machine.status.AirportState; +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 org.springframework.stereotype.Component; import java.util.EnumSet; import java.util.UUID; @@ -18,6 +20,7 @@ import java.util.UUID; * 通过PlatformStrategyFactory动态获取平台特定的Guard、Action和Listener */ @Configuration +@Slf4j public class AirportMachineConfig { @Bean(name = "airportStateMachineFactory") @@ -45,6 +48,7 @@ public class AirportMachineConfig { stateMachine.getExtendedState().getVariables().put("machineId", machineId); return stateMachine; } catch (Exception e) { + log.error("创建AIRPORT机巢状态机失败 - 机器ID: {}", machineId, e); throw new RuntimeException("Failed to create state machine for: " + machineId, e); } } diff --git a/src/main/java/com/tuoheng/machine/config/CoverMachineConfig.java b/src/main/java/com/tuoheng/machine/config/CoverMachineConfig.java index 6ca4d77..be9d1f5 100644 --- a/src/main/java/com/tuoheng/machine/config/CoverMachineConfig.java +++ b/src/main/java/com/tuoheng/machine/config/CoverMachineConfig.java @@ -4,6 +4,7 @@ import com.tuoheng.machine.events.CoverEvent; import com.tuoheng.machine.platform.factory.PlatformStrategyFactory; import com.tuoheng.machine.platform.strategy.CoverPlatformStrategy; import com.tuoheng.machine.status.CoverState; +import lombok.extern.slf4j.Slf4j; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.statemachine.StateMachine; @@ -18,6 +19,7 @@ import java.util.UUID; * 通过PlatformStrategyFactory动态获取平台特定的Guard、Action和Listener */ @Configuration +@Slf4j public class CoverMachineConfig { @Bean @@ -44,6 +46,7 @@ public class CoverMachineConfig { stateMachine.getExtendedState().getVariables().put("machineId", machineId); return stateMachine; } catch (Exception e) { + log.error("创建COVER状态机失败 - 机器ID: {}", machineId, e); throw new RuntimeException("Failed to create cover state machine for: " + machineId, e); } } diff --git a/src/main/java/com/tuoheng/machine/config/DrcMachineConfig.java b/src/main/java/com/tuoheng/machine/config/DrcMachineConfig.java index 1b36841..5eceaca 100644 --- a/src/main/java/com/tuoheng/machine/config/DrcMachineConfig.java +++ b/src/main/java/com/tuoheng/machine/config/DrcMachineConfig.java @@ -4,6 +4,7 @@ import com.tuoheng.machine.events.DrcEvent; import com.tuoheng.machine.platform.factory.PlatformStrategyFactory; import com.tuoheng.machine.platform.strategy.DrcPlatformStrategy; import com.tuoheng.machine.status.DrcState; +import lombok.extern.slf4j.Slf4j; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.statemachine.StateMachine; @@ -18,11 +19,13 @@ import java.util.UUID; * 通过PlatformStrategyFactory动态获取平台特定的Guard、Action和Listener */ @Configuration +@Slf4j public class DrcMachineConfig { @Bean(name = "drcStateMachineFactory") public StateMachineFactory drcStateMachineFactory( PlatformStrategyFactory platformStrategyFactory) throws Exception { + return new StateMachineFactory() { @Override public StateMachine getStateMachine() { @@ -44,6 +47,7 @@ public class DrcMachineConfig { stateMachine.getExtendedState().getVariables().put("machineId", machineId); return stateMachine; } catch (Exception e) { + log.error("创建DRC状态机失败 - 机器ID: {}", machineId, e); throw new RuntimeException("Failed to create DRC state machine for: " + machineId, e); } } @@ -87,7 +91,7 @@ public class DrcMachineConfig { .withExternal() .source(DrcState.UNKNOWN) .target(DrcState.ENTERING) - .event(DrcEvent.ENTER) + .event(DrcEvent.ENTERING) .and() // UNKNOWN -> ENTERED @@ -101,7 +105,7 @@ public class DrcMachineConfig { .withExternal() .source(DrcState.UNKNOWN) .target(DrcState.EXITING) - .event(DrcEvent.EXIT) + .event(DrcEvent.EXITING) .and() // ========== 正常状态转换(带 Guard 和 Action) ========== @@ -109,7 +113,7 @@ public class DrcMachineConfig { .withExternal() .source(DrcState.EXITED) .target(DrcState.ENTERING) - .event(DrcEvent.ENTER) + .event(DrcEvent.ENTERING) .action(strategy.getEnterAction()) .guard(strategy.getCanEnterGuard()) .and() @@ -126,7 +130,7 @@ public class DrcMachineConfig { .withExternal() .source(DrcState.ENTERED) .target(DrcState.EXITING) - .event(DrcEvent.EXIT) + .event(DrcEvent.EXITING) .action(strategy.getExitAction()) .guard(strategy.getCanExitGuard()) .and() diff --git a/src/main/java/com/tuoheng/machine/config/DroneMachineConfig.java b/src/main/java/com/tuoheng/machine/config/DroneMachineConfig.java index 2ea5eeb..0b0a5ad 100644 --- a/src/main/java/com/tuoheng/machine/config/DroneMachineConfig.java +++ b/src/main/java/com/tuoheng/machine/config/DroneMachineConfig.java @@ -4,6 +4,7 @@ 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; @@ -18,6 +19,7 @@ import java.util.UUID; * 通过PlatformStrategyFactory动态获取平台特定的Guard、Action和Listener */ @Configuration +@Slf4j public class DroneMachineConfig { @Bean(name = "droneStateMachineFactory") @@ -44,6 +46,7 @@ public class DroneMachineConfig { 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); } } diff --git a/src/main/java/com/tuoheng/machine/events/DrcEvent.java b/src/main/java/com/tuoheng/machine/events/DrcEvent.java index f522698..4309a63 100644 --- a/src/main/java/com/tuoheng/machine/events/DrcEvent.java +++ b/src/main/java/com/tuoheng/machine/events/DrcEvent.java @@ -9,7 +9,7 @@ public enum DrcEvent { * 进入DRC模式指令 * 触发源: 用户指令 */ - ENTER, + ENTERING, /** * 进入DRC模式完成 @@ -21,7 +21,7 @@ public enum DrcEvent { * 退出DRC模式指令 * 触发源: 用户指令/自动 */ - EXIT, + EXITING, /** * 退出DRC模式完成 diff --git a/src/main/java/com/tuoheng/machine/impl/dji/action/drc/DjiExitAction.java b/src/main/java/com/tuoheng/machine/impl/dji/action/drc/DjiExitAction.java index 994c23e..2c3134b 100644 --- a/src/main/java/com/tuoheng/machine/impl/dji/action/drc/DjiExitAction.java +++ b/src/main/java/com/tuoheng/machine/impl/dji/action/drc/DjiExitAction.java @@ -8,6 +8,8 @@ import com.tuoheng.machine.status.DrcState; import org.springframework.statemachine.StateContext; import org.springframework.stereotype.Component; +import java.util.concurrent.CompletableFuture; + @Slf4j @Component public class DjiExitAction extends ExitAction { @@ -20,6 +22,10 @@ public class DjiExitAction extends ExitAction { @Override public void execute(StateContext context) { String machineId = (String) context.getExtendedState().getVariables().get("machineId"); - log.info("[DJI] 退出DRC模式: %s", machineId); + log.info("[DJI] {} 退出DRC模式: %s 判断外部命令是否成功", machineId); + /** + * 发生命令的结果是失败,或者超时了,这边需要抛出异常 + */ + throw new RuntimeException(""); } } diff --git a/src/main/java/com/tuoheng/machine/impl/dji/guard/drc/DjiCanExitGuard.java b/src/main/java/com/tuoheng/machine/impl/dji/guard/drc/DjiCanExitGuard.java index f74951e..b3665c6 100644 --- a/src/main/java/com/tuoheng/machine/impl/dji/guard/drc/DjiCanExitGuard.java +++ b/src/main/java/com/tuoheng/machine/impl/dji/guard/drc/DjiCanExitGuard.java @@ -22,7 +22,9 @@ public class DjiCanExitGuard extends CanExitGuard { @Override public boolean evaluate(StateContext context) { - // DJI平台特定的退出DRC模式检查逻辑 + String machineId = (String) context.getExtendedState().getVariables().get("machineId"); + log.info("[DJI] {} 退出DRC模式: %s 执行外部命令", machineId); + // 外部命令执行成功返回true,执行失败返回false return true; } } diff --git a/src/main/java/com/tuoheng/machine/impl/dji/listener/DjiDrcListener.java b/src/main/java/com/tuoheng/machine/impl/dji/listener/DjiDrcListener.java index dfaf135..b5c0319 100644 --- a/src/main/java/com/tuoheng/machine/impl/dji/listener/DjiDrcListener.java +++ b/src/main/java/com/tuoheng/machine/impl/dji/listener/DjiDrcListener.java @@ -1,16 +1,27 @@ package com.tuoheng.machine.impl.dji.listener; +import com.tuoheng.machine.events.DrcEvent; import com.tuoheng.machine.listener.DefaultDrcListener; +import com.tuoheng.machine.status.DrcState; +import lombok.extern.slf4j.Slf4j; +import org.springframework.statemachine.state.State; import org.springframework.stereotype.Component; /** * DJI平台DRC状态监听器 */ @Component +@Slf4j public class DjiDrcListener extends DefaultDrcListener { @Override public String getName() { return "DJI-DRC"; } + + @Override + public void stateEntered(State state) { + log.debug("[{}] 大疆进入状态: {}", getName(), state.getId()); + + } } diff --git a/src/main/java/com/tuoheng/machine/listener/DefaultDrcListener.java b/src/main/java/com/tuoheng/machine/listener/DefaultDrcListener.java index 30151ce..9dbe7fb 100644 --- a/src/main/java/com/tuoheng/machine/listener/DefaultDrcListener.java +++ b/src/main/java/com/tuoheng/machine/listener/DefaultDrcListener.java @@ -13,6 +13,8 @@ import org.springframework.statemachine.StateMachine; import org.springframework.statemachine.state.State; import org.springframework.statemachine.transition.Transition; +import java.util.concurrent.CompletableFuture; + /** * 默认DRC状态监听器 * 提供基础的状态变化监听功能,各平台可以继承并定制 @@ -31,6 +33,7 @@ public abstract class DefaultDrcListener implements PlatformListener state) { log.debug("[{}] 进入状态: {}", getName(), state.getId()); + } @Override @@ -91,5 +94,6 @@ public abstract class DefaultDrcListener implements PlatformListener stateContext) { // 默认不处理 + } } diff --git a/src/main/java/com/tuoheng/machine/manager/AbsSystemManager.java b/src/main/java/com/tuoheng/machine/manager/AbsSystemManager.java index f2fe988..62dab6d 100644 --- a/src/main/java/com/tuoheng/machine/manager/AbsSystemManager.java +++ b/src/main/java/com/tuoheng/machine/manager/AbsSystemManager.java @@ -315,11 +315,11 @@ public abstract class AbsSystemManager implements ISystemManager { case EXITED: return DrcEvent.EXITED; case ENTERING: - return DrcEvent.ENTER; + return DrcEvent.ENTERING; case ENTERED: return DrcEvent.ENTERED; case EXITING: - return DrcEvent.EXIT; + return DrcEvent.EXITING; default: return null; } diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml new file mode 100644 index 0000000..a6b9f83 --- /dev/null +++ b/src/main/resources/application.yml @@ -0,0 +1,12 @@ +spring: + application: + name: thingsboard-client-demo + +logging: + level: + root: DEBUG + com.tuoheng: DEBUG + org.springframework: ERROR + org.springframework.web: ERROR + java.lang: ERROR + reactor.util: INFO \ No newline at end of file diff --git a/src/test/java/com/tuoheng/machine/DrcStateMachineTest.java b/src/test/java/com/tuoheng/machine/DrcStateMachineTest.java index 182c401..ae1d152 100644 --- a/src/test/java/com/tuoheng/machine/DrcStateMachineTest.java +++ b/src/test/java/com/tuoheng/machine/DrcStateMachineTest.java @@ -1,18 +1,13 @@ package com.tuoheng.machine; -import com.tuoheng.machine.platform.PlatformType; -import com.tuoheng.machine.platform.factory.PlatformStrategyFactory; -import com.tuoheng.machine.repository.MachinePlatTypeRepository; +import com.tuoheng.machine.events.DrcEvent; import com.tuoheng.machine.service.DrcMachineService; +import com.tuoheng.machine.status.DrcState; import lombok.extern.slf4j.Slf4j; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.MockBean; - -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.Mockito.when; +import org.springframework.statemachine.StateMachine; /** * DRC状态机测试 @@ -22,31 +17,65 @@ import static org.mockito.Mockito.when; @Slf4j public class DrcStateMachineTest { - @Autowired - private DrcMachineService drcMachineService; @Autowired - private PlatformStrategyFactory platformStrategyFactory; + DrcMachineService drcMachineService; - @MockBean - private MachinePlatTypeRepository machinePlatTypeRepository; - - private static final String TEST_AIRPORT_SN = "test-airport-001"; - - /** - * 测试 Spring Boot 依赖注入是否正常工作 - */ @Test - public void testAutowiredInjection() { + public void testDrcMachineService(){ - // 验证 PlatformStrategyFactory 是否成功注入 - assertNotNull(platformStrategyFactory, "PlatformStrategyFactory 应该被成功注入"); - // 验证 DrcMachineService 是否成功注入 - assertNotNull(drcMachineService, "DrcMachineService 应该被成功注入"); - // 验证 AirportPlatformRepository Mock 是否成功 - assertNotNull(machinePlatTypeRepository, "AirportPlatformRepository Mock 应该被成功创建"); + String sn = "airport-001"; + /** + * 不存在的会报错,需要在 MachinePlatTypeRepository 里面定义有这个机场编号 + */ + try { + StateMachine stateMachine = + drcMachineService.getOrCreateStateMachine("airport-001--2"); + }catch (RuntimeException runtimeException){} + StateMachine stateMachine = drcMachineService.getStateMachine("airport-001"); + drcMachineService.getOrCreateStateMachine("airport-001"); + stateMachine = drcMachineService.getStateMachine("airport-001"); + /** + * 打印一下当前的状态 + */ + log.debug(drcMachineService.getCurrentStates("airport-001")); + + /** + * 从UnKnown状态可以走到任意状态 + */ + drcMachineService.sendEvent(sn,DrcEvent.ENTERED); + + /** + * ENTERED无法进入ENTERING DrcMachineConfig 里面配置的 + */ + log.debug(String.valueOf(drcMachineService.sendEvent(sn,DrcEvent.ENTERING))); + + /** + * 现在是 ENTERED,但是你还想进入ENTERED ,这个是不可以的 + */ + log.debug(String.valueOf(drcMachineService.sendEvent(sn,DrcEvent.ENTERED))); + + /** + * 打印一下当前的状态 + */ + log.debug(drcMachineService.getCurrentStates("airport-001")); + + /** + * 变成退出中;这个时候需要在 DjiCanExitGuard 中编写退出的代码(调用三方接口) + * DjiExitAction 里面判断状态是否真的变化了 + */ + log.debug(String.valueOf(drcMachineService.sendEvent(sn,DrcEvent.EXITING))); + + /** + * 打印一下当前的状态 + */ + log.debug(drcMachineService.getCurrentStates("airport-001")); + +// log.debug(String.valueOf(drcMachineService.sendEvent(sn,DrcEvent.EXITED))); +// +// log.debug(drcMachineService.getCurrentStates("airport-001")); } }