432 lines
13 KiB
C#
432 lines
13 KiB
C#
#if false
|
||
using Microsoft.AspNetCore.Authorization;
|
||
using Microsoft.AspNetCore.Mvc;
|
||
using OrpaonVision.Core.Common;
|
||
using OrpaonVision.Core.RuleEngine;
|
||
using OrpaonVision.Core.AlarmSystem;
|
||
using OrpaonVision.Core.ManualOverride;
|
||
using OrpaonVision.SiteApp.Runtime.Services;
|
||
|
||
namespace OrpaonVision.SiteApp.Runtime.Controllers;
|
||
|
||
/// <summary>
|
||
/// 运行时API控制器,提供Agent-2负责的所有服务接口。
|
||
/// </summary>
|
||
[ApiController]
|
||
[Route("api/[controller]")]
|
||
[Authorize]
|
||
public sealed class RuntimeController : ControllerBase
|
||
{
|
||
private readonly IRuleEngineService _ruleEngineService;
|
||
private readonly IRuntimeStateMachineService _stateMachineService;
|
||
private readonly IManualOverrideService _manualOverrideService;
|
||
private readonly IAlarmSystemService _alarmSystemService;
|
||
private readonly ILogger<RuntimeController> _logger;
|
||
|
||
public RuntimeController(
|
||
IRuleEngineService ruleEngineService,
|
||
IRuntimeStateMachineService stateMachineService,
|
||
IManualOverrideService manualOverrideService,
|
||
IAlarmSystemService alarmSystemService,
|
||
ILogger<RuntimeController> logger)
|
||
{
|
||
_ruleEngineService = ruleEngineService;
|
||
_stateMachineService = stateMachineService;
|
||
_manualOverrideService = manualOverrideService;
|
||
_alarmSystemService = alarmSystemService;
|
||
_logger = logger;
|
||
}
|
||
|
||
#region 规则引擎接口
|
||
|
||
/// <summary>
|
||
/// 获取所有规则。
|
||
/// </summary>
|
||
[HttpGet("rules")]
|
||
public async Task<ActionResult<IReadOnlyList<Rule>>> GetRules(CancellationToken cancellationToken = default)
|
||
{
|
||
var result = await _ruleEngineService.GetRulesAsync(cancellationToken);
|
||
|
||
if (!result.IsSuccess)
|
||
{
|
||
return StatusCode(500, new { error = result.Message, traceId = result.TraceId });
|
||
}
|
||
|
||
return Ok(result.Data);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 评估规则。
|
||
/// </summary>
|
||
[HttpPost("rules/evaluate")]
|
||
public async Task<ActionResult<RuleEvaluationResult>> EvaluateRules([FromBody] RuleEvaluationRequest request, CancellationToken cancellationToken = default)
|
||
{
|
||
if (!ModelState.IsValid)
|
||
{
|
||
return BadRequest(ModelState);
|
||
}
|
||
|
||
var result = await _ruleEngineService.EvaluateRulesAsync(request, cancellationToken);
|
||
|
||
if (!result.IsSuccess)
|
||
{
|
||
return StatusCode(500, new { error = result.Message, traceId = result.TraceId });
|
||
}
|
||
|
||
return Ok(result.Data);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取规则详情。
|
||
/// </summary>
|
||
[HttpGet("rules/{ruleId}")]
|
||
public async Task<ActionResult<Rule>> GetRule(string ruleId, CancellationToken cancellationToken = default)
|
||
{
|
||
if (!Guid.TryParse(ruleId, out var guid))
|
||
{
|
||
return BadRequest("无效的规则ID格式");
|
||
}
|
||
|
||
var result = await _ruleEngineService.GetRuleAsync(guid, cancellationToken);
|
||
|
||
if (!result.IsSuccess)
|
||
{
|
||
return NotFound(new { error = result.Message, traceId = result.TraceId });
|
||
}
|
||
|
||
return Ok(result.Data);
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region 状态机接口
|
||
|
||
/// <summary>
|
||
/// 获取当前状态。
|
||
/// </summary>
|
||
[HttpGet("state/current")]
|
||
public ActionResult<object> GetCurrentState()
|
||
{
|
||
var state = _stateMachineService.GetCurrentState();
|
||
var layer = _stateMachineService.GetCurrentLayer();
|
||
|
||
return Ok(new { state = state.ToString(), layer });
|
||
}
|
||
|
||
/// <summary>
|
||
/// 触发状态转换。
|
||
/// </summary>
|
||
[HttpPost("state/trigger")]
|
||
public async Task<ActionResult<StateTransitionEvent>> TriggerStateTransition([FromBody] StateTransitionRequest request, CancellationToken cancellationToken = default)
|
||
{
|
||
if (!ModelState.IsValid)
|
||
{
|
||
return BadRequest(ModelState);
|
||
}
|
||
|
||
var result = await _stateMachineService.TriggerTransitionAsync(request.Trigger, request.Reason, cancellationToken);
|
||
|
||
if (!result.IsSuccess)
|
||
{
|
||
return StatusCode(500, new { error = result.Message, traceId = result.TraceId });
|
||
}
|
||
|
||
return Ok(result.Data);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取状态转换历史。
|
||
/// </summary>
|
||
[HttpGet("state/history")]
|
||
public async Task<ActionResult<IReadOnlyList<StateTransitionEvent>>> GetStateHistory([FromQuery] int maxCount = 100, CancellationToken cancellationToken = default)
|
||
{
|
||
var result = await _stateMachineService.GetEventHistoryAsync(maxCount, cancellationToken);
|
||
|
||
if (!result.IsSuccess)
|
||
{
|
||
return StatusCode(500, new { error = result.Message, traceId = result.TraceId });
|
||
}
|
||
|
||
return Ok(result.Data);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 检查是否可以执行操作。
|
||
/// </summary>
|
||
[HttpGet("state/can-execute/{trigger}")]
|
||
public ActionResult<bool> CanExecuteOperation(string trigger)
|
||
{
|
||
if (!Enum.TryParse<StateTrigger>(trigger, true, out var triggerEnum))
|
||
{
|
||
return BadRequest("无效的触发器");
|
||
}
|
||
|
||
var canExecute = _stateMachineService.CanExecuteOperation(triggerEnum);
|
||
return Ok(canExecute);
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region 人工干预接口
|
||
|
||
/// <summary>
|
||
/// 获取可干预的会话。
|
||
/// </summary>
|
||
[HttpGet("override/sessions")]
|
||
public async Task<ActionResult<IReadOnlyList<OverrideableSession>>> GetOverrideableSessions(
|
||
[FromQuery] DateTime startTime,
|
||
[FromQuery] DateTime endTime,
|
||
[FromQuery] string? productTypeCode = null,
|
||
[FromQuery] OverrideStatus? overrideStatus = null,
|
||
CancellationToken cancellationToken = default)
|
||
{
|
||
var result = await _manualOverrideService.GetOverrideableSessionsAsync(startTime, endTime, productTypeCode, overrideStatus, cancellationToken);
|
||
|
||
if (!result.IsSuccess)
|
||
{
|
||
return StatusCode(500, new { error = result.Message, traceId = result.TraceId });
|
||
}
|
||
|
||
return Ok(result.Data);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取干预权限。
|
||
/// </summary>
|
||
[HttpGet("override/permission/{sessionId}")]
|
||
public async Task<ActionResult<OverridePermission>> GetOverridePermission(string sessionId, [FromQuery] string operatorId, CancellationToken cancellationToken = default)
|
||
{
|
||
if (!Guid.TryParse(sessionId, out var sessionGuid))
|
||
{
|
||
return BadRequest("无效的会话ID格式");
|
||
}
|
||
|
||
var result = await _manualOverrideService.GetOverridePermissionAsync(sessionGuid, operatorId, cancellationToken);
|
||
|
||
if (!result.IsSuccess)
|
||
{
|
||
return StatusCode(500, new { error = result.Message, traceId = result.TraceId });
|
||
}
|
||
|
||
return Ok(result.Data);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 执行人工干预。
|
||
/// </summary>
|
||
[HttpPost("override/execute")]
|
||
[Authorize(Policy = "Operator")]
|
||
public async Task<ActionResult<ManualOverrideResult>> ExecuteManualOverride([FromBody] ManualOverrideRequest request, CancellationToken cancellationToken = default)
|
||
{
|
||
if (!ModelState.IsValid)
|
||
{
|
||
return BadRequest(ModelState);
|
||
}
|
||
|
||
var result = await _manualOverrideService.ExecuteManualOverrideAsync(request, cancellationToken);
|
||
|
||
if (!result.IsSuccess)
|
||
{
|
||
return StatusCode(500, new { error = result.Message, traceId = result.TraceId });
|
||
}
|
||
|
||
return Ok(result.Data);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取干预历史。
|
||
/// </summary>
|
||
[HttpGet("override/history")]
|
||
public async Task<ActionResult<IReadOnlyList<ManualOverrideHistory>>> GetOverrideHistory(
|
||
[FromQuery] DateTime startTime,
|
||
[FromQuery] DateTime endTime,
|
||
[FromQuery] string? operatorId = null,
|
||
[FromQuery] OverrideType? overrideType = null,
|
||
CancellationToken cancellationToken = default)
|
||
{
|
||
var result = await _manualOverrideService.GetOverrideHistoryAsync(startTime, endTime, operatorId, overrideType, cancellationToken);
|
||
|
||
if (!result.IsSuccess)
|
||
{
|
||
return StatusCode(500, new { error = result.Message, traceId = result.TraceId });
|
||
}
|
||
|
||
return Ok(result.Data);
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region 报警系统接口
|
||
|
||
/// <summary>
|
||
/// 触发报警。
|
||
/// </summary>
|
||
[HttpPost("alarms/trigger")]
|
||
public async Task<ActionResult<AlarmResult>> TriggerAlarm([FromBody] AlarmRequest request, CancellationToken cancellationToken = default)
|
||
{
|
||
if (!ModelState.IsValid)
|
||
{
|
||
return BadRequest(ModelState);
|
||
}
|
||
|
||
var result = await _alarmSystemService.TriggerAlarmAsync(request, cancellationToken);
|
||
|
||
if (!result.IsSuccess)
|
||
{
|
||
return StatusCode(500, new { error = result.Message, traceId = result.TraceId });
|
||
}
|
||
|
||
return Ok(result.Data);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 确认报警。
|
||
/// </summary>
|
||
[HttpPost("alarms/{alarmId}/confirm")]
|
||
[Authorize(Policy = "Operator")]
|
||
public async Task<ActionResult<AlarmConfirmResult>> ConfirmAlarm(string alarmId, [FromBody] AlarmConfirmRequest request, CancellationToken cancellationToken = default)
|
||
{
|
||
if (!Guid.TryParse(alarmId, out var alarmGuid))
|
||
{
|
||
return BadRequest("无效的报警ID格式");
|
||
}
|
||
|
||
request.AlarmId = alarmGuid;
|
||
|
||
var result = await _alarmSystemService.ConfirmAlarmAsync(request, cancellationToken);
|
||
|
||
if (!result.IsSuccess)
|
||
{
|
||
return StatusCode(500, new { error = result.Message, traceId = result.TraceId });
|
||
}
|
||
|
||
return Ok(result.Data);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 清除报警。
|
||
/// </summary>
|
||
[HttpPost("alarms/{alarmId}/clear")]
|
||
[Authorize(Policy = "Operator")]
|
||
public async Task<ActionResult<AlarmClearResult>> ClearAlarm(string alarmId, [FromBody] AlarmClearRequest request, CancellationToken cancellationToken = default)
|
||
{
|
||
if (!Guid.TryParse(alarmId, out var alarmGuid))
|
||
{
|
||
return BadRequest("无效的报警ID格式");
|
||
}
|
||
|
||
request.AlarmId = alarmGuid;
|
||
|
||
var result = await _alarmSystemService.ClearAlarmAsync(request, cancellationToken);
|
||
|
||
if (!result.IsSuccess)
|
||
{
|
||
return StatusCode(500, new { error = result.Message, traceId = result.TraceId });
|
||
}
|
||
|
||
return Ok(result.Data);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取活跃报警。
|
||
/// </summary>
|
||
[HttpGet("alarms/active")]
|
||
public async Task<ActionResult<IReadOnlyList<Alarm>>> GetActiveAlarms(CancellationToken cancellationToken = default)
|
||
{
|
||
var result = await _alarmSystemService.GetActiveAlarmsAsync(cancellationToken);
|
||
|
||
if (!result.IsSuccess)
|
||
{
|
||
return StatusCode(500, new { error = result.Message, traceId = result.TraceId });
|
||
}
|
||
|
||
return Ok(result.Data);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取报警栈。
|
||
/// </summary>
|
||
[HttpGet("alarms/stack/{stackType}")]
|
||
public async Task<ActionResult<IReadOnlyList<Alarm>>> GetAlarmStack(string stackType, CancellationToken cancellationToken = default)
|
||
{
|
||
if (!Enum.TryParse<AlarmStackType>(stackType, true, out var stackTypeEnum))
|
||
{
|
||
return BadRequest("无效的报警栈类型");
|
||
}
|
||
|
||
var result = await _alarmSystemService.GetAlarmStackAsync(stackTypeEnum, cancellationToken);
|
||
|
||
if (!result.IsSuccess)
|
||
{
|
||
return StatusCode(500, new { error = result.Message, traceId = result.TraceId });
|
||
}
|
||
|
||
return Ok(result.Data);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取报警生命周期。
|
||
/// </summary>
|
||
[HttpGet("alarms/{alarmId}/lifecycle")]
|
||
public async Task<ActionResult<AlarmLifecycle>> GetAlarmLifecycle(string alarmId, CancellationToken cancellationToken = default)
|
||
{
|
||
if (!Guid.TryParse(alarmId, out var alarmGuid))
|
||
{
|
||
return BadRequest("无效的报警ID格式");
|
||
}
|
||
|
||
var result = await _alarmSystemService.GetAlarmLifecycleAsync(alarmGuid, cancellationToken);
|
||
|
||
if (!result.IsSuccess)
|
||
{
|
||
return StatusCode(500, new { error = result.Message, traceId = result.TraceId });
|
||
}
|
||
|
||
return Ok(result.Data);
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region 系统状态接口
|
||
|
||
/// <summary>
|
||
/// 获取系统整体状态。
|
||
/// </summary>
|
||
[HttpGet("status")]
|
||
public ActionResult<object> GetSystemStatus()
|
||
{
|
||
var currentState = _stateMachineService.GetCurrentState();
|
||
var currentLayer = _stateMachineService.GetCurrentLayer();
|
||
|
||
return Ok(new
|
||
{
|
||
timestamp = DateTime.UtcNow,
|
||
state_machine = new
|
||
{
|
||
current_state = currentState.ToString(),
|
||
current_layer = currentLayer
|
||
},
|
||
services = new
|
||
{
|
||
rule_engine = "healthy",
|
||
state_machine = "healthy",
|
||
manual_override = "healthy",
|
||
alarm_system = "healthy"
|
||
}
|
||
});
|
||
}
|
||
|
||
#endregion
|
||
}
|
||
|
||
/// <summary>
|
||
/// 状态转换请求模型。
|
||
/// </summary>
|
||
public sealed class StateTransitionRequest
|
||
{
|
||
public StateTrigger Trigger { get; set; }
|
||
public string Reason { get; set; } = string.Empty;
|
||
}
|
||
|
||
#endif
|