215 lines
7.7 KiB
C#
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.

using System;
using Microsoft.Extensions.Logging;
using YunDa.Server.ISMSTcp.Models;
using YunDa.Server.ISMSTcp.Interfaces;
namespace YunDa.Server.ISMSTcp.Services
{
/// <summary>
/// 命令状态机实现
/// </summary>
public class CommandStateMachine : ICommandStateMachine
{
private readonly ILogger<CommandStateMachine> _logger;
private readonly object _lock = new object();
private CommandState _currentCommand;
public CommandStateMachine(ILogger<CommandStateMachine> logger)
{
_logger = logger;
}
/// <summary>
/// 当前命令状态
/// </summary>
public CommandState CurrentCommand
{
get
{
lock (_lock)
{
return _currentCommand;
}
}
}
/// <summary>
/// 是否有命令正在执行
/// </summary>
public bool HasPendingCommand
{
get
{
lock (_lock)
{
return _currentCommand != null && _currentCommand.State == CommandExecutionState.WaitingForResponse;
}
}
}
/// <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)
{
// 检查是否有命令正在执行
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;
}
}
/// <summary>
/// 完成当前命令
/// </summary>
/// <param name="commandName">响应的命令名称(用于验证)</param>
/// <returns>是否成功完成</returns>
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;
}
}
/// <summary>
/// 设置命令超时
/// </summary>
/// <returns>是否有命令被设置为超时</returns>
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;
}
}
/// <summary>
/// 检查并处理超时
/// </summary>
/// <returns>是否有命令超时</returns>
public bool CheckAndHandleTimeout()
{
lock (_lock)
{
if (_currentCommand != null && _currentCommand.IsTimeout == true)
{
return TimeoutCommand();
}
return false;
}
}
/// <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.LogInformation("Received OK response but no command is currently pending");
}
return false;
}
}
/// <summary>
/// 重置状态机
/// </summary>
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;
}
}
}
}