using System;
using Microsoft.Extensions.Logging;
using YunDa.Server.ISMSTcp.Models;
using YunDa.Server.ISMSTcp.Interfaces;
namespace YunDa.Server.ISMSTcp.Services
{
///
/// 命令状态机实现
///
public class CommandStateMachine : ICommandStateMachine
{
private readonly ILogger _logger;
private readonly object _lock = new object();
private CommandState _currentCommand;
public CommandStateMachine(ILogger logger)
{
_logger = logger;
}
///
/// 当前命令状态
///
public CommandState CurrentCommand
{
get
{
lock (_lock)
{
return _currentCommand;
}
}
}
///
/// 是否有命令正在执行
///
public bool HasPendingCommand
{
get
{
lock (_lock)
{
return _currentCommand != null && _currentCommand.State == CommandExecutionState.WaitingForResponse;
}
}
}
///
/// 开始执行命令
///
/// 命令名称
/// 完整消息
/// 超时时间(秒)
/// 是否成功开始执行
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)
{
// 检查是否有命令正在执行
if (_currentCommand != null && _currentCommand.State == CommandExecutionState.WaitingForResponse)
{
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;
}
}
///
/// 完成当前命令
///
/// 响应的命令名称(用于验证)
/// 是否成功完成
public bool CompleteCommand(string commandName = null)
{
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;
}
}
///
/// 设置命令超时
///
/// 是否有命令被设置为超时
public bool TimeoutCommand()
{
lock (_lock)
{
if (_currentCommand != null && _currentCommand.State == CommandExecutionState.WaitingForResponse)
{
_currentCommand.State = CommandExecutionState.Timeout;
_logger.LogWarning("Command '{CommandName}' timed out after {TimeoutSeconds}s",
_currentCommand.CommandName, _currentCommand.TimeoutSeconds);
return true;
}
return false;
}
}
///
/// 检查并处理超时
///
/// 是否有命令超时
public bool CheckAndHandleTimeout()
{
lock (_lock)
{
if (_currentCommand != null && _currentCommand.IsTimeout == true)
{
return TimeoutCommand();
}
return false;
}
}
///
/// 处理OK响应,解锁命令状态
///
/// 是否成功处理OK响应
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.LogInformation("Received OK response but no command is currently pending");
}
return false;
}
}
///
/// 重置状态机
///
public void Reset()
{
lock (_lock)
{
if (_currentCommand != null)
{
_logger.LogInformation("Resetting command state machine, current command: '{CommandName}' in state: {State}",
_currentCommand.CommandName, _currentCommand.State);
}
_currentCommand = null;
}
}
}
}