多平台支持

This commit is contained in:
孙小云 2025-12-15 17:21:20 +08:00
parent 6501986e3d
commit fa6ad4f8f9
40 changed files with 1913 additions and 176 deletions

View File

@ -0,0 +1,279 @@
# 多平台机巢状态机架构说明
## 架构概述
本系统采用**策略模式 + 工厂模式**实现多平台支持允许DJI、AUTEL、YUNEEC等不同无人机平台共存并独立运行。
## 核心设计
### 1. 平台类型枚举 (PlatformType)
```
- DJI (大疆)
- AUTEL (道通)
- YUNEEC (昊翔)
```
### 2. 平台策略接口
#### AirportPlatformStrategy
定义机巢平台需要实现的所有Guard、Action和Listener
- Guards: CanOnlineGuard, CanOfflineGuard, IsDebugModeGuard等
- Actions: OnlineAction, OfflineAction, OpenDebugModeAction等
- Listener: 状态变化监听器
#### CoverPlatformStrategy
定义舱门平台需要实现的所有Guard、Action和Listener
- Guards: CanOpenGuard, CanCloseGuard, IsOpenedGuard等
- Actions: OpenAction, CloseAction, OpenedAction等
- Listener: 状态变化监听器
### 3. 平台策略工厂 (PlatformStrategyFactory)
**核心功能:**
- 根据机巢SN从数据库查询平台类型
- 返回对应平台的策略实现
- 自动注册所有平台策略实现
**关键方法:**
```java
AirportPlatformStrategy getAirportStrategy(String airportSn)
CoverPlatformStrategy getCoverStrategy(String airportSn)
PlatformType getPlatformType(String airportSn)
```
### 4. 数据库映射 (AirportPlatformRepository)
**存储结构:**
```
机巢SN -> 平台类型
airport-001 -> DJI
airport-002 -> AUTEL
airport-003 -> DJI
airport-004 -> YUNEEC
```
**说明:** 当前使用内存Map模拟数据库实际使用时替换为真实数据库查询。
### 5. 默认Listener实现
#### DefaultAirportListener
提供机巢状态变化的基础监听功能:
- 状态进入/退出日志
- 状态转换日志
- 事件未接受日志
- 状态机启动/停止日志
#### DefaultCoverListener
提供舱门状态变化的基础监听功能(同上)
**特点:** 各平台可以继承默认Listener并定制自己的逻辑。
## 目录结构
```
com.tuoheng.status.airport
├── platform
│ ├── PlatformType.java # 平台类型枚举
│ ├── strategy # 策略接口
│ │ ├── PlatformAction.java
│ │ ├── PlatformGuard.java
│ │ ├── PlatformListener.java
│ │ ├── AirportPlatformStrategy.java
│ │ └── CoverPlatformStrategy.java
│ ├── factory
│ │ └── PlatformStrategyFactory.java # 平台策略工厂
│ ├── repository
│ │ └── AirportPlatformRepository.java # 数据库映射
│ └── impl # 平台实现
│ └── dji # DJI平台实现
│ ├── DjiAirportPlatformStrategy.java
│ ├── DjiCoverPlatformStrategy.java
│ ├── action
│ │ ├── airport # 机巢Action
│ │ │ ├── DjiOnlineAction.java
│ │ │ ├── DjiOfflineAction.java
│ │ │ ├── DjiOpenDebugModeAction.java
│ │ │ ├── DjiCloseDebugModeAction.java
│ │ │ ├── DjiRebootAction.java
│ │ │ └── DjiRebootCompletedAction.java
│ │ └── cover # 舱门Action
│ │ ├── DjiOpenCoverAction.java
│ │ ├── DjiCoverOpenedAction.java
│ │ ├── DjiCloseCoverAction.java
│ │ ├── DjiCoverClosedAction.java
│ │ ├── DjiCoverErrorAction.java
│ │ └── DjiCoverResetAction.java
│ └── guard
│ ├── airport # 机巢Guard
│ │ ├── DjiCanOnlineGuard.java
│ │ ├── DjiCanOfflineGuard.java
│ │ ├── DjiIsDebugModeGuard.java
│ │ ├── DjiIsNotDebugModeGuard.java
│ │ ├── DjiCanCloseDebugModeGuard.java
│ │ └── DjiIsRebootCompletedGuard.java
│ └── cover # 舱门Guard
│ ├── DjiCanOpenCoverGuard.java
│ ├── DjiCanCloseCoverGuard.java
│ ├── DjiIsCoverOpenedGuard.java
│ └── DjiIsCoverClosedGuard.java
├── listener
│ ├── DefaultAirportListener.java # 默认机巢监听器
│ └── DefaultCoverListener.java # 默认舱门监听器
├── config
│ ├── AirportMachineConfig.java # 机巢状态机配置(多平台)
│ └── CoverMachineConfig.java # 舱门状态机配置(多平台)
├── service
│ ├── AirportMachineService.java # 机巢状态机服务
│ └── CoverMachineService.java # 舱门状态机服务
├── manager
│ └── AirportSystemManager.java # 系统管理器(协调器)
└── demo
├── AirportSystemDemo.java # 单平台演示
└── MultiPlatformDemo.java # 多平台演示
```
## 工作流程
### 1. 状态机创建流程
```
用户调用 -> AirportSystemManager.airportOnline(airportSn)
AirportMachineService.sendEvent(airportSn, AIRPORT_ONLINE)
AirportMachineService.getOrCreateStateMachine(airportSn)
AirportMachineConfig.stateMachineFactory.getStateMachine(airportSn)
PlatformStrategyFactory.getAirportStrategy(airportSn)
AirportPlatformRepository.getPlatformType(airportSn) # 查询数据库
返回对应平台的Strategy (如: DjiAirportPlatformStrategy)
使用Strategy中的Guard、Action、Listener构建状态机
状态机创建完成并启动
```
### 2. 事件处理流程
```
事件触发 -> StateMachine.sendEvent(event)
检查Guard条件 (如: DjiCanOnlineGuard.evaluate())
Guard通过 -> 执行Action (如: DjiOnlineAction.execute())
状态转换
触发Listener回调 (如: DefaultAirportListener.stateChanged())
```
## 如何添加新平台
### 步骤1: 在PlatformType中添加新平台
```java
public enum PlatformType {
DJI("DJI", "大疆"),
AUTEL("AUTEL", "道通"),
YUNEEC("YUNEEC", "昊翔"),
NEW_PLATFORM("NEW", "新平台"); // 添加这行
}
```
### 步骤2: 创建平台实现目录
```
platform/impl/newplatform/
├── NewPlatformAirportStrategy.java
├── NewPlatformCoverStrategy.java
├── action/
│ ├── airport/
│ └── cover/
└── guard/
├── airport/
└── cover/
```
### 步骤3: 实现AirportPlatformStrategy接口
```java
@Component
public class NewPlatformAirportStrategy implements AirportPlatformStrategy {
@Override
public PlatformType getPlatformType() {
return PlatformType.NEW_PLATFORM;
}
// 实现所有Guard、Action、Listener的getter方法
}
```
### 步骤4: 实现CoverPlatformStrategy接口
```java
@Component
public class NewPlatformCoverStrategy implements CoverPlatformStrategy {
@Override
public PlatformType getPlatformType() {
return PlatformType.NEW_PLATFORM;
}
// 实现所有Guard、Action、Listener的getter方法
}
```
### 步骤5: 实现所有Guard和Action
参考DJI平台的实现创建对应的Guard和Action类。
### 步骤6: 在数据库中配置映射关系
```java
repository.savePlatformMapping("airport-005", PlatformType.NEW_PLATFORM);
```
### 步骤7: 测试
```java
systemManager.airportOnline("airport-005");
```
## 运行演示
### 单平台演示
```bash
运行: AirportSystemDemo.main()
演示内容: DJI平台的完整开舱、关舱、重启流程
```
### 多平台演示
```bash
运行: MultiPlatformDemo.main()
演示内容:
- DJI、AUTEL、YUNEEC三个平台同时运行
- 各平台独立的状态管理
- 动态注册新平台
- 多平台状态汇总
```
## 架构优势
1. **平台隔离**: 各平台的业务逻辑完全独立,互不影响
2. **易于扩展**: 添加新平台只需实现Strategy接口无需修改现有代码
3. **数据库驱动**: 平台映射关系存储在数据库,支持动态配置
4. **多平台并发**: 支持多个平台同时运行,状态机独立管理
5. **默认实现**: 提供默认Listener减少重复代码
6. **类型安全**: 使用枚举和接口保证类型安全
7. **Spring集成**: 利用Spring的依赖注入自动注册所有平台策略
## 注意事项
1. **数据库配置**: 当前使用内存Map模拟生产环境需替换为真实数据库
2. **平台注册**: 所有平台Strategy实现必须标注@Component注解
3. **机巢SN**: 必须在数据库中配置机巢SN到平台类型的映射
4. **Listener定制**: 如需定制Listener继承DefaultListener并覆盖相应方法
5. **线程安全**: Service层使用ConcurrentHashMap保证线程安全
## 未来扩展
1. **平台能力差异**: 可在Strategy中添加能力查询接口
2. **动态配置**: 支持运行时动态修改平台映射关系
3. **平台版本**: 支持同一平台的不同版本如DJI v1, DJI v2
4. **监控告警**: 集成监控系统,实时监控各平台状态
5. **性能优化**: 状态机缓存、懒加载等优化策略

View File

@ -1,19 +1,8 @@
package com.tuoheng.status.airport.config;
import com.tuoheng.status.airport.action.airport.OfflineAction;
import com.tuoheng.status.airport.action.airport.OnlineAction;
import com.tuoheng.status.airport.action.debug.CloseDebugModeAction;
import com.tuoheng.status.airport.action.debug.OpenDebugModeAction;
import com.tuoheng.status.airport.action.reboot.RebootAction;
import com.tuoheng.status.airport.action.reboot.RebootCompletedAction;
import com.tuoheng.status.airport.events.AirportEvent;
import com.tuoheng.status.airport.guard.airport.CanOfflineGuard;
import com.tuoheng.status.airport.guard.airport.CanOnlineGuard;
import com.tuoheng.status.airport.guard.debug.CanCloseDebugModeGuard;
import com.tuoheng.status.airport.guard.debug.IsDebugModeGuard;
import com.tuoheng.status.airport.guard.debug.IsNotDebugModeGuard;
import com.tuoheng.status.airport.guard.reboot.IsRebootCompletedGuard;
import com.tuoheng.status.airport.listener.AirPortStatusListener;
import com.tuoheng.status.airport.platform.factory.PlatformStrategyFactory;
import com.tuoheng.status.airport.platform.strategy.AirportPlatformStrategy;
import com.tuoheng.status.airport.status.AirportState;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
@ -26,51 +15,14 @@ import java.util.EnumSet;
import java.util.UUID;
/**
* 机巢状态机配置简化版 - 舱门状态已分离
* 机巢状态机配置多平台支持版本
* 通过PlatformStrategyFactory动态获取平台特定的GuardAction和Listener
*/
@Configuration
public class AirportMachineConfig {
@Autowired
AirPortStatusListener airPortStatusListener;
// ==================== Actions ====================
@Autowired
OnlineAction onlineAction;
@Autowired
OfflineAction offlineAction;
@Autowired
OpenDebugModeAction openDebugModeAction;
@Autowired
CloseDebugModeAction closeDebugModeAction;
@Autowired
RebootAction rebootAction;
@Autowired
RebootCompletedAction rebootCompletedAction;
// ==================== Guards ====================
@Autowired
CanOnlineGuard canOnlineGuard;
@Autowired
CanOfflineGuard canOfflineGuard;
@Autowired
IsDebugModeGuard isDebugModeGuard;
@Autowired
IsNotDebugModeGuard isNotDebugModeGuard;
@Autowired
CanCloseDebugModeGuard canCloseDebugModeGuard;
@Autowired
IsRebootCompletedGuard isRebootCompletedGuard;
private PlatformStrategyFactory platformStrategyFactory;
@Bean(name = "airportStateMachineFactory")
public StateMachineFactory<AirportState, AirportEvent> stateMachineFactory() throws Exception {
@ -83,16 +35,19 @@ public class AirportMachineConfig {
@Override
public StateMachine<AirportState, AirportEvent> getStateMachine(String machineId) {
try {
// 根据机巢SN获取平台策略
AirportPlatformStrategy strategy = platformStrategyFactory.getAirportStrategy(machineId);
StateMachineBuilder.Builder<AirportState, AirportEvent> builder = StateMachineBuilder.builder();
configureStateMachine(builder);
configureStateMachine(builder, strategy);
configureStates(builder);
configureTransitions(builder);
configureTransitions(builder, strategy);
StateMachine<AirportState, AirportEvent> stateMachine = builder.build();
stateMachine.getExtendedState().getVariables().put("machineId", machineId);
return stateMachine;
} catch (Exception e) {
throw new RuntimeException("Failed to create state machine", e);
throw new RuntimeException("Failed to create state machine for: " + machineId, e);
}
}
@ -103,11 +58,13 @@ public class AirportMachineConfig {
};
}
private void configureStateMachine(StateMachineBuilder.Builder<AirportState, AirportEvent> builder) throws Exception {
private void configureStateMachine(
StateMachineBuilder.Builder<AirportState, AirportEvent> builder,
AirportPlatformStrategy strategy) throws Exception {
builder.configureConfiguration()
.withConfiguration()
.autoStartup(true)
.listener(airPortStatusListener);
.listener(strategy.getListener());
}
private void configureStates(StateMachineBuilder.Builder<AirportState, AirportEvent> builder) throws Exception {
@ -129,15 +86,17 @@ public class AirportMachineConfig {
));
}
private void configureTransitions(StateMachineBuilder.Builder<AirportState, AirportEvent> builder) throws Exception {
private void configureTransitions(
StateMachineBuilder.Builder<AirportState, AirportEvent> builder,
AirportPlatformStrategy strategy) throws Exception {
builder.configureTransitions()
// OFFLINE -> ONLINE(STANDBY)
.withExternal()
.source(AirportState.OFFLINE)
.target(AirportState.ONLINE)
.event(AirportEvent.AIRPORT_ONLINE)
.action(onlineAction)
.guard(canOnlineGuard)
.action(strategy.getOnlineAction())
.guard(strategy.getCanOnlineGuard())
.and()
// ONLINE -> OFFLINE
@ -145,8 +104,8 @@ public class AirportMachineConfig {
.source(AirportState.ONLINE)
.target(AirportState.OFFLINE)
.event(AirportEvent.AIRPORT_OFFLINE)
.action(offlineAction)
.guard(canOfflineGuard)
.action(strategy.getOfflineAction())
.guard(strategy.getCanOfflineGuard())
.and()
// STANDBY -> DEBUG_MODE
@ -154,8 +113,8 @@ public class AirportMachineConfig {
.source(AirportState.STANDBY)
.target(AirportState.DEBUG_MODE)
.event(AirportEvent.DEBUG_MODE_OPEN)
.action(openDebugModeAction)
.guard(isNotDebugModeGuard)
.action(strategy.getOpenDebugModeAction())
.guard(strategy.getIsNotDebugModeGuard())
.and()
// DEBUG_MODE -> STANDBY
@ -163,8 +122,8 @@ public class AirportMachineConfig {
.source(AirportState.DEBUG_MODE)
.target(AirportState.STANDBY)
.event(AirportEvent.DEBUG_MODE_CLOSE)
.action(closeDebugModeAction)
.guard(canCloseDebugModeGuard)
.action(strategy.getCloseDebugModeAction())
.guard(strategy.getCanCloseDebugModeGuard())
.and()
// DEBUG_MODE -> REBOOTING
@ -172,8 +131,8 @@ public class AirportMachineConfig {
.source(AirportState.DEBUG_MODE)
.target(AirportState.REBOOTING)
.event(AirportEvent.AIRPORT_REBOOT)
.action(rebootAction)
.guard(isDebugModeGuard)
.action(strategy.getRebootAction())
.guard(strategy.getIsDebugModeGuard())
.and()
// REBOOTING -> ONLINE(STANDBY)
@ -181,7 +140,7 @@ public class AirportMachineConfig {
.source(AirportState.REBOOTING)
.target(AirportState.ONLINE)
.event(AirportEvent.REBOOT_COMPLETED)
.action(rebootCompletedAction)
.guard(isRebootCompletedGuard);
.action(strategy.getRebootCompletedAction())
.guard(strategy.getIsRebootCompletedGuard());
}
}

View File

@ -1,7 +1,10 @@
package com.tuoheng.status.airport.config;
import com.tuoheng.status.airport.events.CoverEvent;
import com.tuoheng.status.airport.platform.factory.PlatformStrategyFactory;
import com.tuoheng.status.airport.platform.strategy.CoverPlatformStrategy;
import com.tuoheng.status.airport.status.CoverState;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.statemachine.StateMachine;
@ -12,11 +15,15 @@ import java.util.EnumSet;
import java.util.UUID;
/**
* 舱门状态机配置
* 舱门状态机配置多平台支持版本
* 通过PlatformStrategyFactory动态获取平台特定的GuardAction和Listener
*/
@Configuration
public class CoverMachineConfig {
@Autowired
private PlatformStrategyFactory platformStrategyFactory;
@Bean
public StateMachineFactory<CoverState, CoverEvent> coverStateMachineFactory() throws Exception {
return new StateMachineFactory<CoverState, CoverEvent>() {
@ -28,16 +35,19 @@ public class CoverMachineConfig {
@Override
public StateMachine<CoverState, CoverEvent> getStateMachine(String machineId) {
try {
// 根据机巢SN获取平台策略
CoverPlatformStrategy strategy = platformStrategyFactory.getCoverStrategy(machineId);
StateMachineBuilder.Builder<CoverState, CoverEvent> builder = StateMachineBuilder.builder();
configureCoverStateMachine(builder);
configureCoverStateMachine(builder, strategy);
configureCoverStates(builder);
configureCoverTransitions(builder);
configureCoverTransitions(builder, strategy);
StateMachine<CoverState, CoverEvent> stateMachine = builder.build();
stateMachine.getExtendedState().getVariables().put("machineId", machineId);
return stateMachine;
} catch (Exception e) {
throw new RuntimeException("Failed to create cover state machine", e);
throw new RuntimeException("Failed to create cover state machine for: " + machineId, e);
}
}
@ -48,10 +58,13 @@ public class CoverMachineConfig {
};
}
private void configureCoverStateMachine(StateMachineBuilder.Builder<CoverState, CoverEvent> builder) throws Exception {
private void configureCoverStateMachine(
StateMachineBuilder.Builder<CoverState, CoverEvent> builder,
CoverPlatformStrategy strategy) throws Exception {
builder.configureConfiguration()
.withConfiguration()
.autoStartup(true);
.autoStartup(true)
.listener(strategy.getListener());
}
private void configureCoverStates(StateMachineBuilder.Builder<CoverState, CoverEvent> builder) throws Exception {
@ -61,13 +74,17 @@ public class CoverMachineConfig {
.states(EnumSet.allOf(CoverState.class));
}
private void configureCoverTransitions(StateMachineBuilder.Builder<CoverState, CoverEvent> builder) throws Exception {
private void configureCoverTransitions(
StateMachineBuilder.Builder<CoverState, CoverEvent> builder,
CoverPlatformStrategy strategy) throws Exception {
builder.configureTransitions()
// CLOSED -> OPENING
.withExternal()
.source(CoverState.CLOSED)
.target(CoverState.OPENING)
.event(CoverEvent.OPEN)
.action(strategy.getOpenAction())
.guard(strategy.getCanOpenGuard())
.and()
// OPENING -> OPENED
@ -75,6 +92,8 @@ public class CoverMachineConfig {
.source(CoverState.OPENING)
.target(CoverState.OPENED)
.event(CoverEvent.OPENED)
.action(strategy.getOpenedAction())
.guard(strategy.getIsOpenedGuard())
.and()
// OPENED -> CLOSING
@ -82,6 +101,8 @@ public class CoverMachineConfig {
.source(CoverState.OPENED)
.target(CoverState.CLOSING)
.event(CoverEvent.CLOSE)
.action(strategy.getCloseAction())
.guard(strategy.getCanCloseGuard())
.and()
// CLOSING -> CLOSED
@ -89,6 +110,8 @@ public class CoverMachineConfig {
.source(CoverState.CLOSING)
.target(CoverState.CLOSED)
.event(CoverEvent.CLOSED)
.action(strategy.getClosedAction())
.guard(strategy.getIsClosedGuard())
.and()
// ERROR handling
@ -96,18 +119,21 @@ public class CoverMachineConfig {
.source(CoverState.OPENING)
.target(CoverState.ERROR)
.event(CoverEvent.ERROR)
.action(strategy.getErrorAction())
.and()
.withExternal()
.source(CoverState.CLOSING)
.target(CoverState.ERROR)
.event(CoverEvent.ERROR)
.action(strategy.getErrorAction())
.and()
// RESET from ERROR
.withExternal()
.source(CoverState.ERROR)
.target(CoverState.CLOSED)
.event(CoverEvent.RESET);
.event(CoverEvent.RESET)
.action(strategy.getResetAction());
}
}

View File

@ -0,0 +1,169 @@
package com.tuoheng.status.airport.demo;
import com.tuoheng.status.airport.manager.AirportSystemManager;
import com.tuoheng.status.airport.platform.PlatformType;
import com.tuoheng.status.airport.platform.factory.PlatformStrategyFactory;
import com.tuoheng.status.airport.platform.repository.AirportPlatformRepository;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
/**
* 多平台演示程序
* 演示DJIAUTELYUNEEC等多个平台同时运行的场景
*/
public class MultiPlatformDemo {
public static void main(String[] args) throws InterruptedException {
// 创建 Spring 上下文
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
// 扫描所有组件
context.scan("com.tuoheng.status.airport");
context.refresh();
// 获取必要的Bean
AirportSystemManager systemManager = context.getBean(AirportSystemManager.class);
PlatformStrategyFactory strategyFactory = context.getBean(PlatformStrategyFactory.class);
AirportPlatformRepository repository = context.getBean(AirportPlatformRepository.class);
System.out.println("\n========== 多平台机巢系统演示开始 ==========\n");
// ==================== 场景1: 多平台机巢上线 ====================
System.out.println("【场景1】多平台机巢上线");
System.out.println("----------------------------------------");
String djiAirport = "airport-001"; // DJI平台
String autelAirport = "airport-002"; // AUTEL平台
String djiAirport2 = "airport-003"; // DJI平台
System.out.println("1. DJI机巢上线: " + djiAirport);
System.out.println(" 平台类型: " + strategyFactory.getPlatformType(djiAirport).getName());
systemManager.airportOnline(djiAirport);
System.out.println(" " + systemManager.getFullStatus(djiAirport));
System.out.println();
Thread.sleep(500);
System.out.println("2. AUTEL机巢上线: " + autelAirport);
System.out.println(" 平台类型: " + strategyFactory.getPlatformType(autelAirport).getName());
systemManager.airportOnline(autelAirport);
System.out.println(" " + systemManager.getFullStatus(autelAirport));
System.out.println();
Thread.sleep(500);
System.out.println("3. 另一个DJI机巢上线: " + djiAirport2);
System.out.println(" 平台类型: " + strategyFactory.getPlatformType(djiAirport2).getName());
systemManager.airportOnline(djiAirport2);
System.out.println(" " + systemManager.getFullStatus(djiAirport2));
System.out.println();
Thread.sleep(500);
// ==================== 场景2: DJI平台开舱流程 ====================
System.out.println("【场景2】DJI平台开舱流程");
System.out.println("----------------------------------------");
System.out.println("4. DJI机巢开启调试模式: " + djiAirport);
systemManager.openDebugMode(djiAirport);
System.out.println(" " + systemManager.getFullStatus(djiAirport));
System.out.println();
Thread.sleep(500);
System.out.println("5. DJI机巢开舱: " + djiAirport);
systemManager.openCover(djiAirport);
System.out.println(" " + systemManager.getFullStatus(djiAirport));
System.out.println();
Thread.sleep(500);
System.out.println("6. DJI机巢舱门打开完成: " + djiAirport);
systemManager.coverOpened(djiAirport);
System.out.println(" " + systemManager.getFullStatus(djiAirport));
System.out.println();
Thread.sleep(500);
// ==================== 场景3: AUTEL平台开舱流程同时进行 ====================
System.out.println("【场景3】AUTEL平台开舱流程与DJI平台并行");
System.out.println("----------------------------------------");
System.out.println("7. AUTEL机巢开启调试模式: " + autelAirport);
systemManager.openDebugMode(autelAirport);
System.out.println(" " + systemManager.getFullStatus(autelAirport));
System.out.println();
Thread.sleep(500);
System.out.println("8. AUTEL机巢开舱: " + autelAirport);
systemManager.openCover(autelAirport);
System.out.println(" " + systemManager.getFullStatus(autelAirport));
System.out.println();
Thread.sleep(500);
// ==================== 场景4: 查看所有机巢状态 ====================
System.out.println("【场景4】查看所有机巢当前状态");
System.out.println("----------------------------------------");
System.out.println("DJI机巢-001: " + systemManager.getFullStatus(djiAirport));
System.out.println("AUTEL机巢-002: " + systemManager.getFullStatus(autelAirport));
System.out.println("DJI机巢-003: " + systemManager.getFullStatus(djiAirport2));
System.out.println();
Thread.sleep(500);
// ==================== 场景5: DJI机巢关舱 ====================
System.out.println("【场景5】DJI机巢关舱流程");
System.out.println("----------------------------------------");
System.out.println("9. DJI机巢关舱: " + djiAirport);
systemManager.closeCover(djiAirport);
System.out.println(" " + systemManager.getFullStatus(djiAirport));
System.out.println();
Thread.sleep(500);
System.out.println("10. DJI机巢舱门关闭完成: " + djiAirport);
systemManager.coverClosed(djiAirport);
System.out.println(" " + systemManager.getFullStatus(djiAirport));
System.out.println();
Thread.sleep(500);
// ==================== 场景6: 动态注册新平台机巢 ====================
System.out.println("【场景6】动态注册新平台机巢");
System.out.println("----------------------------------------");
String yuneecAirport = "airport-004";
System.out.println("11. 注册YUNEEC平台机巢: " + yuneecAirport);
System.out.println(" 平台类型: " + strategyFactory.getPlatformType(yuneecAirport).getName());
systemManager.airportOnline(yuneecAirport);
System.out.println(" " + systemManager.getFullStatus(yuneecAirport));
System.out.println();
// ==================== 场景7: 最终状态汇总 ====================
System.out.println("【场景7】所有机巢最终状态汇总");
System.out.println("----------------------------------------");
System.out.println(String.format("%-20s %-15s %s", "机巢SN", "平台类型", "状态"));
System.out.println("------------------------------------------------------------");
System.out.println(String.format("%-20s %-15s %s",
djiAirport,
strategyFactory.getPlatformType(djiAirport).getName(),
systemManager.getFullStatus(djiAirport)));
System.out.println(String.format("%-20s %-15s %s",
autelAirport,
strategyFactory.getPlatformType(autelAirport).getName(),
systemManager.getFullStatus(autelAirport)));
System.out.println(String.format("%-20s %-15s %s",
djiAirport2,
strategyFactory.getPlatformType(djiAirport2).getName(),
systemManager.getFullStatus(djiAirport2)));
System.out.println(String.format("%-20s %-15s %s",
yuneecAirport,
strategyFactory.getPlatformType(yuneecAirport).getName(),
systemManager.getFullStatus(yuneecAirport)));
System.out.println();
System.out.println("\n========== 多平台机巢系统演示结束 ==========\n");
System.out.println("✅ 多平台架构优势:");
System.out.println(" 1. 支持多个无人机平台DJI、AUTEL、YUNEEC等");
System.out.println(" 2. 各平台独立实现Guard、Action和Listener");
System.out.println(" 3. 通过数据库配置平台映射关系");
System.out.println(" 4. 多个平台可以同时运行,互不干扰");
System.out.println(" 5. 易于扩展新平台只需实现对应的Strategy接口");
System.out.println(" 6. 默认Listener提供基础功能各平台可定制");
context.close();
}
}

View File

@ -1,77 +0,0 @@
package com.tuoheng.status.airport.listener;
import com.tuoheng.status.airport.events.AirportEvent;
import com.tuoheng.status.airport.status.AirportState;
import com.tuoheng.status.statemachine.events.Event;
import com.tuoheng.status.statemachine.status.Status;
import org.springframework.messaging.Message;
import org.springframework.statemachine.StateContext;
import org.springframework.statemachine.StateMachine;
import org.springframework.statemachine.listener.StateMachineListener;
import org.springframework.statemachine.state.State;
import org.springframework.statemachine.transition.Transition;
import org.springframework.stereotype.Component;
@Component
public class AirPortStatusListener implements StateMachineListener<AirportState, AirportEvent> {
@Override
public void stateChanged(State<AirportState, AirportEvent> state, State<AirportState, AirportEvent> state1) {
}
@Override
public void stateEntered(State<AirportState, AirportEvent> state) {
}
@Override
public void stateExited(State<AirportState, AirportEvent> state) {
}
@Override
public void eventNotAccepted(Message<AirportEvent> message) {
}
@Override
public void transition(Transition<AirportState, AirportEvent> transition) {
}
@Override
public void transitionStarted(Transition<AirportState, AirportEvent> transition) {
}
@Override
public void transitionEnded(Transition<AirportState, AirportEvent> transition) {
}
@Override
public void stateMachineStarted(StateMachine<AirportState, AirportEvent> stateMachine) {
}
@Override
public void stateMachineStopped(StateMachine<AirportState, AirportEvent> stateMachine) {
}
@Override
public void stateMachineError(StateMachine<AirportState, AirportEvent> stateMachine, Exception e) {
}
@Override
public void extendedStateChanged(Object o, Object o1) {
}
@Override
public void stateContext(StateContext<AirportState, AirportEvent> stateContext) {
}
}

View File

@ -0,0 +1,97 @@
package com.tuoheng.status.airport.listener;
import com.tuoheng.status.airport.events.AirportEvent;
import com.tuoheng.status.airport.platform.strategy.PlatformListener;
import com.tuoheng.status.airport.status.AirportState;
import org.springframework.messaging.Message;
import org.springframework.statemachine.StateContext;
import org.springframework.statemachine.StateMachine;
import org.springframework.statemachine.state.State;
import org.springframework.statemachine.transition.Transition;
import org.springframework.stereotype.Component;
/**
* 默认机巢状态监听器
* 提供基础的状态变化监听功能各平台可以继承并定制
*/
@Component
public class DefaultAirportListener implements PlatformListener<AirportState, AirportEvent> {
@Override
public String getName() {
return "DefaultAirportListener";
}
@Override
public void stateChanged(State<AirportState, AirportEvent> from, State<AirportState, AirportEvent> to) {
if (from != null && to != null) {
System.out.println(String.format("[%s] 状态变化: %s -> %s",
getName(), from.getId(), to.getId()));
}
}
@Override
public void stateEntered(State<AirportState, AirportEvent> state) {
System.out.println(String.format("[%s] 进入状态: %s", getName(), state.getId()));
}
@Override
public void stateExited(State<AirportState, AirportEvent> state) {
System.out.println(String.format("[%s] 退出状态: %s", getName(), state.getId()));
}
@Override
public void eventNotAccepted(Message<AirportEvent> event) {
System.out.println(String.format("[%s] 事件未被接受: %s", getName(), event.getPayload()));
}
@Override
public void transition(Transition<AirportState, AirportEvent> transition) {
// 默认不处理
}
@Override
public void transitionStarted(Transition<AirportState, AirportEvent> transition) {
if (transition.getSource() != null && transition.getTarget() != null) {
System.out.println(String.format("[%s] 转换开始: %s -> %s",
getName(), transition.getSource().getId(), transition.getTarget().getId()));
}
}
@Override
public void transitionEnded(Transition<AirportState, AirportEvent> transition) {
if (transition.getSource() != null && transition.getTarget() != null) {
System.out.println(String.format("[%s] 转换结束: %s -> %s",
getName(), transition.getSource().getId(), transition.getTarget().getId()));
}
}
@Override
public void stateMachineStarted(StateMachine<AirportState, AirportEvent> stateMachine) {
String machineId = (String) stateMachine.getExtendedState().getVariables().get("machineId");
System.out.println(String.format("[%s] 状态机启动: %s", getName(), machineId));
}
@Override
public void stateMachineStopped(StateMachine<AirportState, AirportEvent> stateMachine) {
String machineId = (String) stateMachine.getExtendedState().getVariables().get("machineId");
System.out.println(String.format("[%s] 状态机停止: %s", getName(), machineId));
}
@Override
public void stateMachineError(StateMachine<AirportState, AirportEvent> stateMachine, Exception exception) {
String machineId = (String) stateMachine.getExtendedState().getVariables().get("machineId");
System.err.println(String.format("[%s] 状态机错误: %s, 异常: %s",
getName(), machineId, exception.getMessage()));
}
@Override
public void extendedStateChanged(Object key, Object value) {
System.out.println(String.format("[%s] 扩展状态变化: %s = %s", getName(), key, value));
}
@Override
public void stateContext(StateContext<AirportState, AirportEvent> stateContext) {
// 默认不处理
}
}

View File

@ -0,0 +1,97 @@
package com.tuoheng.status.airport.listener;
import com.tuoheng.status.airport.events.CoverEvent;
import com.tuoheng.status.airport.platform.strategy.PlatformListener;
import com.tuoheng.status.airport.status.CoverState;
import org.springframework.messaging.Message;
import org.springframework.statemachine.StateContext;
import org.springframework.statemachine.StateMachine;
import org.springframework.statemachine.state.State;
import org.springframework.statemachine.transition.Transition;
import org.springframework.stereotype.Component;
/**
* 默认舱门状态监听器
* 提供基础的状态变化监听功能各平台可以继承并定制
*/
@Component
public class DefaultCoverListener implements PlatformListener<CoverState, CoverEvent> {
@Override
public String getName() {
return "DefaultCoverListener";
}
@Override
public void stateChanged(State<CoverState, CoverEvent> from, State<CoverState, CoverEvent> to) {
if (from != null && to != null) {
System.out.println(String.format("[%s] 状态变化: %s -> %s",
getName(), from.getId(), to.getId()));
}
}
@Override
public void stateEntered(State<CoverState, CoverEvent> state) {
System.out.println(String.format("[%s] 进入状态: %s", getName(), state.getId()));
}
@Override
public void stateExited(State<CoverState, CoverEvent> state) {
System.out.println(String.format("[%s] 退出状态: %s", getName(), state.getId()));
}
@Override
public void eventNotAccepted(Message<CoverEvent> event) {
System.out.println(String.format("[%s] 事件未被接受: %s", getName(), event.getPayload()));
}
@Override
public void transition(Transition<CoverState, CoverEvent> transition) {
// 默认不处理
}
@Override
public void transitionStarted(Transition<CoverState, CoverEvent> transition) {
if (transition.getSource() != null && transition.getTarget() != null) {
System.out.println(String.format("[%s] 转换开始: %s -> %s",
getName(), transition.getSource().getId(), transition.getTarget().getId()));
}
}
@Override
public void transitionEnded(Transition<CoverState, CoverEvent> transition) {
if (transition.getSource() != null && transition.getTarget() != null) {
System.out.println(String.format("[%s] 转换结束: %s -> %s",
getName(), transition.getSource().getId(), transition.getTarget().getId()));
}
}
@Override
public void stateMachineStarted(StateMachine<CoverState, CoverEvent> stateMachine) {
String machineId = (String) stateMachine.getExtendedState().getVariables().get("machineId");
System.out.println(String.format("[%s] 状态机启动: %s", getName(), machineId));
}
@Override
public void stateMachineStopped(StateMachine<CoverState, CoverEvent> stateMachine) {
String machineId = (String) stateMachine.getExtendedState().getVariables().get("machineId");
System.out.println(String.format("[%s] 状态机停止: %s", getName(), machineId));
}
@Override
public void stateMachineError(StateMachine<CoverState, CoverEvent> stateMachine, Exception exception) {
String machineId = (String) stateMachine.getExtendedState().getVariables().get("machineId");
System.err.println(String.format("[%s] 状态机错误: %s, 异常: %s",
getName(), machineId, exception.getMessage()));
}
@Override
public void extendedStateChanged(Object key, Object value) {
System.out.println(String.format("[%s] 扩展状态变化: %s = %s", getName(), key, value));
}
@Override
public void stateContext(StateContext<CoverState, CoverEvent> stateContext) {
// 默认不处理
}
}

View File

@ -17,41 +17,41 @@ import org.springframework.stereotype.Component;
public class AirportSystemManager {
@Autowired
private AirportMachineService airportManager;
private AirportMachineService airportService;
@Autowired
private CoverMachineService coverManager;
private CoverMachineService coverService;
/**
* 机巢上线
*/
public boolean airportOnline(String airportSn) {
return airportManager.sendEvent(airportSn, AirportEvent.AIRPORT_ONLINE);
return airportService.sendEvent(airportSn, AirportEvent.AIRPORT_ONLINE);
}
/**
* 机巢离线
*/
public boolean airportOffline(String airportSn) {
return airportManager.sendEvent(airportSn, AirportEvent.AIRPORT_OFFLINE);
return airportService.sendEvent(airportSn, AirportEvent.AIRPORT_OFFLINE);
}
/**
* 开启调试模式
*/
public boolean openDebugMode(String airportSn) {
if (!airportManager.isInState(airportSn, AirportState.ONLINE)) {
if (!airportService.isInState(airportSn, AirportState.ONLINE)) {
System.out.println("机巢未在线,无法开启调试模式");
return false;
}
return airportManager.sendEvent(airportSn, AirportEvent.DEBUG_MODE_OPEN);
return airportService.sendEvent(airportSn, AirportEvent.DEBUG_MODE_OPEN);
}
/**
* 关闭调试模式
*/
public boolean closeDebugMode(String airportSn) {
return airportManager.sendEvent(airportSn, AirportEvent.DEBUG_MODE_CLOSE);
return airportService.sendEvent(airportSn, AirportEvent.DEBUG_MODE_CLOSE);
}
/**
@ -59,26 +59,26 @@ public class AirportSystemManager {
*/
public boolean openCover(String airportSn) {
// 检查机巢是否在调试模式
if (!airportManager.isInState(airportSn, AirportState.DEBUG_MODE)) {
if (!airportService.isInState(airportSn, AirportState.DEBUG_MODE)) {
System.out.println("必须在调试模式下才能开舱");
return false;
}
// 检查舱门是否已经打开
if (coverManager.isInState(airportSn, CoverState.OPENED)) {
if (coverService.isInState(airportSn, CoverState.OPENED)) {
System.out.println("舱门已经打开");
return false;
}
// 发送开舱指令到舱门状态机
return coverManager.sendEvent(airportSn, CoverEvent.OPEN);
return coverService.sendEvent(airportSn, CoverEvent.OPEN);
}
/**
* 舱门打开完成
*/
public boolean coverOpened(String airportSn) {
return coverManager.sendEvent(airportSn, CoverEvent.OPENED);
return coverService.sendEvent(airportSn, CoverEvent.OPENED);
}
/**
@ -86,58 +86,58 @@ public class AirportSystemManager {
*/
public boolean closeCover(String airportSn) {
// 检查机巢是否在调试模式
if (!airportManager.isInState(airportSn, AirportState.DEBUG_MODE)) {
if (!airportService.isInState(airportSn, AirportState.DEBUG_MODE)) {
System.out.println("必须在调试模式下才能关舱");
return false;
}
// 检查舱门是否已经关闭
if (coverManager.isInState(airportSn, CoverState.CLOSED)) {
if (coverService.isInState(airportSn, CoverState.CLOSED)) {
System.out.println("舱门已经关闭");
return false;
}
// 发送关舱指令到舱门状态机
return coverManager.sendEvent(airportSn, CoverEvent.CLOSE);
return coverService.sendEvent(airportSn, CoverEvent.CLOSE);
}
/**
* 舱门关闭完成
*/
public boolean coverClosed(String airportSn) {
return coverManager.sendEvent(airportSn, CoverEvent.CLOSED);
return coverService.sendEvent(airportSn, CoverEvent.CLOSED);
}
/**
* 机巢重启
*/
public boolean rebootAirport(String airportSn) {
if (!airportManager.isInState(airportSn, AirportState.DEBUG_MODE)) {
if (!airportService.isInState(airportSn, AirportState.DEBUG_MODE)) {
System.out.println("必须在调试模式下才能重启");
return false;
}
return airportManager.sendEvent(airportSn, AirportEvent.AIRPORT_REBOOT);
return airportService.sendEvent(airportSn, AirportEvent.AIRPORT_REBOOT);
}
/**
* 重启完成
*/
public boolean rebootCompleted(String airportSn) {
return airportManager.sendEvent(airportSn, AirportEvent.REBOOT_COMPLETED);
return airportService.sendEvent(airportSn, AirportEvent.REBOOT_COMPLETED);
}
/**
* 获取机巢状态
*/
public AirportState getAirportState(String airportSn) {
return airportManager.getCurrentState(airportSn);
return airportService.getCurrentState(airportSn);
}
/**
* 获取舱门状态
*/
public CoverState getCoverState(String airportSn) {
return coverManager.getCurrentState(airportSn);
return coverService.getCurrentState(airportSn);
}
/**

View File

@ -0,0 +1,49 @@
package com.tuoheng.status.airport.platform;
/**
* 无人机平台类型枚举
*/
public enum PlatformType {
/**
* 大疆平台
*/
DJI("DJI", "大疆"),
/**
* 道通平台
*/
AUTEL("AUTEL", "道通"),
/**
* 昊翔平台
*/
YUNEEC("YUNEEC", "昊翔");
private final String code;
private final String name;
PlatformType(String code, String name) {
this.code = code;
this.name = name;
}
public String getCode() {
return code;
}
public String getName() {
return name;
}
/**
* 根据code获取平台类型
*/
public static PlatformType fromCode(String code) {
for (PlatformType type : values()) {
if (type.code.equalsIgnoreCase(code)) {
return type;
}
}
throw new IllegalArgumentException("Unknown platform code: " + code);
}
}

View File

@ -0,0 +1,143 @@
package com.tuoheng.status.airport.platform.factory;
import com.tuoheng.status.airport.platform.PlatformType;
import com.tuoheng.status.airport.platform.repository.AirportPlatformRepository;
import com.tuoheng.status.airport.platform.strategy.AirportPlatformStrategy;
import com.tuoheng.status.airport.platform.strategy.CoverPlatformStrategy;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* 平台策略工厂
* 根据机巢SN从数据库查询平台类型返回对应的平台策略
*/
@Component
public class PlatformStrategyFactory {
@Autowired
private AirportPlatformRepository airportPlatformRepository;
/**
* 存储所有机巢平台策略实现
* Key: PlatformType
* Value: AirportPlatformStrategy实现
*/
private final Map<PlatformType, AirportPlatformStrategy> airportStrategyMap = new ConcurrentHashMap<>();
/**
* 存储所有舱门平台策略实现
* Key: PlatformType
* Value: CoverPlatformStrategy实现
*/
private final Map<PlatformType, CoverPlatformStrategy> coverStrategyMap = new ConcurrentHashMap<>();
/**
* 注册所有平台策略
* Spring会自动注入所有实现了AirportPlatformStrategy和CoverPlatformStrategy的Bean
*/
@Autowired
public void registerStrategies(
List<AirportPlatformStrategy> airportStrategies,
List<CoverPlatformStrategy> coverStrategies) {
// 注册机巢策略
for (AirportPlatformStrategy strategy : airportStrategies) {
airportStrategyMap.put(strategy.getPlatformType(), strategy);
System.out.println(String.format("注册机巢平台策略: %s -> %s",
strategy.getPlatformType().getName(), strategy.getClass().getSimpleName()));
}
// 注册舱门策略
for (CoverPlatformStrategy strategy : coverStrategies) {
coverStrategyMap.put(strategy.getPlatformType(), strategy);
System.out.println(String.format("注册舱门平台策略: %s -> %s",
strategy.getPlatformType().getName(), strategy.getClass().getSimpleName()));
}
}
/**
* 根据机巢SN获取机巢平台策略
*
* @param airportSn 机巢序列号
* @return 机巢平台策略
* @throws IllegalArgumentException 如果机巢未注册或平台策略不存在
*/
public AirportPlatformStrategy getAirportStrategy(String airportSn) {
// 从数据库查询平台类型
PlatformType platformType = airportPlatformRepository.getPlatformType(airportSn);
if (platformType == null) {
throw new IllegalArgumentException(
String.format("机巢未注册或平台类型未配置: %s", airportSn));
}
AirportPlatformStrategy strategy = airportStrategyMap.get(platformType);
if (strategy == null) {
throw new IllegalArgumentException(
String.format("未找到平台策略: %s (机巢: %s)", platformType.getName(), airportSn));
}
return strategy;
}
/**
* 根据机巢SN获取舱门平台策略
*
* @param airportSn 机巢序列号
* @return 舱门平台策略
* @throws IllegalArgumentException 如果机巢未注册或平台策略不存在
*/
public CoverPlatformStrategy getCoverStrategy(String airportSn) {
// 从数据库查询平台类型
PlatformType platformType = airportPlatformRepository.getPlatformType(airportSn);
if (platformType == null) {
throw new IllegalArgumentException(
String.format("机巢未注册或平台类型未配置: %s", airportSn));
}
CoverPlatformStrategy strategy = coverStrategyMap.get(platformType);
if (strategy == null) {
throw new IllegalArgumentException(
String.format("未找到平台策略: %s (机巢: %s)", platformType.getName(), airportSn));
}
return strategy;
}
/**
* 根据平台类型获取机巢平台策略
*
* @param platformType 平台类型
* @return 机巢平台策略
*/
public AirportPlatformStrategy getAirportStrategyByType(PlatformType platformType) {
return airportStrategyMap.get(platformType);
}
/**
* 根据平台类型获取舱门平台策略
*
* @param platformType 平台类型
* @return 舱门平台策略
*/
public CoverPlatformStrategy getCoverStrategyByType(PlatformType platformType) {
return coverStrategyMap.get(platformType);
}
/**
* 获取机巢的平台类型
*
* @param airportSn 机巢序列号
* @return 平台类型
*/
public PlatformType getPlatformType(String airportSn) {
return airportPlatformRepository.getPlatformType(airportSn);
}
}

View File

@ -0,0 +1,142 @@
package com.tuoheng.status.airport.platform.impl.dji;
import com.tuoheng.status.airport.events.AirportEvent;
import com.tuoheng.status.airport.listener.DefaultAirportListener;
import com.tuoheng.status.airport.platform.PlatformType;
import com.tuoheng.status.airport.platform.impl.dji.action.airport.*;
import com.tuoheng.status.airport.platform.impl.dji.guard.airport.*;
import com.tuoheng.status.airport.platform.strategy.AirportPlatformStrategy;
import com.tuoheng.status.airport.platform.strategy.PlatformAction;
import com.tuoheng.status.airport.platform.strategy.PlatformGuard;
import com.tuoheng.status.airport.platform.strategy.PlatformListener;
import com.tuoheng.status.airport.status.AirportState;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* DJI平台机巢策略实现
*/
@Component
public class DjiAirportPlatformStrategy implements AirportPlatformStrategy {
@Autowired
private DjiCanOnlineGuard canOnlineGuard;
@Autowired
private DjiCanOfflineGuard canOfflineGuard;
@Autowired
private DjiIsDebugModeGuard isDebugModeGuard;
@Autowired
private DjiIsNotDebugModeGuard isNotDebugModeGuard;
@Autowired
private DjiCanCloseDebugModeGuard canCloseDebugModeGuard;
@Autowired
private DjiIsRebootCompletedGuard isRebootCompletedGuard;
@Autowired
private DjiOnlineAction onlineAction;
@Autowired
private DjiOfflineAction offlineAction;
@Autowired
private DjiOpenDebugModeAction openDebugModeAction;
@Autowired
private DjiCloseDebugModeAction closeDebugModeAction;
@Autowired
private DjiRebootAction rebootAction;
@Autowired
private DjiRebootCompletedAction rebootCompletedAction;
/**
* DJI平台的Listener实例单例所有DJI机巢共享
*/
private final PlatformListener<AirportState, AirportEvent> djiListener = new DefaultAirportListener() {
@Override
public String getName() {
return "DjiAirportListener";
}
};
@Override
public PlatformType getPlatformType() {
return PlatformType.DJI;
}
@Override
public PlatformGuard<AirportState, AirportEvent> getCanOnlineGuard() {
return canOnlineGuard;
}
@Override
public PlatformGuard<AirportState, AirportEvent> getCanOfflineGuard() {
return canOfflineGuard;
}
@Override
public PlatformGuard<AirportState, AirportEvent> getIsDebugModeGuard() {
return isDebugModeGuard;
}
@Override
public PlatformGuard<AirportState, AirportEvent> getIsNotDebugModeGuard() {
return isNotDebugModeGuard;
}
@Override
public PlatformGuard<AirportState, AirportEvent> getCanCloseDebugModeGuard() {
return canCloseDebugModeGuard;
}
@Override
public PlatformGuard<AirportState, AirportEvent> getIsRebootCompletedGuard() {
return isRebootCompletedGuard;
}
@Override
public PlatformAction<AirportState, AirportEvent> getOnlineAction() {
return onlineAction;
}
@Override
public PlatformAction<AirportState, AirportEvent> getOfflineAction() {
return offlineAction;
}
@Override
public PlatformAction<AirportState, AirportEvent> getOpenDebugModeAction() {
return openDebugModeAction;
}
@Override
public PlatformAction<AirportState, AirportEvent> getCloseDebugModeAction() {
return closeDebugModeAction;
}
@Override
public PlatformAction<AirportState, AirportEvent> getRebootAction() {
return rebootAction;
}
@Override
public PlatformAction<AirportState, AirportEvent> getRebootCompletedAction() {
return rebootCompletedAction;
}
@Override
public PlatformListener<AirportState, AirportEvent> getListener() {
// 返回DJI平台的Listener单例
// 所有DJI机巢共享这个Listener实例
return djiListener;
}
}

View File

@ -0,0 +1,123 @@
package com.tuoheng.status.airport.platform.impl.dji;
import com.tuoheng.status.airport.events.CoverEvent;
import com.tuoheng.status.airport.listener.DefaultCoverListener;
import com.tuoheng.status.airport.platform.PlatformType;
import com.tuoheng.status.airport.platform.impl.dji.action.cover.*;
import com.tuoheng.status.airport.platform.impl.dji.guard.cover.*;
import com.tuoheng.status.airport.platform.strategy.CoverPlatformStrategy;
import com.tuoheng.status.airport.platform.strategy.PlatformAction;
import com.tuoheng.status.airport.platform.strategy.PlatformGuard;
import com.tuoheng.status.airport.platform.strategy.PlatformListener;
import com.tuoheng.status.airport.status.CoverState;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* DJI平台舱门策略实现
*/
@Component
public class DjiCoverPlatformStrategy implements CoverPlatformStrategy {
@Autowired
private DjiCanOpenCoverGuard canOpenGuard;
@Autowired
private DjiCanCloseCoverGuard canCloseGuard;
@Autowired
private DjiIsCoverOpenedGuard isOpenedGuard;
@Autowired
private DjiIsCoverClosedGuard isClosedGuard;
@Autowired
private DjiOpenCoverAction openAction;
@Autowired
private DjiCoverOpenedAction openedAction;
@Autowired
private DjiCloseCoverAction closeAction;
@Autowired
private DjiCoverClosedAction closedAction;
@Autowired
private DjiCoverErrorAction errorAction;
@Autowired
private DjiCoverResetAction resetAction;
/**
* DJI平台的舱门Listener实例单例所有DJI机巢共享
*/
private final PlatformListener<CoverState, CoverEvent> djiCoverListener = new com.tuoheng.status.airport.listener.DefaultCoverListener() {
@Override
public String getName() {
return "DjiCoverListener";
}
};
@Override
public PlatformType getPlatformType() {
return PlatformType.DJI;
}
@Override
public PlatformGuard<CoverState, CoverEvent> getCanOpenGuard() {
return canOpenGuard;
}
@Override
public PlatformGuard<CoverState, CoverEvent> getCanCloseGuard() {
return canCloseGuard;
}
@Override
public PlatformGuard<CoverState, CoverEvent> getIsOpenedGuard() {
return isOpenedGuard;
}
@Override
public PlatformGuard<CoverState, CoverEvent> getIsClosedGuard() {
return isClosedGuard;
}
@Override
public PlatformAction<CoverState, CoverEvent> getOpenAction() {
return openAction;
}
@Override
public PlatformAction<CoverState, CoverEvent> getOpenedAction() {
return openedAction;
}
@Override
public PlatformAction<CoverState, CoverEvent> getCloseAction() {
return closeAction;
}
@Override
public PlatformAction<CoverState, CoverEvent> getClosedAction() {
return closedAction;
}
@Override
public PlatformAction<CoverState, CoverEvent> getErrorAction() {
return errorAction;
}
@Override
public PlatformAction<CoverState, CoverEvent> getResetAction() {
return resetAction;
}
@Override
public PlatformListener<CoverState, CoverEvent> getListener() {
// 返回DJI平台的舱门Listener单例
// 所有DJI机巢共享这个Listener实例
return djiCoverListener;
}
}

View File

@ -0,0 +1,22 @@
package com.tuoheng.status.airport.platform.impl.dji.action.airport;
import com.tuoheng.status.airport.events.AirportEvent;
import com.tuoheng.status.airport.platform.strategy.PlatformAction;
import com.tuoheng.status.airport.status.AirportState;
import org.springframework.statemachine.StateContext;
import org.springframework.stereotype.Component;
@Component
public class DjiCloseDebugModeAction implements PlatformAction<AirportState, AirportEvent> {
@Override
public String getName() {
return "DjiCloseDebugModeAction";
}
@Override
public void execute(StateContext<AirportState, AirportEvent> context) {
String machineId = (String) context.getExtendedState().getVariables().get("machineId");
System.out.println(String.format("[DJI] 关闭调试模式: %s", machineId));
}
}

View File

@ -0,0 +1,22 @@
package com.tuoheng.status.airport.platform.impl.dji.action.airport;
import com.tuoheng.status.airport.events.AirportEvent;
import com.tuoheng.status.airport.platform.strategy.PlatformAction;
import com.tuoheng.status.airport.status.AirportState;
import org.springframework.statemachine.StateContext;
import org.springframework.stereotype.Component;
@Component
public class DjiOfflineAction implements PlatformAction<AirportState, AirportEvent> {
@Override
public String getName() {
return "DjiOfflineAction";
}
@Override
public void execute(StateContext<AirportState, AirportEvent> context) {
String machineId = (String) context.getExtendedState().getVariables().get("machineId");
System.out.println(String.format("[DJI] 机巢离线: %s", machineId));
}
}

View File

@ -0,0 +1,24 @@
package com.tuoheng.status.airport.platform.impl.dji.action.airport;
import com.tuoheng.status.airport.events.AirportEvent;
import com.tuoheng.status.airport.platform.strategy.PlatformAction;
import com.tuoheng.status.airport.status.AirportState;
import org.springframework.statemachine.StateContext;
import org.springframework.stereotype.Component;
@Component
public class DjiOnlineAction implements PlatformAction<AirportState, AirportEvent> {
@Override
public String getName() {
return "DjiOnlineAction";
}
@Override
public void execute(StateContext<AirportState, AirportEvent> context) {
String machineId = (String) context.getExtendedState().getVariables().get("machineId");
System.out.println(String.format("[DJI] 机巢上线: %s", machineId));
// DJI平台特定的上线逻辑
// 例如初始化DJI SDK连接注册设备等
}
}

View File

@ -0,0 +1,22 @@
package com.tuoheng.status.airport.platform.impl.dji.action.airport;
import com.tuoheng.status.airport.events.AirportEvent;
import com.tuoheng.status.airport.platform.strategy.PlatformAction;
import com.tuoheng.status.airport.status.AirportState;
import org.springframework.statemachine.StateContext;
import org.springframework.stereotype.Component;
@Component
public class DjiOpenDebugModeAction implements PlatformAction<AirportState, AirportEvent> {
@Override
public String getName() {
return "DjiOpenDebugModeAction";
}
@Override
public void execute(StateContext<AirportState, AirportEvent> context) {
String machineId = (String) context.getExtendedState().getVariables().get("machineId");
System.out.println(String.format("[DJI] 开启调试模式: %s", machineId));
}
}

View File

@ -0,0 +1,22 @@
package com.tuoheng.status.airport.platform.impl.dji.action.airport;
import com.tuoheng.status.airport.events.AirportEvent;
import com.tuoheng.status.airport.platform.strategy.PlatformAction;
import com.tuoheng.status.airport.status.AirportState;
import org.springframework.statemachine.StateContext;
import org.springframework.stereotype.Component;
@Component
public class DjiRebootAction implements PlatformAction<AirportState, AirportEvent> {
@Override
public String getName() {
return "DjiRebootAction";
}
@Override
public void execute(StateContext<AirportState, AirportEvent> context) {
String machineId = (String) context.getExtendedState().getVariables().get("machineId");
System.out.println(String.format("[DJI] 机巢重启: %s", machineId));
}
}

View File

@ -0,0 +1,22 @@
package com.tuoheng.status.airport.platform.impl.dji.action.airport;
import com.tuoheng.status.airport.events.AirportEvent;
import com.tuoheng.status.airport.platform.strategy.PlatformAction;
import com.tuoheng.status.airport.status.AirportState;
import org.springframework.statemachine.StateContext;
import org.springframework.stereotype.Component;
@Component
public class DjiRebootCompletedAction implements PlatformAction<AirportState, AirportEvent> {
@Override
public String getName() {
return "DjiRebootCompletedAction";
}
@Override
public void execute(StateContext<AirportState, AirportEvent> context) {
String machineId = (String) context.getExtendedState().getVariables().get("machineId");
System.out.println(String.format("[DJI] 重启完成: %s", machineId));
}
}

View File

@ -0,0 +1,22 @@
package com.tuoheng.status.airport.platform.impl.dji.action.cover;
import com.tuoheng.status.airport.events.CoverEvent;
import com.tuoheng.status.airport.platform.strategy.PlatformAction;
import com.tuoheng.status.airport.status.CoverState;
import org.springframework.statemachine.StateContext;
import org.springframework.stereotype.Component;
@Component
public class DjiCloseCoverAction implements PlatformAction<CoverState, CoverEvent> {
@Override
public String getName() {
return "DjiCloseCoverAction";
}
@Override
public void execute(StateContext<CoverState, CoverEvent> context) {
String machineId = (String) context.getExtendedState().getVariables().get("machineId");
System.out.println(String.format("[DJI] 开始关舱: %s", machineId));
}
}

View File

@ -0,0 +1,22 @@
package com.tuoheng.status.airport.platform.impl.dji.action.cover;
import com.tuoheng.status.airport.events.CoverEvent;
import com.tuoheng.status.airport.platform.strategy.PlatformAction;
import com.tuoheng.status.airport.status.CoverState;
import org.springframework.statemachine.StateContext;
import org.springframework.stereotype.Component;
@Component
public class DjiCoverClosedAction implements PlatformAction<CoverState, CoverEvent> {
@Override
public String getName() {
return "DjiCoverClosedAction";
}
@Override
public void execute(StateContext<CoverState, CoverEvent> context) {
String machineId = (String) context.getExtendedState().getVariables().get("machineId");
System.out.println(String.format("[DJI] 舱门已关闭: %s", machineId));
}
}

View File

@ -0,0 +1,22 @@
package com.tuoheng.status.airport.platform.impl.dji.action.cover;
import com.tuoheng.status.airport.events.CoverEvent;
import com.tuoheng.status.airport.platform.strategy.PlatformAction;
import com.tuoheng.status.airport.status.CoverState;
import org.springframework.statemachine.StateContext;
import org.springframework.stereotype.Component;
@Component
public class DjiCoverErrorAction implements PlatformAction<CoverState, CoverEvent> {
@Override
public String getName() {
return "DjiCoverErrorAction";
}
@Override
public void execute(StateContext<CoverState, CoverEvent> context) {
String machineId = (String) context.getExtendedState().getVariables().get("machineId");
System.out.println(String.format("[DJI] 舱门错误: %s", machineId));
}
}

View File

@ -0,0 +1,22 @@
package com.tuoheng.status.airport.platform.impl.dji.action.cover;
import com.tuoheng.status.airport.events.CoverEvent;
import com.tuoheng.status.airport.platform.strategy.PlatformAction;
import com.tuoheng.status.airport.status.CoverState;
import org.springframework.statemachine.StateContext;
import org.springframework.stereotype.Component;
@Component
public class DjiCoverOpenedAction implements PlatformAction<CoverState, CoverEvent> {
@Override
public String getName() {
return "DjiCoverOpenedAction";
}
@Override
public void execute(StateContext<CoverState, CoverEvent> context) {
String machineId = (String) context.getExtendedState().getVariables().get("machineId");
System.out.println(String.format("[DJI] 舱门已打开: %s", machineId));
}
}

View File

@ -0,0 +1,22 @@
package com.tuoheng.status.airport.platform.impl.dji.action.cover;
import com.tuoheng.status.airport.events.CoverEvent;
import com.tuoheng.status.airport.platform.strategy.PlatformAction;
import com.tuoheng.status.airport.status.CoverState;
import org.springframework.statemachine.StateContext;
import org.springframework.stereotype.Component;
@Component
public class DjiCoverResetAction implements PlatformAction<CoverState, CoverEvent> {
@Override
public String getName() {
return "DjiCoverResetAction";
}
@Override
public void execute(StateContext<CoverState, CoverEvent> context) {
String machineId = (String) context.getExtendedState().getVariables().get("machineId");
System.out.println(String.format("[DJI] 舱门重置: %s", machineId));
}
}

View File

@ -0,0 +1,23 @@
package com.tuoheng.status.airport.platform.impl.dji.action.cover;
import com.tuoheng.status.airport.events.CoverEvent;
import com.tuoheng.status.airport.platform.strategy.PlatformAction;
import com.tuoheng.status.airport.status.CoverState;
import org.springframework.statemachine.StateContext;
import org.springframework.stereotype.Component;
@Component
public class DjiOpenCoverAction implements PlatformAction<CoverState, CoverEvent> {
@Override
public String getName() {
return "DjiOpenCoverAction";
}
@Override
public void execute(StateContext<CoverState, CoverEvent> context) {
String machineId = (String) context.getExtendedState().getVariables().get("machineId");
System.out.println(String.format("[DJI] 开始开舱: %s", machineId));
// DJI平台特定的开舱逻辑
}
}

View File

@ -0,0 +1,22 @@
package com.tuoheng.status.airport.platform.impl.dji.guard.airport;
import com.tuoheng.status.airport.events.AirportEvent;
import com.tuoheng.status.airport.platform.strategy.PlatformGuard;
import com.tuoheng.status.airport.status.AirportState;
import org.springframework.statemachine.StateContext;
import org.springframework.stereotype.Component;
@Component
public class DjiCanCloseDebugModeGuard implements PlatformGuard<AirportState, AirportEvent> {
@Override
public String getName() {
return "DjiCanCloseDebugModeGuard";
}
@Override
public boolean evaluate(StateContext<AirportState, AirportEvent> context) {
System.out.println("[DJI] 检查是否可以关闭调试模式");
return true;
}
}

View File

@ -0,0 +1,22 @@
package com.tuoheng.status.airport.platform.impl.dji.guard.airport;
import com.tuoheng.status.airport.events.AirportEvent;
import com.tuoheng.status.airport.platform.strategy.PlatformGuard;
import com.tuoheng.status.airport.status.AirportState;
import org.springframework.statemachine.StateContext;
import org.springframework.stereotype.Component;
@Component
public class DjiCanOfflineGuard implements PlatformGuard<AirportState, AirportEvent> {
@Override
public String getName() {
return "DjiCanOfflineGuard";
}
@Override
public boolean evaluate(StateContext<AirportState, AirportEvent> context) {
System.out.println("[DJI] 检查机巢是否可以离线");
return true;
}
}

View File

@ -0,0 +1,30 @@
package com.tuoheng.status.airport.platform.impl.dji.guard.airport;
import com.tuoheng.status.airport.events.AirportEvent;
import com.tuoheng.status.airport.platform.strategy.PlatformGuard;
import com.tuoheng.status.airport.status.AirportState;
import org.springframework.statemachine.StateContext;
import org.springframework.stereotype.Component;
/**
* DJI平台 - 机巢上线Guard
*/
@Component
public class DjiCanOnlineGuard implements PlatformGuard<AirportState, AirportEvent> {
@Override
public String getName() {
return "DjiCanOnlineGuard";
}
@Override
public boolean evaluate(StateContext<AirportState, AirportEvent> context) {
// DJI平台特定的上线检查逻辑
System.out.println("[DJI] 检查机巢是否可以上线");
// 这里可以添加DJI平台特定的检查逻辑例如
// - 检查DJI设备连接状态
// - 检查DJI固件版本
// - 检查DJI授权状态
return true;
}
}

View File

@ -0,0 +1,22 @@
package com.tuoheng.status.airport.platform.impl.dji.guard.airport;
import com.tuoheng.status.airport.events.AirportEvent;
import com.tuoheng.status.airport.platform.strategy.PlatformGuard;
import com.tuoheng.status.airport.status.AirportState;
import org.springframework.statemachine.StateContext;
import org.springframework.stereotype.Component;
@Component
public class DjiIsDebugModeGuard implements PlatformGuard<AirportState, AirportEvent> {
@Override
public String getName() {
return "DjiIsDebugModeGuard";
}
@Override
public boolean evaluate(StateContext<AirportState, AirportEvent> context) {
System.out.println("[DJI] 检查是否处于调试模式");
return true;
}
}

View File

@ -0,0 +1,22 @@
package com.tuoheng.status.airport.platform.impl.dji.guard.airport;
import com.tuoheng.status.airport.events.AirportEvent;
import com.tuoheng.status.airport.platform.strategy.PlatformGuard;
import com.tuoheng.status.airport.status.AirportState;
import org.springframework.statemachine.StateContext;
import org.springframework.stereotype.Component;
@Component
public class DjiIsNotDebugModeGuard implements PlatformGuard<AirportState, AirportEvent> {
@Override
public String getName() {
return "DjiIsNotDebugModeGuard";
}
@Override
public boolean evaluate(StateContext<AirportState, AirportEvent> context) {
System.out.println("[DJI] 检查是否不在调试模式");
return true;
}
}

View File

@ -0,0 +1,22 @@
package com.tuoheng.status.airport.platform.impl.dji.guard.airport;
import com.tuoheng.status.airport.events.AirportEvent;
import com.tuoheng.status.airport.platform.strategy.PlatformGuard;
import com.tuoheng.status.airport.status.AirportState;
import org.springframework.statemachine.StateContext;
import org.springframework.stereotype.Component;
@Component
public class DjiIsRebootCompletedGuard implements PlatformGuard<AirportState, AirportEvent> {
@Override
public String getName() {
return "DjiIsRebootCompletedGuard";
}
@Override
public boolean evaluate(StateContext<AirportState, AirportEvent> context) {
System.out.println("[DJI] 检查重启是否完成");
return true;
}
}

View File

@ -0,0 +1,22 @@
package com.tuoheng.status.airport.platform.impl.dji.guard.cover;
import com.tuoheng.status.airport.events.CoverEvent;
import com.tuoheng.status.airport.platform.strategy.PlatformGuard;
import com.tuoheng.status.airport.status.CoverState;
import org.springframework.statemachine.StateContext;
import org.springframework.stereotype.Component;
@Component
public class DjiCanCloseCoverGuard implements PlatformGuard<CoverState, CoverEvent> {
@Override
public String getName() {
return "DjiCanCloseCoverGuard";
}
@Override
public boolean evaluate(StateContext<CoverState, CoverEvent> context) {
System.out.println("[DJI] 检查舱门是否可以关闭");
return true;
}
}

View File

@ -0,0 +1,22 @@
package com.tuoheng.status.airport.platform.impl.dji.guard.cover;
import com.tuoheng.status.airport.events.CoverEvent;
import com.tuoheng.status.airport.platform.strategy.PlatformGuard;
import com.tuoheng.status.airport.status.CoverState;
import org.springframework.statemachine.StateContext;
import org.springframework.stereotype.Component;
@Component
public class DjiCanOpenCoverGuard implements PlatformGuard<CoverState, CoverEvent> {
@Override
public String getName() {
return "DjiCanOpenCoverGuard";
}
@Override
public boolean evaluate(StateContext<CoverState, CoverEvent> context) {
System.out.println("[DJI] 检查舱门是否可以打开");
return true;
}
}

View File

@ -0,0 +1,22 @@
package com.tuoheng.status.airport.platform.impl.dji.guard.cover;
import com.tuoheng.status.airport.events.CoverEvent;
import com.tuoheng.status.airport.platform.strategy.PlatformGuard;
import com.tuoheng.status.airport.status.CoverState;
import org.springframework.statemachine.StateContext;
import org.springframework.stereotype.Component;
@Component
public class DjiIsCoverClosedGuard implements PlatformGuard<CoverState, CoverEvent> {
@Override
public String getName() {
return "DjiIsCoverClosedGuard";
}
@Override
public boolean evaluate(StateContext<CoverState, CoverEvent> context) {
System.out.println("[DJI] 检查舱门是否已关闭");
return true;
}
}

View File

@ -0,0 +1,22 @@
package com.tuoheng.status.airport.platform.impl.dji.guard.cover;
import com.tuoheng.status.airport.events.CoverEvent;
import com.tuoheng.status.airport.platform.strategy.PlatformGuard;
import com.tuoheng.status.airport.status.CoverState;
import org.springframework.statemachine.StateContext;
import org.springframework.stereotype.Component;
@Component
public class DjiIsCoverOpenedGuard implements PlatformGuard<CoverState, CoverEvent> {
@Override
public String getName() {
return "DjiIsCoverOpenedGuard";
}
@Override
public boolean evaluate(StateContext<CoverState, CoverEvent> context) {
System.out.println("[DJI] 检查舱门是否已打开");
return true;
}
}

View File

@ -0,0 +1,74 @@
package com.tuoheng.status.airport.platform.repository;
import com.tuoheng.status.airport.platform.PlatformType;
import org.springframework.stereotype.Repository;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* 机巢平台映射仓储
* 模拟数据库查询存储机巢SN到平台类型的映射关系
*/
@Repository
public class AirportPlatformRepository {
/**
* 模拟数据库存储
* Key: 机巢SN
* Value: 平台类型
*/
private final Map<String, PlatformType> airportPlatformMap = new ConcurrentHashMap<>();
/**
* 初始化一些测试数据
*/
public AirportPlatformRepository() {
// 模拟数据库中的数据
airportPlatformMap.put("airport-001", PlatformType.DJI);
airportPlatformMap.put("airport-002", PlatformType.DJI);
airportPlatformMap.put("airport-003", PlatformType.DJI);
airportPlatformMap.put("airport-004", PlatformType.DJI);
}
/**
* 根据机巢SN查询平台类型
*
* @param airportSn 机巢序列号
* @return 平台类型如果不存在返回null
*/
public PlatformType getPlatformType(String airportSn) {
return airportPlatformMap.get(airportSn);
}
/**
* 保存机巢平台映射关系
*
* @param airportSn 机巢序列号
* @param platformType 平台类型
*/
public void savePlatformMapping(String airportSn, PlatformType platformType) {
airportPlatformMap.put(airportSn, platformType);
System.out.println(String.format("保存平台映射: %s -> %s", airportSn, platformType.getName()));
}
/**
* 删除机巢平台映射关系
*
* @param airportSn 机巢序列号
*/
public void deletePlatformMapping(String airportSn) {
airportPlatformMap.remove(airportSn);
System.out.println(String.format("删除平台映射: %s", airportSn));
}
/**
* 检查机巢是否已注册
*
* @param airportSn 机巢序列号
* @return 是否已注册
*/
public boolean exists(String airportSn) {
return airportPlatformMap.containsKey(airportSn);
}
}

View File

@ -0,0 +1,53 @@
package com.tuoheng.status.airport.platform.strategy;
import com.tuoheng.status.airport.events.AirportEvent;
import com.tuoheng.status.airport.platform.PlatformType;
import com.tuoheng.status.airport.status.AirportState;
/**
* 机巢平台策略接口
* 定义各平台需要实现的GuardAction和Listener
*/
public interface AirportPlatformStrategy {
/**
* 获取平台类型
*/
PlatformType getPlatformType();
// ==================== Guards ====================
PlatformGuard<AirportState, AirportEvent> getCanOnlineGuard();
PlatformGuard<AirportState, AirportEvent> getCanOfflineGuard();
PlatformGuard<AirportState, AirportEvent> getIsDebugModeGuard();
PlatformGuard<AirportState, AirportEvent> getIsNotDebugModeGuard();
PlatformGuard<AirportState, AirportEvent> getCanCloseDebugModeGuard();
PlatformGuard<AirportState, AirportEvent> getIsRebootCompletedGuard();
// ==================== Actions ====================
PlatformAction<AirportState, AirportEvent> getOnlineAction();
PlatformAction<AirportState, AirportEvent> getOfflineAction();
PlatformAction<AirportState, AirportEvent> getOpenDebugModeAction();
PlatformAction<AirportState, AirportEvent> getCloseDebugModeAction();
PlatformAction<AirportState, AirportEvent> getRebootAction();
PlatformAction<AirportState, AirportEvent> getRebootCompletedAction();
// ==================== Listener ====================
/**
* 获取平台Listener
* 每个平台有一个Listener实例所有该平台的机巢共享
*/
PlatformListener<AirportState, AirportEvent> getListener();
}

View File

@ -0,0 +1,49 @@
package com.tuoheng.status.airport.platform.strategy;
import com.tuoheng.status.airport.events.CoverEvent;
import com.tuoheng.status.airport.platform.PlatformType;
import com.tuoheng.status.airport.status.CoverState;
/**
* 舱门平台策略接口
* 定义各平台需要实现的GuardAction和Listener
*/
public interface CoverPlatformStrategy {
/**
* 获取平台类型
*/
PlatformType getPlatformType();
// ==================== Guards ====================
PlatformGuard<CoverState, CoverEvent> getCanOpenGuard();
PlatformGuard<CoverState, CoverEvent> getCanCloseGuard();
PlatformGuard<CoverState, CoverEvent> getIsOpenedGuard();
PlatformGuard<CoverState, CoverEvent> getIsClosedGuard();
// ==================== Actions ====================
PlatformAction<CoverState, CoverEvent> getOpenAction();
PlatformAction<CoverState, CoverEvent> getOpenedAction();
PlatformAction<CoverState, CoverEvent> getCloseAction();
PlatformAction<CoverState, CoverEvent> getClosedAction();
PlatformAction<CoverState, CoverEvent> getErrorAction();
PlatformAction<CoverState, CoverEvent> getResetAction();
// ==================== Listener ====================
/**
* 获取平台Listener
* 每个平台有一个Listener实例所有该平台的机巢共享
*/
PlatformListener<CoverState, CoverEvent> getListener();
}

View File

@ -0,0 +1,22 @@
package com.tuoheng.status.airport.platform.strategy;
import org.springframework.statemachine.StateContext;
import org.springframework.statemachine.action.Action;
/**
* 平台Action接口
* 各平台实现自己的Action逻辑
*/
public interface PlatformAction<S, E> extends Action<S, E> {
/**
* 获取Action名称
*/
String getName();
/**
* 执行Action
*/
@Override
void execute(StateContext<S, E> context);
}

View File

@ -0,0 +1,22 @@
package com.tuoheng.status.airport.platform.strategy;
import org.springframework.statemachine.StateContext;
import org.springframework.statemachine.guard.Guard;
/**
* 平台Guard接口
* 各平台实现自己的Guard逻辑
*/
public interface PlatformGuard<S, E> extends Guard<S, E> {
/**
* 获取Guard名称
*/
String getName();
/**
* 评估Guard条件
*/
@Override
boolean evaluate(StateContext<S, E> context);
}

View File

@ -0,0 +1,15 @@
package com.tuoheng.status.airport.platform.strategy;
import org.springframework.statemachine.listener.StateMachineListener;
/**
* 平台Listener接口
* 各平台可以定制自己的Listener逻辑
*/
public interface PlatformListener<S, E> extends StateMachineListener<S, E> {
/**
* 获取Listener名称
*/
String getName();
}