Sic.Framework-Nanjing-Baishi/MECF.Framework.Common/Aitex/Core/RT/IOCore/Interlock/Actions/InterlockDaemonAction.cs

82 lines
2.1 KiB
C#
Raw Normal View History

using System.Collections.Generic;
using System.Linq;
using System.Text;
using Aitex.Core.RT.Event;
using Aitex.Core.RT.Log;
using Aitex.Core.Util;
using TypeDefLimitList = System.Collections.Generic.List<Aitex.Core.RT.IOCore.IInterlockLimit>;
namespace Aitex.Core.RT.IOCore.Interlock.Actions;
public class InterlockDaemonAction : InterlockActionBase
{
#region Variables
private readonly R_TRIG _rTrigSetDoFailed = new();
#endregion
#region Constructors
public InterlockDaemonAction(string module, DOAccessor doItem, bool value, string tip, Dictionary<string, string> cultureTip)
: base(module, doItem, value, tip, cultureTip)
{
}
#endregion
#region Methods
/// <summary>
/// 扫描当前动作的条件并设置相关DO的输出状态。
/// </summary>
public override void Monitor()
{
var info = new StringBuilder();
// 检查所有的Limit是否满足要求
foreach (var limit in Limits)
{
if (!limit.CanDo(out _))
return;
info.AppendLine($"{limit.DaemonReason}");
}
// 扫描OR定义的Limit组每个组中只要有一个Limit命中则继续测试下个OR组否则直接退出。
foreach (var group in LogicOrGroups)
{
var hitLimit = group.FirstOrDefault(limit => limit.CanDo(out _));
if (hitLimit == null) // 当前OR组中没用命中的Limit退出Monitor
return;
info.AppendLine($"{hitLimit.DaemonReason}");
}
// 如果DO输出已经满足要求则直接退出
if (_do.Value == _actionValue)
return;
// 所有的Limit和OR逻辑组均命中
var succeeded = _do.SetValue(_actionValue, out var reason);
_rTrigSetDoFailed.CLK = !succeeded;
if (succeeded)
{
info.Insert(0,
$"Interlock Daemon Force set DO-{_do.IoTableIndex}({_do.Name}) = [{((_actionValue) ? "ON" : "OFF")}] Due to\r\n");
EV.PostInfoLog( _module, info.ToString().TrimEnd('\r', '\n'));
_rTrigSetDoFailed.CLK = false;
}
else if(_rTrigSetDoFailed.Q)
{
// 第一次Set DO错误时打印日志
LOG.Error($"Interlock Daemon set {_do.Name} failed, {reason}");
}
}
#endregion
}