215 lines
7.7 KiB
C#
Raw Normal View History

2025-07-16 09:20:13 +08:00
using System;
using Microsoft.Extensions.Logging;
using YunDa.Server.ISMSTcp.Models;
2025-07-31 18:51:24 +08:00
using YunDa.Server.ISMSTcp.Interfaces;
2025-07-16 09:20:13 +08:00
namespace YunDa.Server.ISMSTcp.Services
{
/// <summary>
/// 命令状态机实现
/// </summary>
public class CommandStateMachine : ICommandStateMachine
{
private readonly ILogger<CommandStateMachine> _logger;
private readonly object _lock = new object();
2025-07-31 18:51:24 +08:00
private CommandState _currentCommand;
2025-07-16 09:20:13 +08:00
public CommandStateMachine(ILogger<CommandStateMachine> logger)
{
_logger = logger;
}
/// <summary>
/// 当前命令状态
/// </summary>
2025-07-31 18:51:24 +08:00
public CommandState CurrentCommand
2025-07-16 09:20:13 +08:00
{
get
{
lock (_lock)
{
return _currentCommand;
}
}
}
/// <summary>
/// 是否有命令正在执行
/// </summary>
public bool HasPendingCommand
{
get
{
lock (_lock)
{
2025-07-31 18:51:24 +08:00
return _currentCommand != null && _currentCommand.State == CommandExecutionState.WaitingForResponse;
2025-07-16 09:20:13 +08:00
}
}
}
/// <summary>
/// 开始执行命令
/// </summary>
/// <param name="commandName">命令名称</param>
/// <param name="fullMessage">完整消息</param>
/// <param name="timeoutSeconds">超时时间(秒)</param>
/// <returns>是否成功开始执行</returns>
public bool StartCommand(string commandName, string fullMessage, int timeoutSeconds = 180)
{
if (string.IsNullOrWhiteSpace(commandName))
{
_logger.LogWarning("Cannot start command with empty name");
return false;
}
lock (_lock)
{
// 检查是否有命令正在执行
2025-07-31 18:51:24 +08:00
if (_currentCommand != null && _currentCommand.State == CommandExecutionState.WaitingForResponse)
2025-07-16 09:20:13 +08:00
{
if (_currentCommand.IsTimeout)
{
_logger.LogWarning("Previous command '{PreviousCommand}' timed out, starting new command '{NewCommand}'",
_currentCommand.CommandName, commandName);
_currentCommand.State = CommandExecutionState.Timeout;
}
else
{
_logger.LogWarning("Command '{CurrentCommand}' is still pending (remaining: {RemainingTime:F1}s), cannot start new command '{NewCommand}'",
_currentCommand.CommandName, _currentCommand.RemainingTimeoutSeconds, commandName);
return false;
}
}
// 创建新的命令状态
_currentCommand = new CommandState
{
CommandName = commandName,
FullMessage = fullMessage,
State = CommandExecutionState.WaitingForResponse,
SentTime = DateTime.Now,
TimeoutSeconds = timeoutSeconds
};
_logger.LogInformation("Started command '{CommandName}' with timeout {TimeoutSeconds}s",
commandName, timeoutSeconds);
return true;
}
}
/// <summary>
/// 完成当前命令
/// </summary>
/// <param name="commandName">响应的命令名称(用于验证)</param>
/// <returns>是否成功完成</returns>
2025-07-31 18:51:24 +08:00
public bool CompleteCommand(string commandName = null)
2025-07-16 09:20:13 +08:00
{
lock (_lock)
{
if (_currentCommand == null || _currentCommand.State != CommandExecutionState.WaitingForResponse)
{
_logger.LogWarning("No pending command to complete");
return false;
}
// 如果提供了命令名称,验证是否匹配
if (!string.IsNullOrEmpty(commandName) &&
!string.Equals(_currentCommand.CommandName, commandName, StringComparison.OrdinalIgnoreCase))
{
_logger.LogWarning("Command name mismatch: expected '{Expected}', got '{Actual}'",
_currentCommand.CommandName, commandName);
return false;
}
var executionTime = DateTime.Now.Subtract(_currentCommand.SentTime).TotalSeconds;
_currentCommand.State = CommandExecutionState.Completed;
_logger.LogInformation("Completed command '{CommandName}' in {ExecutionTime:F2}s",
_currentCommand.CommandName, executionTime);
return true;
}
}
/// <summary>
/// 设置命令超时
/// </summary>
/// <returns>是否有命令被设置为超时</returns>
public bool TimeoutCommand()
{
lock (_lock)
{
2025-07-31 18:51:24 +08:00
if (_currentCommand != null && _currentCommand.State == CommandExecutionState.WaitingForResponse)
2025-07-16 09:20:13 +08:00
{
_currentCommand.State = CommandExecutionState.Timeout;
_logger.LogWarning("Command '{CommandName}' timed out after {TimeoutSeconds}s",
_currentCommand.CommandName, _currentCommand.TimeoutSeconds);
return true;
}
return false;
}
}
/// <summary>
/// 检查并处理超时
/// </summary>
/// <returns>是否有命令超时</returns>
public bool CheckAndHandleTimeout()
{
lock (_lock)
{
2025-07-31 18:51:24 +08:00
if (_currentCommand != null && _currentCommand.IsTimeout == true)
2025-07-16 09:20:13 +08:00
{
return TimeoutCommand();
}
return false;
}
}
2025-07-31 18:51:24 +08:00
/// <summary>
/// 处理OK响应解锁命令状态
/// </summary>
/// <returns>是否成功处理OK响应</returns>
public bool HandleOkResponse()
{
lock (_lock)
{
if (_currentCommand != null && _currentCommand.State == CommandExecutionState.WaitingForResponse)
{
var executionTime = DateTime.Now.Subtract(_currentCommand.SentTime).TotalSeconds;
_currentCommand.State = CommandExecutionState.Completed;
_logger.LogInformation("Command '{CommandName}' completed with OK response in {ExecutionTime:F2}s",
_currentCommand.CommandName, executionTime);
return true;
}
else if (_currentCommand != null)
{
_logger.LogWarning("Received OK response but command '{CommandName}' is in state: {State}",
_currentCommand.CommandName, _currentCommand.State);
}
else
{
_logger.LogDebug("Received OK response but no command is currently pending");
}
return false;
}
}
2025-07-16 09:20:13 +08:00
/// <summary>
/// 重置状态机
/// </summary>
public void Reset()
{
lock (_lock)
{
if (_currentCommand != null)
{
2025-07-31 18:51:24 +08:00
_logger.LogInformation("Resetting command state machine, current command: '{CommandName}' in state: {State}",
2025-07-16 09:20:13 +08:00
_currentCommand.CommandName, _currentCommand.State);
}
_currentCommand = null;
}
}
}
}