Files
OrpaonVision/OrpaonVision.SiteApp/Runtime/Services/AdvancedRuntimeStateMachineService.cs
2026-04-06 22:04:05 +08:00

1325 lines
48 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 Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using OrpaonVision.Core.Results;
using OrpaonVision.Core.ManualOverride;
using OrpaonVision.SiteApp.Runtime.Contracts;
using OrpaonVision.SiteApp.Runtime.Options;
using System.Collections.Concurrent;
namespace OrpaonVision.SiteApp.Runtime.Services;
/// <summary>
/// 高级运行时状态机服务。
/// </summary>
public sealed class AdvancedRuntimeStateMachineService : IRuntimeStateMachineService, IDisposable
{
private readonly ILogger<AdvancedRuntimeStateMachineService> _logger;
private readonly RuntimeOptions _options;
private readonly IManualOverrideService _manualOverrideService;
private readonly ConcurrentQueue<StateTransitionEvent> _eventHistory;
private readonly object _stateLock = new();
private RuntimeState _currentState;
private int _currentLayer;
private DateTime _lastTransitionTime;
private bool _isPaused;
private bool _isStopped;
public AdvancedRuntimeStateMachineService(
ILogger<AdvancedRuntimeStateMachineService> logger,
IOptions<RuntimeOptions> options,
IManualOverrideService manualOverrideService)
{
_logger = logger;
_options = options.Value;
_manualOverrideService = manualOverrideService;
_eventHistory = new ConcurrentQueue<StateTransitionEvent>();
Reset();
}
/// <inheritdoc />
public RuntimeStateSnapshotDto GetSnapshot()
{
lock (_stateLock)
{
return new RuntimeStateSnapshotDto
{
CurrentLayer = _currentLayer,
TotalLayers = _options.TotalLayers,
StateText = GetStateDescription(_currentState)
};
}
}
/// <inheritdoc />
public Result MoveToNextLayer()
{
lock (_stateLock)
{
try
{
_logger.LogDebug("尝试移动到下一层:当前层={CurrentLayer},总层数={TotalLayers}",
_currentLayer, _options.TotalLayers);
// 检查是否可以移动
if (!CanMoveToNextLayer())
{
var reason = GetCannotMoveForwardReason();
_logger.LogWarning("无法移动到下一层:{Reason}", reason);
return Result.Fail("CANNOT_MOVE_FORWARD", reason);
}
// 记录状态转换事件
var previousState = _currentState;
var previousLayer = _currentLayer;
// 执行状态转换
_currentLayer++;
_currentState = RuntimeState.Running;
_lastTransitionTime = DateTime.UtcNow;
// 记录事件
var transitionEvent = new StateTransitionEvent
{
EventType = StateTransitionEventType.LayerForward,
PreviousState = previousState,
NewState = _currentState,
PreviousLayer = previousLayer,
NewLayer = _currentLayer,
Timestamp = _lastTransitionTime,
Reason = "用户请求移动到下一层"
};
_eventHistory.Enqueue(transitionEvent);
_logger.LogInformation("已移动到第 {CurrentLayer} 层,状态:{State}", _currentLayer, _currentState);
// 检查是否完成所有层
if (_currentLayer >= _options.TotalLayers)
{
return CompleteProcess();
}
return Result.Success("LAYER_MOVED_FORWARD", $"已移动到第 {_currentLayer} 层");
}
catch (Exception ex)
{
var traceId = Guid.NewGuid().ToString("N");
_logger.LogError(ex, "移动到下一层失败。TraceId: {TraceId}", traceId);
var result = Result.FromException(ex, "MOVE_TO_NEXT_LAYER_FAILED", "移动到下一层失败", traceId);
return Result.FailWithTrace(result.Code, result.Message, result.TraceId ?? traceId, result.Errors.ToArray());
}
}
}
/// <inheritdoc />
public Result MoveToPreviousLayer()
{
lock (_stateLock)
{
try
{
_logger.LogDebug("尝试移动到上一层:当前层={CurrentLayer}", _currentLayer);
// 检查是否可以移动
if (!CanMoveToPreviousLayer())
{
var reason = GetCannotMoveBackwardReason();
_logger.LogWarning("无法移动到上一层:{Reason}", reason);
return Result.Fail("CANNOT_MOVE_BACKWARD", reason);
}
// 记录状态转换事件
var previousState = _currentState;
var previousLayer = _currentLayer;
// 执行状态转换
_currentLayer--;
_currentState = RuntimeState.Running;
_lastTransitionTime = DateTime.UtcNow;
// 记录事件
var transitionEvent = new StateTransitionEvent
{
EventType = StateTransitionEventType.LayerBackward,
PreviousState = previousState,
NewState = _currentState,
PreviousLayer = previousLayer,
NewLayer = _currentLayer,
Timestamp = _lastTransitionTime,
Reason = "用户请求移动到上一层"
};
_eventHistory.Enqueue(transitionEvent);
_logger.LogInformation("已移动到第 {CurrentLayer} 层,状态:{State}", _currentLayer, _currentState);
return Result.Success("LAYER_MOVED_BACKWARD", $"已移动到第 {_currentLayer} 层");
}
catch (Exception ex)
{
var traceId = Guid.NewGuid().ToString("N");
_logger.LogError(ex, "移动到上一层失败。TraceId: {TraceId}", traceId);
var result = Result.FromException(ex, "MOVE_TO_PREVIOUS_LAYER_FAILED", "移动到上一层失败", traceId);
return Result.FailWithTrace(result.Code, result.Message, result.TraceId ?? traceId, result.Errors.ToArray());
}
}
}
/// <inheritdoc />
public Result Pause()
{
lock (_stateLock)
{
try
{
_logger.LogDebug("尝试暂停状态机");
// 检查是否可以暂停
if (!CanPause())
{
var reason = GetCannotPauseReason();
_logger.LogWarning("无法暂停:{Reason}", reason);
return Result.Fail("CANNOT_PAUSE", reason);
}
// 记录状态转换事件
var previousState = _currentState;
// 执行状态转换
_currentState = RuntimeState.Paused;
_isPaused = true;
_lastTransitionTime = DateTime.UtcNow;
// 记录事件
var transitionEvent = new StateTransitionEvent
{
EventType = StateTransitionEventType.Pause,
PreviousState = previousState,
NewState = _currentState,
PreviousLayer = _currentLayer,
NewLayer = _currentLayer,
Timestamp = _lastTransitionTime,
Reason = "用户请求暂停"
};
_eventHistory.Enqueue(transitionEvent);
_logger.LogInformation("状态机已暂停,当前层:{CurrentLayer}", _currentLayer);
return Result.Success("STATE_MACHINE_PAUSED", "状态机已暂停");
}
catch (Exception ex)
{
var traceId = Guid.NewGuid().ToString("N");
_logger.LogError(ex, "暂停状态机失败。TraceId: {TraceId}", traceId);
var result = Result.FromException(ex, "PAUSE_STATE_MACHINE_FAILED", "暂停状态机失败", traceId);
return Result.FailWithTrace(result.Code, result.Message, result.TraceId ?? traceId, result.Errors.ToArray());
}
}
}
/// <inheritdoc />
public Result Resume()
{
lock (_stateLock)
{
try
{
_logger.LogDebug("尝试恢复状态机");
// 检查是否可以恢复
if (!CanResume())
{
var reason = GetCannotResumeReason();
_logger.LogWarning("无法恢复:{Reason}", reason);
return Result.Fail("CANNOT_RESUME", reason);
}
// 记录状态转换事件
var previousState = _currentState;
// 执行状态转换
_currentState = RuntimeState.Running;
_isPaused = false;
_lastTransitionTime = DateTime.UtcNow;
// 记录事件
var transitionEvent = new StateTransitionEvent
{
EventType = StateTransitionEventType.Resume,
PreviousState = previousState,
NewState = _currentState,
PreviousLayer = _currentLayer,
NewLayer = _currentLayer,
Timestamp = _lastTransitionTime,
Reason = "用户请求恢复"
};
_eventHistory.Enqueue(transitionEvent);
_logger.LogInformation("状态机已恢复,当前层:{CurrentLayer}", _currentLayer);
return Result.Success("STATE_MACHINE_RESUMED", "状态机已恢复");
}
catch (Exception ex)
{
var traceId = Guid.NewGuid().ToString("N");
_logger.LogError(ex, "恢复状态机失败。TraceId: {TraceId}", traceId);
var result = Result.FromException(ex, "RESUME_STATE_MACHINE_FAILED", "恢复状态机失败", traceId);
return Result.FailWithTrace(result.Code, result.Message, result.TraceId ?? traceId, result.Errors.ToArray());
}
}
}
/// <inheritdoc />
public Result Stop()
{
lock (_stateLock)
{
try
{
_logger.LogDebug("尝试停止状态机");
// 检查是否可以停止
if (!CanStop())
{
var reason = GetCannotStopReason();
_logger.LogWarning("无法停止:{Reason}", reason);
return Result.Fail("CANNOT_STOP", reason);
}
// 记录状态转换事件
var previousState = _currentState;
// 执行状态转换
_currentState = RuntimeState.Stopped;
_isStopped = true;
_isPaused = false;
_lastTransitionTime = DateTime.UtcNow;
// 记录事件
var transitionEvent = new StateTransitionEvent
{
EventType = StateTransitionEventType.Stop,
PreviousState = previousState,
NewState = _currentState,
PreviousLayer = _currentLayer,
NewLayer = _currentLayer,
Timestamp = _lastTransitionTime,
Reason = "用户请求停止"
};
_eventHistory.Enqueue(transitionEvent);
_logger.LogInformation("状态机已停止,当前层:{CurrentLayer}", _currentLayer);
return Result.Success("STATE_MACHINE_STOPPED", "状态机已停止");
}
catch (Exception ex)
{
var traceId = Guid.NewGuid().ToString("N");
_logger.LogError(ex, "停止状态机失败。TraceId: {TraceId}", traceId);
var result = Result.FromException(ex, "STOP_STATE_MACHINE_FAILED", "停止状态机失败", traceId);
return Result.FailWithTrace(result.Code, result.Message, result.TraceId ?? traceId, result.Errors.ToArray());
}
}
}
/// <inheritdoc />
public void Reset()
{
lock (_stateLock)
{
try
{
_logger.LogInformation("重置状态机");
// 记录重置事件
var transitionEvent = new StateTransitionEvent
{
EventType = StateTransitionEventType.Reset,
PreviousState = _currentState,
NewState = RuntimeState.Idle,
PreviousLayer = _currentLayer,
NewLayer = 1,
Timestamp = DateTime.UtcNow,
Reason = "用户请求重置"
};
_eventHistory.Enqueue(transitionEvent);
// 重置状态
_currentState = RuntimeState.Idle;
_currentLayer = 1;
_lastTransitionTime = DateTime.UtcNow;
_isPaused = false;
_isStopped = false;
_logger.LogInformation("状态机已重置");
}
catch (Exception ex)
{
_logger.LogError(ex, "重置状态机失败");
}
}
}
/// <inheritdoc />
public Result<IReadOnlyList<StateTransitionEvent>> GetEventHistory(int maxCount = 100)
{
try
{
var events = _eventHistory.ToArray();
var recentEvents = events.Length > maxCount
? events[^maxCount..]
: events;
return Result<IReadOnlyList<StateTransitionEvent>>.Success(recentEvents.ToList(),
message: $"获取到 {recentEvents.Length} 个历史事件");
}
catch (Exception ex)
{
var traceId = Guid.NewGuid().ToString("N");
_logger.LogError(ex, "获取事件历史失败。TraceId: {TraceId}", traceId);
var result = Result.FromException(ex, "GET_EVENT_HISTORY_FAILED", "获取事件历史失败", traceId);
return Result<IReadOnlyList<StateTransitionEvent>>.FailWithTrace(result.Code, result.Message, result.TraceId ?? traceId, result.Errors.ToArray());
}
}
/// <summary>
/// 完成处理流程。
/// </summary>
private Result CompleteProcess()
{
_currentState = RuntimeState.Completed;
_lastTransitionTime = DateTime.UtcNow;
// 记录完成事件
var transitionEvent = new StateTransitionEvent
{
EventType = StateTransitionEventType.Complete,
PreviousState = RuntimeState.Running,
NewState = _currentState,
PreviousLayer = _currentLayer - 1,
NewLayer = _currentLayer,
Timestamp = _lastTransitionTime,
Reason = "所有层处理完成"
};
_eventHistory.Enqueue(transitionEvent);
_logger.LogInformation("处理流程已完成,共处理 {TotalLayers} 层", _options.TotalLayers);
return Result.Success("PROCESS_COMPLETED", $"所有 {_options.TotalLayers} 层处理完成");
}
#region
private GuardResult CanInitialize()
{
return _currentState == RuntimeState.Uninitialized
? new GuardResult { IsAllowed = true, Reason = "可以从未初始化状态开始初始化" }
: new GuardResult { IsAllowed = false, Reason = $"当前状态 {_currentState} 不允许初始化" };
}
private GuardResult CanStart()
{
return _currentState == RuntimeState.Idle
? new GuardResult { IsAllowed = true, Reason = "可以从空闲状态开始运行" }
: new GuardResult { IsAllowed = false, Reason = $"当前状态 {_currentState} 不允许开始运行" };
}
private GuardResult CanAcceptProduct()
{
return _currentState == RuntimeState.Ready
? new GuardResult { IsAllowed = true, Reason = "就绪状态可以接受产品" }
: new GuardResult { IsAllowed = false, Reason = $"当前状态 {_currentState} 不允许接受产品" };
}
private GuardResult CanStartLayerIdentification()
{
return _currentState == RuntimeState.WaitingProduct || _currentState == RuntimeState.Ready
? new GuardResult { IsAllowed = true, Reason = "可以开始层识别" }
: new GuardResult { IsAllowed = false, Reason = $"当前状态 {_currentState} 不允许开始层识别" };
}
private GuardResult CanCompleteLayerIdentification()
{
return _currentState == RuntimeState.LayerIdentifying
? new GuardResult { IsAllowed = true, Reason = "可以完成层识别" }
: new GuardResult { IsAllowed = false, Reason = $"当前状态 {_currentState} 不允许完成层识别" };
}
private GuardResult CanMoveToNextLayerGuard()
{
if (_currentState != RuntimeState.Running)
return new GuardResult { IsAllowed = false, Reason = $"当前状态 {_currentState} 不允许移动到下一层" };
if (_currentLayer >= _options.TotalLayers)
return new GuardResult { IsAllowed = false, Reason = "已到达最后一层" };
return new GuardResult { IsAllowed = true, Reason = "可以移动到下一层" };
}
private GuardResult CanMoveToPreviousLayerGuard()
{
if (_currentState != RuntimeState.Running)
return new GuardResult { IsAllowed = false, Reason = $"当前状态 {_currentState} 不允许移动到上一层" };
if (_currentLayer <= 1)
return new GuardResult { IsAllowed = false, Reason = "已在第一层" };
return new GuardResult { IsAllowed = true, Reason = "可以移动到上一层" };
}
private GuardResult CanPauseGuard()
{
return _currentState == RuntimeState.Running && !_isPaused && !_isStopped
? new GuardResult { IsAllowed = true, Reason = "运行状态可以暂停" }
: new GuardResult { IsAllowed = false, Reason = $"当前状态 {_currentState} 不允许暂停" };
}
private GuardResult CanResumeGuard()
{
return _currentState == RuntimeState.Paused && _isPaused && !_isStopped
? new GuardResult { IsAllowed = true, Reason = "暂停状态可以恢复" }
: new GuardResult { IsAllowed = false, Reason = $"当前状态 {_currentState} 不允许恢复" };
}
private GuardResult CanStopGuard()
{
return _currentState != RuntimeState.Stopped && _currentState != RuntimeState.Completed && _currentState != RuntimeState.ShuttingDown
? new GuardResult { IsAllowed = true, Reason = "可以停止" }
: new GuardResult { IsAllowed = false, Reason = $"当前状态 {_currentState} 不允许停止" };
}
private GuardResult CanHandleNg()
{
return (_currentState == RuntimeState.Running || _currentState == RuntimeState.LayerIdentifying) && !_isStopped
? new GuardResult { IsAllowed = true, Reason = "可以处理NG检测" }
: new GuardResult { IsAllowed = false, Reason = $"当前状态 {_currentState} 不允许处理NG" };
}
private GuardResult CanAcceptManualIntervention()
{
return (_currentState == RuntimeState.NgLocked || _currentState == RuntimeState.Faulted || _currentState == RuntimeState.Error) && !_isStopped
? new GuardResult { IsAllowed = true, Reason = "可以接受人工干预" }
: new GuardResult { IsAllowed = false, Reason = $"当前状态 {_currentState} 不允许人工干预" };
}
private GuardResult CanCompleteManualIntervention()
{
return _currentState == RuntimeState.ManualIntervening
? new GuardResult { IsAllowed = true, Reason = "可以完成人工干预" }
: new GuardResult { IsAllowed = false, Reason = $"当前状态 {_currentState} 不允许完成人工干预" };
}
private GuardResult CanHandleFault()
{
return _currentState != RuntimeState.ShuttingDown && _currentState != RuntimeState.Uninitialized
? new GuardResult { IsAllowed = true, Reason = "可以处理故障" }
: new GuardResult { IsAllowed = false, Reason = $"当前状态 {_currentState} 不允许处理故障" };
}
private GuardResult CanRecoverFromFault()
{
return _currentState == RuntimeState.Faulted
? new GuardResult { IsAllowed = true, Reason = "可以从故障状态恢复" }
: new GuardResult { IsAllowed = false, Reason = $"当前状态 {_currentState} 不允许从故障恢复" };
}
private GuardResult CanResetGuard()
{
return _currentState != RuntimeState.ShuttingDown && _currentState != RuntimeState.Uninitialized
? new GuardResult { IsAllowed = true, Reason = "可以重置" }
: new GuardResult { IsAllowed = false, Reason = $"当前状态 {_currentState} 不允许重置" };
}
private GuardResult CanShutdown()
{
return _currentState != RuntimeState.ShuttingDown && _currentState != RuntimeState.Uninitialized
? new GuardResult { IsAllowed = true, Reason = "可以关闭" }
: new GuardResult { IsAllowed = false, Reason = $"当前状态 {_currentState} 不允许关闭" };
}
#endregion
#region
/// <summary>
/// 执行人工放行操作。
/// </summary>
public async Task<Result<StateTransitionEvent>> ExecuteManualReleaseAsync(Guid sessionId, string operatorId, string? reason = null, CancellationToken cancellationToken = default)
{
try
{
_logger.LogInformation("开始执行人工放行操作会话ID={SessionId},操作员={OperatorId}", sessionId, operatorId);
// 1. 权限校验
var permissionResult = await _manualOverrideService.GetOverridePermissionAsync(sessionId, operatorId, cancellationToken);
if (!permissionResult.IsSuccess || !permissionResult.Data?.HasPermission == true)
{
return Result<StateTransitionEvent>.Fail("PERMISSION_DENIED", "人工放行权限校验失败");
}
// 2. 构建人工干预请求
var overrideRequest = new ManualOverrideRequest
{
RequestId = Guid.NewGuid(),
SessionId = sessionId,
OperatorId = operatorId,
OperatorName = operatorId,
OverrideType = OverrideType.Release,
TargetStatus = SessionStatus.Running,
RequestTimeUtc = DateTime.UtcNow
};
// 3. 条件验证
var validationResult = await _manualOverrideService.ValidateOverrideConditionsAsync(sessionId, overrideRequest, cancellationToken);
if (!validationResult.IsSuccess || !validationResult.Data?.IsValid == true)
{
return Result<StateTransitionEvent>.Fail("VALIDATION_FAILED", "人工放行条件验证失败");
}
// 4. 执行状态迁移
var transitionResult = TriggerTransition(StateTrigger.ManualInterventionCompleted, reason ?? "人工放行", new { OperatorId = operatorId });
if (!transitionResult.IsSuccess)
{
return transitionResult;
}
// 5. 执行人工干预
var overrideResult = await _manualOverrideService.ExecuteManualOverrideAsync(overrideRequest, cancellationToken);
if (!overrideResult.IsSuccess)
{
return Result<StateTransitionEvent>.Fail("OVERRIDE_FAILED", "人工放行执行失败");
}
// 6. 记录审计日志
await LogManualOverrideAuditAsync(sessionId, overrideRequest, overrideResult.Data, reason, cancellationToken);
_logger.LogInformation("人工放行操作成功完成会话ID={SessionId},操作员={OperatorId}", sessionId, operatorId);
return transitionResult;
}
catch (Exception ex)
{
var traceId = Guid.NewGuid().ToString("N");
_logger.LogError(ex, "执行人工放行操作失败。TraceId: {TraceId}", traceId);
return Result<StateTransitionEvent>.FailWithTrace("MANUAL_RELEASE_FAILED", "执行人工放行操作失败", traceId);
}
}
/// <summary>
/// 执行人工复位操作。
/// </summary>
public async Task<Result<StateTransitionEvent>> ExecuteManualResetAsync(Guid sessionId, string operatorId, string? reason = null, CancellationToken cancellationToken = default)
{
try
{
_logger.LogInformation("开始执行人工复位操作会话ID={SessionId},操作员={OperatorId}", sessionId, operatorId);
// 1. 权限校验
var permissionResult = await _manualOverrideService.GetOverridePermissionAsync(sessionId, operatorId, cancellationToken);
if (!permissionResult.IsSuccess || !permissionResult.Data?.HasPermission == true)
{
return Result<StateTransitionEvent>.Fail("PERMISSION_DENIED", "人工复位权限校验失败");
}
// 2. 构建人工干预请求
var overrideRequest = new ManualOverrideRequest
{
RequestId = Guid.NewGuid(),
SessionId = sessionId,
OperatorId = operatorId,
OperatorName = operatorId,
OverrideType = OverrideType.Reset,
TargetStatus = SessionStatus.Ready,
RequestTimeUtc = DateTime.UtcNow
};
// 3. 条件验证
var validationResult = await _manualOverrideService.ValidateOverrideConditionsAsync(sessionId, overrideRequest, cancellationToken);
if (!validationResult.IsSuccess || !validationResult.Data?.IsValid == true)
{
return Result<StateTransitionEvent>.Fail("VALIDATION_FAILED", "人工复位条件验证失败");
}
// 4. 执行状态迁移
var transitionResult = TriggerTransition(StateTrigger.Reset, reason ?? "人工复位", new { OperatorId = operatorId });
if (!transitionResult.IsSuccess)
{
return transitionResult;
}
// 5. 执行人工干预
var overrideResult = await _manualOverrideService.ExecuteManualOverrideAsync(overrideRequest, cancellationToken);
if (!overrideResult.IsSuccess)
{
return Result<StateTransitionEvent>.Fail("OVERRIDE_FAILED", "人工复位执行失败");
}
// 6. 记录审计日志
await LogManualOverrideAuditAsync(sessionId, overrideRequest, overrideResult.Data, reason, cancellationToken);
_logger.LogInformation("人工复位操作成功完成会话ID={SessionId},操作员={OperatorId}", sessionId, operatorId);
return transitionResult;
}
catch (Exception ex)
{
var traceId = Guid.NewGuid().ToString("N");
_logger.LogError(ex, "执行人工复位操作失败。TraceId: {TraceId}", traceId);
return Result<StateTransitionEvent>.FailWithTrace("MANUAL_RESET_FAILED", "执行人工复位操作失败", traceId);
}
}
/// <summary>
/// 执行人工跳层操作。
/// </summary>
public async Task<Result<StateTransitionEvent>> ExecuteManualSkipLayerAsync(Guid sessionId, string operatorId, int targetLayer, string? reason = null, CancellationToken cancellationToken = default)
{
try
{
_logger.LogInformation("开始执行人工跳层操作会话ID={SessionId},操作员={OperatorId},目标层={TargetLayer}", sessionId, operatorId, targetLayer);
// 1. 权限校验
var permissionResult = await _manualOverrideService.GetOverridePermissionAsync(sessionId, operatorId, cancellationToken);
if (!permissionResult.IsSuccess || !permissionResult.Data?.HasPermission == true)
{
return Result<StateTransitionEvent>.Fail("PERMISSION_DENIED", "人工跳层权限校验失败");
}
// 2. 构建人工干预请求
var overrideRequest = new ManualOverrideRequest
{
RequestId = Guid.NewGuid(),
SessionId = sessionId,
OperatorId = operatorId,
OperatorName = operatorId,
OverrideType = OverrideType.SkipLayer,
TargetStatus = SessionStatus.Running,
RequestTimeUtc = DateTime.UtcNow
};
// 3. 条件验证
var validationResult = await _manualOverrideService.ValidateOverrideConditionsAsync(sessionId, overrideRequest, cancellationToken);
if (!validationResult.IsSuccess || !validationResult.Data?.IsValid == true)
{
return Result<StateTransitionEvent>.Fail("VALIDATION_FAILED", "人工跳层条件验证失败");
}
// 4. 执行状态迁移(直接设置目标层)
lock (_stateLock)
{
if (targetLayer < 1 || targetLayer > _options.TotalLayers)
{
return Result<StateTransitionEvent>.Fail("INVALID_TARGET_LAYER", $"目标层 {targetLayer} 无效");
}
var previousLayer = _currentLayer;
_currentLayer = targetLayer;
var transitionEvent = new StateTransitionEvent
{
EventType = StateTransitionEventType.LayerForward,
PreviousState = _currentState,
NewState = _currentState,
PreviousLayer = previousLayer,
NewLayer = _currentLayer,
Timestamp = DateTime.UtcNow,
Reason = reason ?? $"人工跳层到第{targetLayer}层",
Trigger = StateTrigger.ManualIntervention,
GuardResult = "人工干预跳层"
};
_eventHistory.Enqueue(transitionEvent);
_logger.LogInformation("人工跳层成功:{PreviousLayer} -> {NewLayer}", previousLayer, _currentLayer);
// 5. 执行人工干预
var overrideResult = await _manualOverrideService.ExecuteManualOverrideAsync(overrideRequest, cancellationToken);
// 6. 记录审计日志
await LogManualOverrideAuditAsync(sessionId, overrideRequest, overrideResult.Data, reason, cancellationToken);
return Result<StateTransitionEvent>.Success(transitionEvent, "人工跳层成功");
}
}
catch (Exception ex)
{
var traceId = Guid.NewGuid().ToString("N");
_logger.LogError(ex, "执行人工跳层操作失败。TraceId: {TraceId}", traceId);
return Result<StateTransitionEvent>.FailWithTrace("MANUAL_SKIP_LAYER_FAILED", "执行人工跳层操作失败", traceId);
}
}
/// <summary>
/// 记录人工干预审计日志。
/// </summary>
private async Task LogManualOverrideAuditAsync(Guid sessionId, ManualOverrideRequest request, ManualOverrideResult? result, string? reason, CancellationToken cancellationToken)
{
try
{
// 这里可以通过审计服务记录日志
// 目前使用日志记录
_logger.LogInformation(
"人工干预审计记录会话ID={SessionId}请求ID={RequestId},操作员={OperatorId},类型={OverrideType},原因={Reason},结果={OverrideResult}",
sessionId, request.RequestId, request.OperatorId, request.OverrideType, reason, result?.OverrideResult);
}
catch (Exception ex)
{
_logger.LogError(ex, "记录人工干预审计日志失败");
}
}
#endregion
#region
private bool CanMoveToNextLayer()
{
return !_isStopped && !_isPaused && _currentLayer < _options.TotalLayers;
}
private bool CanMoveToPreviousLayer()
{
return !_isStopped && !_isPaused && _currentLayer > 1;
}
private bool CanPause()
{
return _currentState == RuntimeState.Running && !_isPaused && !_isStopped;
}
private bool CanResume()
{
return _currentState == RuntimeState.Paused && _isPaused && !_isStopped;
}
private bool CanReset()
{
return true; // 总是可以重置
}
private bool CanStop()
{
return _currentState != RuntimeState.Stopped && _currentState != RuntimeState.Completed;
}
#endregion
#region
private string GetCannotMoveForwardReason()
{
if (_isStopped) return "状态机已停止";
if (_isPaused) return "状态机已暂停";
if (_currentLayer >= _options.TotalLayers) return "已到达最后一层";
return "未知原因";
}
private string GetCannotMoveBackwardReason()
{
if (_isStopped) return "状态机已停止";
if (_isPaused) return "状态机已暂停";
if (_currentLayer <= 1) return "已在第一层";
return "未知原因";
}
private string GetCannotPauseReason()
{
if (_isPaused) return "状态机已暂停";
if (_isStopped) return "状态机已停止";
if (_currentState == RuntimeState.Completed) return "处理已完成";
if (_currentState != RuntimeState.Running) return "状态机不在运行状态";
return "未知原因";
}
private string GetCannotResumeReason()
{
if (!_isPaused) return "状态机未暂停";
if (_isStopped) return "状态机已停止";
return "未知原因";
}
private string GetCannotStopReason()
{
if (_isStopped) return "状态机已停止";
if (_currentState == RuntimeState.Completed) return "处理已完成";
return "未知原因";
}
#endregion
#region
private string GetStateDescription(RuntimeState state)
{
return state switch
{
RuntimeState.Uninitialized => "未初始化",
RuntimeState.Initializing => "初始化中",
RuntimeState.Idle => "空闲",
RuntimeState.Ready => "就绪",
RuntimeState.WaitingProduct => "等待产品",
RuntimeState.LayerIdentifying => "层识别中",
RuntimeState.Running => "运行中",
RuntimeState.Paused => "已暂停",
RuntimeState.Stopped => "已停止",
RuntimeState.Completed => "已完成",
RuntimeState.NgLocked => "NG锁定",
RuntimeState.ManualIntervening => "人工干预",
RuntimeState.Faulted => "故障",
RuntimeState.Error => "错误",
RuntimeState.ShuttingDown => "关闭中",
_ => "未知状态"
};
}
private string GetDetailedStateDescription(RuntimeState state)
{
return state switch
{
RuntimeState.Uninitialized => "状态机未初始化,需要执行初始化流程",
RuntimeState.Initializing => "状态机正在初始化,加载配置和资源",
RuntimeState.Idle => "状态机处于空闲状态,等待开始处理",
RuntimeState.Ready => "状态机已就绪,等待产品进入工位",
RuntimeState.WaitingProduct => "状态机正在等待产品进入检测区域",
RuntimeState.LayerIdentifying => $"状态机正在识别第 {_currentLayer} 层的部件",
RuntimeState.Running => $"状态机正在运行,当前处理第 {_currentLayer} 层",
RuntimeState.Paused => $"状态机已暂停,当前在第 {_currentLayer} 层",
RuntimeState.Stopped => "状态机已停止,需要重置才能重新开始",
RuntimeState.Completed => $"所有 {_options.TotalLayers} 层处理已完成",
RuntimeState.NgLocked => "检测到NG状态机已锁定需要人工干预",
RuntimeState.ManualIntervening => "人工正在进行干预操作",
RuntimeState.Faulted => "设备发生故障,需要检查并修复",
RuntimeState.Error => "状态机发生错误,需要检查并重置",
RuntimeState.ShuttingDown => "状态机正在关闭,清理资源中",
_ => "状态机处于未知状态"
};
}
#endregion
/// <summary>
/// 基于触发器执行状态转换。
/// </summary>
public Result<StateTransitionEvent> TriggerTransition(StateTrigger trigger, string? reason = null, object? parameters = null)
{
lock (_stateLock)
{
try
{
_logger.LogDebug("尝试触发状态转换:触发器={Trigger},当前状态={CurrentState}", trigger, _currentState);
// 检查转换是否被允许
var guardResult = EvaluateTransitionGuard(trigger, _currentState, parameters);
if (!guardResult.IsAllowed)
{
_logger.LogWarning("状态转换被守卫条件拒绝:触发器={Trigger},原因={Reason}", trigger, guardResult.Reason);
return Result<StateTransitionEvent>.Fail("TRANSITION_GUARD_REJECTED", guardResult.Reason);
}
// 获取目标状态
var targetState = GetTargetState(trigger, _currentState);
if (targetState == _currentState)
{
_logger.LogWarning("状态转换无效果:触发器={Trigger},当前状态={CurrentState}", trigger, _currentState);
return Result<StateTransitionEvent>.Fail("TRANSITION_NO_EFFECT", "状态转换无效果");
}
// 执行状态转换
return ExecuteStateTransition(trigger, targetState, reason ?? $"触发器 {trigger} 执行");
}
catch (Exception ex)
{
var traceId = Guid.NewGuid().ToString("N");
_logger.LogError(ex, "触发状态转换失败。TraceId: {TraceId}", traceId);
var result = Result.FromException(ex, "TRIGGER_TRANSITION_FAILED", "触发状态转换失败", traceId);
return Result<StateTransitionEvent>.FailWithTrace(result.Code, result.Message, result.TraceId ?? traceId, result.Errors.ToArray());
}
}
}
/// <summary>
/// 评估状态转换守卫条件。
/// </summary>
private GuardResult EvaluateTransitionGuard(StateTrigger trigger, RuntimeState currentState, object? parameters)
{
return trigger switch
{
StateTrigger.Initialize => CanInitialize(),
StateTrigger.Start => CanStart(),
StateTrigger.ProductEntered => CanAcceptProduct(),
StateTrigger.StartLayerIdentification => CanStartLayerIdentification(),
StateTrigger.LayerIdentificationCompleted => CanCompleteLayerIdentification(),
StateTrigger.MoveToNextLayer => CanMoveToNextLayerGuard(),
StateTrigger.MoveToPreviousLayer => CanMoveToPreviousLayerGuard(),
StateTrigger.Pause => CanPauseGuard(),
StateTrigger.Resume => CanResumeGuard(),
StateTrigger.Stop => CanStopGuard(),
StateTrigger.NgDetected => CanHandleNg(),
StateTrigger.ManualIntervention => CanAcceptManualIntervention(),
StateTrigger.ManualInterventionCompleted => CanCompleteManualIntervention(),
StateTrigger.Fault => CanHandleFault(),
StateTrigger.FaultRecovered => CanRecoverFromFault(),
StateTrigger.Reset => CanResetGuard(),
StateTrigger.Shutdown => CanShutdown(),
_ => new GuardResult { IsAllowed = false, Reason = $"未知的触发器: {trigger}" }
};
}
/// <summary>
/// 获取触发器的目标状态。
/// </summary>
private RuntimeState GetTargetState(StateTrigger trigger, RuntimeState currentState)
{
return trigger switch
{
StateTrigger.Initialize => RuntimeState.Initializing,
StateTrigger.Initialized => RuntimeState.Idle,
StateTrigger.Start => RuntimeState.Ready,
StateTrigger.ProductEntered => RuntimeState.LayerIdentifying,
StateTrigger.StartLayerIdentification => RuntimeState.LayerIdentifying,
StateTrigger.LayerIdentificationCompleted => RuntimeState.Running,
StateTrigger.MoveToNextLayer => RuntimeState.Running,
StateTrigger.MoveToPreviousLayer => RuntimeState.Running,
StateTrigger.Pause => RuntimeState.Paused,
StateTrigger.Resume => RuntimeState.Running,
StateTrigger.Stop => RuntimeState.Stopped,
StateTrigger.Complete => RuntimeState.Completed,
StateTrigger.NgDetected => RuntimeState.NgLocked,
StateTrigger.ManualIntervention => RuntimeState.ManualIntervening,
StateTrigger.ManualInterventionCompleted => RuntimeState.Running,
StateTrigger.Fault => RuntimeState.Faulted,
StateTrigger.FaultRecovered => RuntimeState.Running,
StateTrigger.Error => RuntimeState.Error,
StateTrigger.Reset => RuntimeState.Idle,
StateTrigger.Shutdown => RuntimeState.ShuttingDown,
_ => currentState
};
}
/// <summary>
/// 执行状态转换。
/// </summary>
private Result<StateTransitionEvent> ExecuteStateTransition(StateTrigger trigger, RuntimeState targetState, string reason)
{
var previousState = _currentState;
var previousLayer = _currentLayer;
// 更新状态
_currentState = targetState;
_lastTransitionTime = DateTime.UtcNow;
// 特殊处理某些转换
if (trigger == StateTrigger.MoveToNextLayer)
{
_currentLayer++;
}
else if (trigger == StateTrigger.MoveToPreviousLayer)
{
_currentLayer--;
}
else if (trigger == StateTrigger.Reset)
{
_currentLayer = 1;
_isPaused = false;
_isStopped = false;
}
// 创建转换事件
var transitionEvent = new StateTransitionEvent
{
EventType = GetEventTypeFromTrigger(trigger),
PreviousState = previousState,
NewState = targetState,
PreviousLayer = previousLayer,
NewLayer = _currentLayer,
Timestamp = _lastTransitionTime,
Reason = reason,
Trigger = trigger,
GuardResult = "守卫条件通过"
};
_eventHistory.Enqueue(transitionEvent);
_logger.LogInformation("状态转换成功:{PreviousState} -> {NewState},触发器={Trigger},原因={Reason}",
previousState, targetState, trigger, reason);
return Result<StateTransitionEvent>.Success(transitionEvent, "状态转换成功");
}
/// <summary>
/// 从触发器获取事件类型。
/// </summary>
private StateTransitionEventType GetEventTypeFromTrigger(StateTrigger trigger)
{
return trigger switch
{
StateTrigger.MoveToNextLayer => StateTransitionEventType.LayerForward,
StateTrigger.MoveToPreviousLayer => StateTransitionEventType.LayerBackward,
StateTrigger.Pause => StateTransitionEventType.Pause,
StateTrigger.Resume => StateTransitionEventType.Resume,
StateTrigger.Stop => StateTransitionEventType.Stop,
StateTrigger.Reset => StateTransitionEventType.Reset,
StateTrigger.Complete => StateTransitionEventType.Complete,
StateTrigger.NgDetected => StateTransitionEventType.NgLocked,
StateTrigger.ManualIntervention => StateTransitionEventType.ManualIntervention,
StateTrigger.Fault => StateTransitionEventType.Fault,
StateTrigger.Shutdown => StateTransitionEventType.Shutdown,
_ => StateTransitionEventType.Error
};
}
/// <summary>
/// 释放资源。
/// </summary>
public void Dispose()
{
try
{
_eventHistory.Clear();
_logger.LogInformation("运行状态机服务已释放");
}
catch (Exception ex)
{
_logger.LogError(ex, "释放运行状态机服务资源时发生错误");
}
}
}
#region
/// <summary>
/// 守卫条件结果。
/// </summary>
internal sealed class GuardResult
{
public bool IsAllowed { get; init; }
public string Reason { get; init; } = string.Empty;
}
/// <summary>
/// 状态转换触发器。
/// </summary>
public enum StateTrigger
{
/// <summary>
/// 初始化触发器。
/// </summary>
Initialize,
/// <summary>
/// 初始化完成触发器。
/// </summary>
Initialized,
/// <summary>
/// 启动触发器。
/// </summary>
Start,
/// <summary>
/// 产品进入触发器。
/// </summary>
ProductEntered,
/// <summary>
/// 开始层识别触发器。
/// </summary>
StartLayerIdentification,
/// <summary>
/// 层识别完成触发器。
/// </summary>
LayerIdentificationCompleted,
/// <summary>
/// 移动到下一层触发器。
/// </summary>
MoveToNextLayer,
/// <summary>
/// 移动到上一层触发器。
/// </summary>
MoveToPreviousLayer,
/// <summary>
/// 暂停触发器。
/// </summary>
Pause,
/// <summary>
/// 恢复触发器。
/// </summary>
Resume,
/// <summary>
/// 停止触发器。
/// </summary>
Stop,
/// <summary>
/// 完成触发器。
/// </summary>
Complete,
/// <summary>
/// NG检测触发器。
/// </summary>
NgDetected,
/// <summary>
/// 人工干预触发器。
/// </summary>
ManualIntervention,
/// <summary>
/// 人工干预完成触发器。
/// </summary>
ManualInterventionCompleted,
/// <summary>
/// 故障触发器。
/// </summary>
Fault,
/// <summary>
/// 故障恢复触发器。
/// </summary>
FaultRecovered,
/// <summary>
/// 错误触发器。
/// </summary>
Error,
/// <summary>
/// 重置触发器。
/// </summary>
Reset,
/// <summary>
/// 关闭触发器。
/// </summary>
Shutdown
}
/// <summary>
/// 状态转换事件。
/// </summary>
public sealed class StateTransitionEvent
{
public StateTransitionEventType EventType { get; init; }
public RuntimeState PreviousState { get; init; }
public RuntimeState NewState { get; init; }
public int PreviousLayer { get; init; }
public int NewLayer { get; init; }
public DateTime Timestamp { get; init; }
public string Reason { get; init; } = string.Empty;
public StateTrigger Trigger { get; init; }
public string? GuardResult { get; init; }
}
/// <summary>
/// 状态转换事件类型。
/// </summary>
public enum StateTransitionEventType
{
LayerForward,
LayerBackward,
Pause,
Resume,
Stop,
Reset,
Complete,
Error,
NgLocked,
ManualIntervention,
Fault,
Shutdown
}
#endregion
/// <summary>
/// 运行状态枚举。
/// </summary>
public enum RuntimeState
{
/// <summary>
/// 未初始化状态。
/// </summary>
Uninitialized,
/// <summary>
/// 初始化中状态。
/// </summary>
Initializing,
/// <summary>
/// 空闲状态。
/// </summary>
Idle,
/// <summary>
/// 就绪状态,等待产品。
/// </summary>
Ready,
/// <summary>
/// 等待产品状态。
/// </summary>
WaitingProduct,
/// <summary>
/// 层识别中状态。
/// </summary>
LayerIdentifying,
/// <summary>
/// 运行中状态。
/// </summary>
Running,
/// <summary>
/// 已暂停状态。
/// </summary>
Paused,
/// <summary>
/// 已停止状态。
/// </summary>
Stopped,
/// <summary>
/// 已完成状态。
/// </summary>
Completed,
/// <summary>
/// NG锁定状态。
/// </summary>
NgLocked,
/// <summary>
/// 人工干预状态。
/// </summary>
ManualIntervening,
/// <summary>
/// 故障状态。
/// </summary>
Faulted,
/// <summary>
/// 错误状态。
/// </summary>
Error,
/// <summary>
/// 关闭中状态。
/// </summary>
ShuttingDown
}