thingsboard-client-demo/src/main/java/com/tuoheng/machine/service/DrcMachineService.java

195 lines
5.9 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package com.tuoheng.machine.service;
import lombok.extern.slf4j.Slf4j;
import com.tuoheng.machine.events.DrcEvent;
import com.tuoheng.machine.redis.RedisStateStore;
import com.tuoheng.machine.status.DrcState;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.statemachine.StateMachine;
import org.springframework.statemachine.config.StateMachineFactory;
import org.springframework.stereotype.Component;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* DRC状态机管理器
* 负责管理多个机巢的DRC状态机实例
*/
@Slf4j
@Component
public class DrcMachineService {
@Autowired
StateMachineFactory<DrcState, DrcEvent> drcStateMachineFactory;
@Autowired
private RedisStateStore redisStateStore;
/**
* 存储所有机巢的DRC状态机实例
* Key: 机巢ID (airportSn)
* Value: 状态机实例
*/
private final Map<String, StateMachine<DrcState, DrcEvent>> stateMachineMap = new ConcurrentHashMap<>();
/**
* 获取或创建状态机
* 如果状态机不存在,则创建新的状态机实例
*
* @param airportSn 机巢序列号
* @return 状态机实例
*/
public StateMachine<DrcState, DrcEvent> getOrCreateStateMachine(String airportSn) {
return stateMachineMap.computeIfAbsent(airportSn, id -> {
StateMachine<DrcState, DrcEvent> stateMachine = drcStateMachineFactory.getStateMachine(id);
// 服务器重启后,状态机初始化为 UNKNOWN 状态
// 不从 Redis 恢复旧状态,等待第一次心跳同步真实状态
// 这样可以避免服务器重启期间丢失心跳导致的状态不一致问题
stateMachine.start();
log.info("创建并启动DRC状态机: %s, 初始状态: UNKNOWN (等待心跳同步)", id);
return stateMachine;
});
}
/**
* 获取状态机(不创建)
*
* @param airportSn 机巢序列号
* @return 状态机实例如果不存在返回null
*/
public StateMachine<DrcState, DrcEvent> getStateMachine(String airportSn) {
return stateMachineMap.get(airportSn);
}
/**
* 获取状态机的当前状态
*
* @param airportSn 机巢序列号
* @return 当前状态如果状态机不存在返回null
*/
public DrcState getCurrentState(String airportSn) {
StateMachine<DrcState, DrcEvent> stateMachine = stateMachineMap.get(airportSn);
if (stateMachine == null) {
log.info("DRC状态机不存在: {}", airportSn);
return null;
}
return stateMachine.getState().getId();
}
/**
* 获取状态机的所有当前状态(包括子状态)
*
* @param airportSn 机巢序列号
* @return 当前状态集合的字符串表示
*/
public String getCurrentStates(String airportSn) {
StateMachine<DrcState, DrcEvent> stateMachine = stateMachineMap.get(airportSn);
if (stateMachine == null) {
return "状态机不存在";
}
StringBuilder states = new StringBuilder();
stateMachine.getState().getIds().forEach(state -> {
if (states.length() > 0) {
states.append(" -> ");
}
states.append(state);
});
return states.toString();
}
/**
* 发送事件到状态机
*
* @param airportSn 机巢序列号
* @param event 事件
* @return 是否发送成功
*/
public boolean sendEvent(String airportSn, DrcEvent event) {
StateMachine<DrcState, DrcEvent> stateMachine = getOrCreateStateMachine(airportSn);
boolean result = stateMachine.sendEvent(event);
if (result) {
// 持久化最新状态
redisStateStore.saveDrcState(airportSn, stateMachine.getState().getId());
log.info("DRC事件发送成功 - 机巢: {}, 事件: {}, 当前状态: {}",
airportSn, event, getCurrentStates(airportSn));
} else {
log.error("DRC事件发送失败 - 机巢: {}, 事件: {}, 当前状态: {}",
airportSn, event, getCurrentStates(airportSn));
}
return result;
}
/**
* 移除状态机
*
* @param airportSn 机巢序列号
*/
public void removeStateMachine(String airportSn) {
StateMachine<DrcState, DrcEvent> stateMachine = stateMachineMap.remove(airportSn);
if (stateMachine != null) {
stateMachine.stop();
log.info("停止并移除DRC状态机: {}", airportSn);
}
}
/**
* 检查状态机是否存在
*
* @param airportSn 机巢序列号
* @return 是否存在
*/
public boolean hasStateMachine(String airportSn) {
return stateMachineMap.containsKey(airportSn);
}
/**
* 获取所有状态机的数量
*
* @return 状态机数量
*/
public int getStateMachineCount() {
return stateMachineMap.size();
}
/**
* 获取所有机巢ID
*
* @return 机巢ID集合
*/
public java.util.Set<String> getAllAirportIds() {
return stateMachineMap.keySet();
}
/**
* 检查状态机是否处于指定状态
*
* @param airportSn 机巢序列号
* @param state 要检查的状态
* @return 是否处于指定状态
*/
public boolean isInState(String airportSn, DrcState state) {
StateMachine<DrcState, DrcEvent> stateMachine = stateMachineMap.get(airportSn);
if (stateMachine == null) {
return false;
}
return stateMachine.getState().getIds().contains(state);
}
/**
* 重启状态机
*
* @param airportSn 机巢序列号
*/
public void restartStateMachine(String airportSn) {
removeStateMachine(airportSn);
getOrCreateStateMachine(airportSn);
log.info("重启DRC状态机: {}", airportSn);
}
}