280 lines
9.2 KiB
Markdown
280 lines
9.2 KiB
Markdown
# 多平台机巢状态机架构说明
|
||
|
||
## 架构概述
|
||
|
||
本系统采用**策略模式 + 工厂模式**实现多平台支持,允许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.machine
|
||
├── 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. **性能优化**: 状态机缓存、懒加载等优化策略
|