修改方法

This commit is contained in:
孙小云 2025-12-16 17:40:31 +08:00
parent 092043895c
commit 22a81cff7e
12 changed files with 114 additions and 36 deletions

View File

@ -4,11 +4,13 @@ import com.tuoheng.machine.events.AirportEvent;
import com.tuoheng.machine.platform.factory.PlatformStrategyFactory; import com.tuoheng.machine.platform.factory.PlatformStrategyFactory;
import com.tuoheng.machine.platform.strategy.AirportPlatformStrategy; import com.tuoheng.machine.platform.strategy.AirportPlatformStrategy;
import com.tuoheng.machine.status.AirportState; import com.tuoheng.machine.status.AirportState;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.statemachine.StateMachine; import org.springframework.statemachine.StateMachine;
import org.springframework.statemachine.config.StateMachineBuilder; import org.springframework.statemachine.config.StateMachineBuilder;
import org.springframework.statemachine.config.StateMachineFactory; import org.springframework.statemachine.config.StateMachineFactory;
import org.springframework.stereotype.Component;
import java.util.EnumSet; import java.util.EnumSet;
import java.util.UUID; import java.util.UUID;
@ -18,6 +20,7 @@ import java.util.UUID;
* 通过PlatformStrategyFactory动态获取平台特定的GuardAction和Listener * 通过PlatformStrategyFactory动态获取平台特定的GuardAction和Listener
*/ */
@Configuration @Configuration
@Slf4j
public class AirportMachineConfig { public class AirportMachineConfig {
@Bean(name = "airportStateMachineFactory") @Bean(name = "airportStateMachineFactory")
@ -45,6 +48,7 @@ public class AirportMachineConfig {
stateMachine.getExtendedState().getVariables().put("machineId", machineId); stateMachine.getExtendedState().getVariables().put("machineId", machineId);
return stateMachine; return stateMachine;
} catch (Exception e) { } catch (Exception e) {
log.error("创建AIRPORT机巢状态机失败 - 机器ID: {}", machineId, e);
throw new RuntimeException("Failed to create state machine for: " + machineId, e); throw new RuntimeException("Failed to create state machine for: " + machineId, e);
} }
} }

View File

@ -4,6 +4,7 @@ import com.tuoheng.machine.events.CoverEvent;
import com.tuoheng.machine.platform.factory.PlatformStrategyFactory; import com.tuoheng.machine.platform.factory.PlatformStrategyFactory;
import com.tuoheng.machine.platform.strategy.CoverPlatformStrategy; import com.tuoheng.machine.platform.strategy.CoverPlatformStrategy;
import com.tuoheng.machine.status.CoverState; import com.tuoheng.machine.status.CoverState;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.statemachine.StateMachine; import org.springframework.statemachine.StateMachine;
@ -18,6 +19,7 @@ import java.util.UUID;
* 通过PlatformStrategyFactory动态获取平台特定的GuardAction和Listener * 通过PlatformStrategyFactory动态获取平台特定的GuardAction和Listener
*/ */
@Configuration @Configuration
@Slf4j
public class CoverMachineConfig { public class CoverMachineConfig {
@Bean @Bean
@ -44,6 +46,7 @@ public class CoverMachineConfig {
stateMachine.getExtendedState().getVariables().put("machineId", machineId); stateMachine.getExtendedState().getVariables().put("machineId", machineId);
return stateMachine; return stateMachine;
} catch (Exception e) { } catch (Exception e) {
log.error("创建COVER状态机失败 - 机器ID: {}", machineId, e);
throw new RuntimeException("Failed to create cover state machine for: " + machineId, e); throw new RuntimeException("Failed to create cover state machine for: " + machineId, e);
} }
} }

View File

@ -4,6 +4,7 @@ import com.tuoheng.machine.events.DrcEvent;
import com.tuoheng.machine.platform.factory.PlatformStrategyFactory; import com.tuoheng.machine.platform.factory.PlatformStrategyFactory;
import com.tuoheng.machine.platform.strategy.DrcPlatformStrategy; import com.tuoheng.machine.platform.strategy.DrcPlatformStrategy;
import com.tuoheng.machine.status.DrcState; import com.tuoheng.machine.status.DrcState;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.statemachine.StateMachine; import org.springframework.statemachine.StateMachine;
@ -18,11 +19,13 @@ import java.util.UUID;
* 通过PlatformStrategyFactory动态获取平台特定的GuardAction和Listener * 通过PlatformStrategyFactory动态获取平台特定的GuardAction和Listener
*/ */
@Configuration @Configuration
@Slf4j
public class DrcMachineConfig { public class DrcMachineConfig {
@Bean(name = "drcStateMachineFactory") @Bean(name = "drcStateMachineFactory")
public StateMachineFactory<DrcState, DrcEvent> drcStateMachineFactory( public StateMachineFactory<DrcState, DrcEvent> drcStateMachineFactory(
PlatformStrategyFactory platformStrategyFactory) throws Exception { PlatformStrategyFactory platformStrategyFactory) throws Exception {
return new StateMachineFactory<DrcState, DrcEvent>() { return new StateMachineFactory<DrcState, DrcEvent>() {
@Override @Override
public StateMachine<DrcState, DrcEvent> getStateMachine() { public StateMachine<DrcState, DrcEvent> getStateMachine() {
@ -44,6 +47,7 @@ public class DrcMachineConfig {
stateMachine.getExtendedState().getVariables().put("machineId", machineId); stateMachine.getExtendedState().getVariables().put("machineId", machineId);
return stateMachine; return stateMachine;
} catch (Exception e) { } catch (Exception e) {
log.error("创建DRC状态机失败 - 机器ID: {}", machineId, e);
throw new RuntimeException("Failed to create DRC state machine for: " + machineId, e); throw new RuntimeException("Failed to create DRC state machine for: " + machineId, e);
} }
} }
@ -87,7 +91,7 @@ public class DrcMachineConfig {
.withExternal() .withExternal()
.source(DrcState.UNKNOWN) .source(DrcState.UNKNOWN)
.target(DrcState.ENTERING) .target(DrcState.ENTERING)
.event(DrcEvent.ENTER) .event(DrcEvent.ENTERING)
.and() .and()
// UNKNOWN -> ENTERED // UNKNOWN -> ENTERED
@ -101,7 +105,7 @@ public class DrcMachineConfig {
.withExternal() .withExternal()
.source(DrcState.UNKNOWN) .source(DrcState.UNKNOWN)
.target(DrcState.EXITING) .target(DrcState.EXITING)
.event(DrcEvent.EXIT) .event(DrcEvent.EXITING)
.and() .and()
// ========== 正常状态转换 Guard Action ========== // ========== 正常状态转换 Guard Action ==========
@ -109,7 +113,7 @@ public class DrcMachineConfig {
.withExternal() .withExternal()
.source(DrcState.EXITED) .source(DrcState.EXITED)
.target(DrcState.ENTERING) .target(DrcState.ENTERING)
.event(DrcEvent.ENTER) .event(DrcEvent.ENTERING)
.action(strategy.getEnterAction()) .action(strategy.getEnterAction())
.guard(strategy.getCanEnterGuard()) .guard(strategy.getCanEnterGuard())
.and() .and()
@ -126,7 +130,7 @@ public class DrcMachineConfig {
.withExternal() .withExternal()
.source(DrcState.ENTERED) .source(DrcState.ENTERED)
.target(DrcState.EXITING) .target(DrcState.EXITING)
.event(DrcEvent.EXIT) .event(DrcEvent.EXITING)
.action(strategy.getExitAction()) .action(strategy.getExitAction())
.guard(strategy.getCanExitGuard()) .guard(strategy.getCanExitGuard())
.and() .and()

View File

@ -4,6 +4,7 @@ import com.tuoheng.machine.events.DroneEvent;
import com.tuoheng.machine.platform.factory.PlatformStrategyFactory; import com.tuoheng.machine.platform.factory.PlatformStrategyFactory;
import com.tuoheng.machine.platform.strategy.DronePlatformStrategy; import com.tuoheng.machine.platform.strategy.DronePlatformStrategy;
import com.tuoheng.machine.status.DroneState; import com.tuoheng.machine.status.DroneState;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.statemachine.StateMachine; import org.springframework.statemachine.StateMachine;
@ -18,6 +19,7 @@ import java.util.UUID;
* 通过PlatformStrategyFactory动态获取平台特定的GuardAction和Listener * 通过PlatformStrategyFactory动态获取平台特定的GuardAction和Listener
*/ */
@Configuration @Configuration
@Slf4j
public class DroneMachineConfig { public class DroneMachineConfig {
@Bean(name = "droneStateMachineFactory") @Bean(name = "droneStateMachineFactory")
@ -44,6 +46,7 @@ public class DroneMachineConfig {
stateMachine.getExtendedState().getVariables().put("machineId", machineId); stateMachine.getExtendedState().getVariables().put("machineId", machineId);
return stateMachine; return stateMachine;
} catch (Exception e) { } catch (Exception e) {
log.error("创建DRONE状态机失败 - 机器ID: {}", machineId, e);
throw new RuntimeException("Failed to create drone state machine for: " + machineId, e); throw new RuntimeException("Failed to create drone state machine for: " + machineId, e);
} }
} }

View File

@ -9,7 +9,7 @@ public enum DrcEvent {
* 进入DRC模式指令 * 进入DRC模式指令
* 触发源: 用户指令 * 触发源: 用户指令
*/ */
ENTER, ENTERING,
/** /**
* 进入DRC模式完成 * 进入DRC模式完成
@ -21,7 +21,7 @@ public enum DrcEvent {
* 退出DRC模式指令 * 退出DRC模式指令
* 触发源: 用户指令/自动 * 触发源: 用户指令/自动
*/ */
EXIT, EXITING,
/** /**
* 退出DRC模式完成 * 退出DRC模式完成

View File

@ -8,6 +8,8 @@ import com.tuoheng.machine.status.DrcState;
import org.springframework.statemachine.StateContext; import org.springframework.statemachine.StateContext;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import java.util.concurrent.CompletableFuture;
@Slf4j @Slf4j
@Component @Component
public class DjiExitAction extends ExitAction { public class DjiExitAction extends ExitAction {
@ -20,6 +22,10 @@ public class DjiExitAction extends ExitAction {
@Override @Override
public void execute(StateContext<DrcState, DrcEvent> context) { public void execute(StateContext<DrcState, DrcEvent> context) {
String machineId = (String) context.getExtendedState().getVariables().get("machineId"); String machineId = (String) context.getExtendedState().getVariables().get("machineId");
log.info("[DJI] 退出DRC模式: %s", machineId); log.info("[DJI] {} 退出DRC模式: %s 判断外部命令是否成功", machineId);
/**
* 发生命令的结果是失败或者超时了这边需要抛出异常
*/
throw new RuntimeException("");
} }
} }

View File

@ -22,7 +22,9 @@ public class DjiCanExitGuard extends CanExitGuard {
@Override @Override
public boolean evaluate(StateContext<DrcState, DrcEvent> context) { public boolean evaluate(StateContext<DrcState, DrcEvent> context) {
// DJI平台特定的退出DRC模式检查逻辑 String machineId = (String) context.getExtendedState().getVariables().get("machineId");
log.info("[DJI] {} 退出DRC模式: %s 执行外部命令", machineId);
// 外部命令执行成功返回true,执行失败返回false
return true; return true;
} }
} }

View File

@ -1,16 +1,27 @@
package com.tuoheng.machine.impl.dji.listener; package com.tuoheng.machine.impl.dji.listener;
import com.tuoheng.machine.events.DrcEvent;
import com.tuoheng.machine.listener.DefaultDrcListener; 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; import org.springframework.stereotype.Component;
/** /**
* DJI平台DRC状态监听器 * DJI平台DRC状态监听器
*/ */
@Component @Component
@Slf4j
public class DjiDrcListener extends DefaultDrcListener { public class DjiDrcListener extends DefaultDrcListener {
@Override @Override
public String getName() { public String getName() {
return "DJI-DRC"; return "DJI-DRC";
} }
@Override
public void stateEntered(State<DrcState, DrcEvent> state) {
log.debug("[{}] 大疆进入状态: {}", getName(), state.getId());
}
} }

View File

@ -13,6 +13,8 @@ import org.springframework.statemachine.StateMachine;
import org.springframework.statemachine.state.State; import org.springframework.statemachine.state.State;
import org.springframework.statemachine.transition.Transition; import org.springframework.statemachine.transition.Transition;
import java.util.concurrent.CompletableFuture;
/** /**
* 默认DRC状态监听器 * 默认DRC状态监听器
* 提供基础的状态变化监听功能各平台可以继承并定制 * 提供基础的状态变化监听功能各平台可以继承并定制
@ -31,6 +33,7 @@ public abstract class DefaultDrcListener implements PlatformListener<DrcState, D
@Override @Override
public void stateEntered(State<DrcState, DrcEvent> state) { public void stateEntered(State<DrcState, DrcEvent> state) {
log.debug("[{}] 进入状态: {}", getName(), state.getId()); log.debug("[{}] 进入状态: {}", getName(), state.getId());
} }
@Override @Override
@ -91,5 +94,6 @@ public abstract class DefaultDrcListener implements PlatformListener<DrcState, D
@Override @Override
public void stateContext(StateContext<DrcState, DrcEvent> stateContext) { public void stateContext(StateContext<DrcState, DrcEvent> stateContext) {
// 默认不处理 // 默认不处理
} }
} }

View File

@ -315,11 +315,11 @@ public abstract class AbsSystemManager implements ISystemManager {
case EXITED: case EXITED:
return DrcEvent.EXITED; return DrcEvent.EXITED;
case ENTERING: case ENTERING:
return DrcEvent.ENTER; return DrcEvent.ENTERING;
case ENTERED: case ENTERED:
return DrcEvent.ENTERED; return DrcEvent.ENTERED;
case EXITING: case EXITING:
return DrcEvent.EXIT; return DrcEvent.EXITING;
default: default:
return null; return null;
} }

View File

@ -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

View File

@ -1,18 +1,13 @@
package com.tuoheng.machine; package com.tuoheng.machine;
import com.tuoheng.machine.platform.PlatformType; import com.tuoheng.machine.events.DrcEvent;
import com.tuoheng.machine.platform.factory.PlatformStrategyFactory;
import com.tuoheng.machine.repository.MachinePlatTypeRepository;
import com.tuoheng.machine.service.DrcMachineService; import com.tuoheng.machine.service.DrcMachineService;
import com.tuoheng.machine.status.DrcState;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.statemachine.StateMachine;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.when;
/** /**
* DRC状态机测试 * DRC状态机测试
@ -22,31 +17,65 @@ import static org.mockito.Mockito.when;
@Slf4j @Slf4j
public class DrcStateMachineTest { public class DrcStateMachineTest {
@Autowired
private DrcMachineService drcMachineService;
@Autowired @Autowired
private PlatformStrategyFactory platformStrategyFactory; DrcMachineService drcMachineService;
@MockBean
private MachinePlatTypeRepository machinePlatTypeRepository;
private static final String TEST_AIRPORT_SN = "test-airport-001";
/**
* 测试 Spring Boot 依赖注入是否正常工作
*/
@Test @Test
public void testAutowiredInjection() { public void testDrcMachineService(){
// 验证 PlatformStrategyFactory 是否成功注入 String sn = "airport-001";
assertNotNull(platformStrategyFactory, "PlatformStrategyFactory 应该被成功注入"); /**
// 验证 DrcMachineService 是否成功注入 * 不存在的会报错,需要在 MachinePlatTypeRepository 里面定义有这个机场编号
assertNotNull(drcMachineService, "DrcMachineService 应该被成功注入"); */
// 验证 AirportPlatformRepository Mock 是否成功 try {
assertNotNull(machinePlatTypeRepository, "AirportPlatformRepository Mock 应该被成功创建"); StateMachine<DrcState, DrcEvent> stateMachine =
drcMachineService.getOrCreateStateMachine("airport-001--2");
}catch (RuntimeException runtimeException){}
StateMachine<DrcState, DrcEvent> 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"));
} }
} }