using System.Collections.Generic; using System.Linq; using System.Text; using Aitex.Core.RT.Event; using Aitex.Core.Util; using TypeDefLimitList = System.Collections.Generic.List; 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 cultureTip) : base(module, doItem, value, tip, cultureTip) { } #endregion #region Methods /// /// 扫描当前动作的条件,并设置相关DO的输出状态。 /// 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.PostWarningLog( _module, info.ToString().TrimEnd('\r', '\n')); _rTrigSetDoFailed.CLK = false; } else if(_rTrigSetDoFailed.Q) { // 第一次Set DO错误时打印日志 EV.PostWarningLog(_module, $"Interlock Daemon set {_do.Name} failed, {reason}"); } } #endregion }