package com.tuoheng.machine; import com.tuoheng.machine.command.*; import com.tuoheng.machine.instruction.InstructionContext; import com.tuoheng.machine.state.MachineStates; import com.tuoheng.machine.statemachine.MachineStateManager; import com.tuoheng.machine.statemachine.StateChangeListener; import com.tuoheng.machine.vendor.VendorConfig; import com.tuoheng.machine.vendor.VendorRegistry; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import java.util.List; import java.util.Map; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ConcurrentHashMap; /** * 设备命令管理器(框架使用者的主要入口) */ @Slf4j @Component public class MachineCommandManager { private final VendorRegistry vendorRegistry; private final MachineStateManager stateManager; private final TransactionExecutor transactionExecutor; /** * SN -> 当前正在执行的命令 */ private final Map executingCommands = new ConcurrentHashMap<>(); /** * 命令执行监听器 */ private final Map commandListeners = new ConcurrentHashMap<>(); public MachineCommandManager(VendorRegistry vendorRegistry, MachineStateManager stateManager, TransactionExecutor transactionExecutor) { this.vendorRegistry = vendorRegistry; this.stateManager = stateManager; this.transactionExecutor = transactionExecutor; } /** * 绑定设备到厂家 * * @param sn 设备SN号 * @param vendorType 厂家类型 */ public void bindMachine(String sn, String vendorType) { vendorRegistry.bindSnToVendor(sn, vendorType); log.info("绑定设备到厂家: sn=, vendorType={}", sn, vendorType); } /** * 解绑设备 * * @param sn 设备SN号 */ public void unbindMachine(String sn) { vendorRegistry.unbindSn(sn); executingCommands.remove(sn); stateManager.removeStates(sn); log.info("解绑设备: sn={}", sn); } /** * 获取设备当前状态 * * @param sn 设备SN号 * @return 设备状态 */ public MachineStates getMachineStates(String sn) { return stateManager.getStates(sn); } /** * 更新设备状态(通常在心跳中调用) * * @param sn 设备SN号 * @param newStates 新状态 */ public void updateMachineStates(String sn, MachineStates newStates) { stateManager.updateStates(sn, newStates); } /** * 判断设备是否正在执行命令 * * @param sn 设备SN号 * @return 是否正在执行命令 */ public boolean isExecutingCommand(String sn) { CommandExecution execution = executingCommands.get(sn); return execution != null && !execution.getFuture().isDone(); } /** * 获取设备当前正在执行的命令类型 * * @param sn 设备SN号 * @return 命令类型,如果没有正在执行的命令则返回null */ public CommandType getExecutingCommandType(String sn) { CommandExecution execution = executingCommands.get(sn); if (execution != null && !execution.getFuture().isDone()) { return execution.getCommandType(); } return null; } /** * 获取设备在当前状态下可以执行的命令列表 * * @param sn 设备SN号 * @return 可执行的命令列表 */ public List getAvailableCommands(String sn) { VendorConfig vendorConfig = vendorRegistry.getVendorConfig(sn); if (vendorConfig == null) { log.warn("设备未绑定厂家: sn={}", sn); return List.of(); } MachineStates currentStates = stateManager.getStates(sn); return vendorConfig.getAvailableCommands(currentStates); } /** * 执行命令 * * @param sn 设备SN号 * @param commandType 命令类型 * @return 命令执行结果的Future */ public CompletableFuture executeCommand(String sn, CommandType commandType) { return executeCommand(sn, commandType, Map.of()); } /** * 执行命令(带参数) * * @param sn 设备SN号 * @param commandType 命令类型 * @param params 命令参数 * @return 命令执行结果的Future */ public CompletableFuture executeCommand(String sn, CommandType commandType, Map params) { log.info("收到命令执行请求: sn={}, commandType={}, params={}", sn, commandType, params); // 1. 检查设备是否已绑定厂家 VendorConfig vendorConfig = vendorRegistry.getVendorConfig(sn); if (vendorConfig == null) { String error = "设备未绑定厂家"; log.error("{}: sn={}", error, sn); return CompletableFuture.completedFuture(CommandResult.failure(commandType, error)); } // 2. 检查是否正在执行其他命令 if (isExecutingCommand(sn)) { String error = "设备正在执行其他命令: " + getExecutingCommandType(sn); log.warn("{}: sn={}", error, sn); return CompletableFuture.completedFuture(CommandResult.failure(commandType, error)); } // 3. 检查当前状态是否可以执行该命令 MachineStates currentStates = stateManager.getStates(sn); if (!vendorConfig.canExecuteCommand(currentStates, commandType)) { String error = "当前状态不允许执行该命令"; log.warn("{}: sn={}, commandType={}, currentStates={}", error, sn, commandType, currentStates); return CompletableFuture.completedFuture(CommandResult.failure(commandType, error)); } // 4. 获取事务定义 Transaction transaction = vendorConfig.getTransaction(commandType); if (transaction == null) { String error = "厂家不支持该命令"; log.error("{}: sn={}, commandType={}, vendorType={}", error, sn, commandType, vendorConfig.getVendorType()); return CompletableFuture.completedFuture(CommandResult.failure(commandType, error)); } // 5. 创建指令上下文 InstructionContext context = new InstructionContext(sn, vendorConfig.getVendorType()); params.forEach(context::putCommandParam); // 6. 执行事务 CompletableFuture future = transactionExecutor.executeTransaction(transaction, context); // 7. 记录正在执行的命令 executingCommands.put(sn, new CommandExecution(commandType, future, System.currentTimeMillis())); // 8. 添加完成回调 future.whenComplete((result, throwable) -> { executingCommands.remove(sn); if (throwable != null) { log.error("命令执行异常: sn={}, commandType={}", sn, commandType, throwable); notifyCommandComplete(sn, CommandResult.failure(commandType, "命令执行异常: " + throwable.getMessage())); } else { log.info("命令执行完成: sn={}, commandType={}, success={}", sn, commandType, result.isSuccess()); notifyCommandComplete(sn, result); } }); return future; } /** * 注册命令执行监听器 * * @param listenerId 监听器ID * @param listener 监听器 */ public void registerCommandListener(String listenerId, CommandExecutionListener listener) { commandListeners.put(listenerId, listener); log.debug("注册命令执行监听器: listenerId={}", listenerId); } /** * 取消注册命令执行监听器 * * @param listenerId 监听器ID */ public void unregisterCommandListener(String listenerId) { commandListeners.remove(listenerId); log.debug("取消注册命令执行监听器: listenerId={}", listenerId); } /** * 注册状态变化监听器 * * @param listenerId 监听器ID * @param listener 监听器 */ public void registerStateChangeListener(String listenerId, StateChangeListener listener) { stateManager.registerStateChangeListener(listenerId, listener); } /** * 取消注册状态变化监听器 * * @param listenerId 监听器ID */ public void unregisterStateChangeListener(String listenerId) { stateManager.unregisterStateChangeListener(listenerId); } /** * 通知命令执行完成 */ private void notifyCommandComplete(String sn, CommandResult result) { for (CommandExecutionListener listener : commandListeners.values()) { try { listener.onCommandComplete(sn, result); } catch (Exception e) { log.error("命令执行监听器执行失败: sn={}, commandType={}", sn, result.getCommandType(), e); } } } /** * 命令执行信息 */ private static class CommandExecution { private final CommandType commandType; private final CompletableFuture future; private final long startTime; public CommandExecution(CommandType commandType, CompletableFuture future, long startTime) { this.commandType = commandType; this.future = future; this.startTime = startTime; } public CommandType getCommandType() { return commandType; } public CompletableFuture getFuture() { return future; } public long getStartTime() { return startTime; } } }