using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Text; using Aitex.Core.RT.Event; using Aitex.Core.RT.IOCore.Interlock.Base; using Aitex.Core.RT.SCCore; using MECF.Framework.Common.Equipment; namespace Aitex.Core.RT.IOCore { /// /// 互锁管理器。 /// /// 互锁管理器作为独立工作的设备,被系统的后台循环调度。 ///
/// 当监测到某个InterlockLimit被触发时,和该Limit相关的所有Action中定义的DO均被 /// 置为Action节点Value属性中定义电平的反向电平。 ///
///
public class InterlockManager : InterlockManagerBase { #region Variables /// /// 以Module为单位,当设置该Module所属的DO并触发互锁时,是否输出Info而不是Warning。 /// private Dictionary _dicModulePostInfo; /// /// 每个Module对应的Limit集合。 /// private readonly Dictionary> _dicLimitsPerModule; /// /// 每个Limit对应的DoAction集合。 /// private readonly Dictionary> _dicLimitToActionMap; #endregion #region Constructors /// /// 互锁管理器的构造函数。 /// public InterlockManager() { RootNodeName = "Interlock"; _dicLimitToActionMap = new (); _dicLimitsPerModule = new (); _dicModulePostInfo = new(); } #endregion #region Methods /// /// 初始化互锁管理器。 /// /// 互锁配置文件。 /// DO点表。 /// DI点表。 /// AO点表。 /// AI点表。 /// 初始化失败原因。 /// public override bool Initialize(string configFie, Dictionary doMap, Dictionary diMap, Dictionary aiMap, Dictionary aoMap, out string reason) { reason = ""; var succ = base.Initialize(configFie, doMap, diMap, aiMap, aoMap, out reason); if (!succ) return false; try { foreach (var action in _lstActions) { // 创建InterlockLimit到被使用的InterlockAction映射字典 foreach (var limit in action.Limits) { // 检查InterlockLimit是否已经存在于字典中 var exists = _dicLimitToActionMap.ContainsKey(limit); Debug.Assert(exists, "The limit object is not in the mapping dictionary"); // 当前Limit是否反向绑定了其所影响的所有DoAction _dicLimitToActionMap[limit].Add(action); } } _dicModulePostInfo = _dicLimitsPerModule.Keys.ToDictionary(x => x, x=>false); Debug.Assert(!_dicActionsPerModule.ContainsKey(ModuleName.UnDefined), $"InterlockManager {nameof(_dicActionsPerModule)} contains key {ModuleName.UnDefined}"); Debug.Assert(!_dicLimitsPerModule.ContainsKey(ModuleName.UnDefined), $"InterlockManager {nameof(_dicLimitsPerModule)} contains key {ModuleName.UnDefined}"); } catch (Exception ex) { reason = ex.Message; } if (reason.Length <= 0) return true; reason = reason.TrimEnd('\n', '\r'); return false; } /// /// 背景扫描线程执行的任务。 /// public override void Monitor() { // 按Module扫描Interlock Limit foreach (var moduleName in _dicLimitsPerModule.Keys.ToList()) { Debug.Assert(moduleName != ModuleName.UnDefined, $"Interlock Manager CanSetDo() undesired module name {ModuleName.UnDefined}"); // 检查当前Module是否旁路Interlock var isBypassInterlock = GetScBypassInterlockValue(moduleName); if (isBypassInterlock) continue; foreach (var limit in _dicLimitsPerModule[moduleName].ToList()) { // 如果互锁没被触发 if (!limit.IsTriggered()) continue; var reverseInfo = new StringBuilder(); var module = "System"; var actions = _dicLimitToActionMap[limit].ToList(); foreach (var action in actions) { // 尝试根据Action定义复位该互锁限制条件对应的所有DO的电平 if (action.TryReverse(out var reason)) { var ss = action.ActionName.Split('.'); if (ss.Length > 1 && ModuleHelper.IsPm(ss[0])) module = ss[0]; reverseInfo.AppendLine(reason); } } // 如果PM腔有被恢复的DO,则打印信息并报警。 if (reverseInfo.Length > 0) { reverseInfo.Insert(0, $"Due to the {limit.Tip}, {limit.Name} is not [{limit.GetLimitValue()}]\r\n"); // Post事件的类型, Info还是Warning _dicModulePostInfo.TryGetValue(moduleName, out var isPostInfo); if (isPostInfo) EV.PostInfoLog(module, reverseInfo.ToString().TrimEnd('\r', '\n')); else EV.PostWarningLog(module, reverseInfo.ToString().TrimEnd('\r', '\n')); } } } } /// /// 设置指定Module的Interlock打印信息等级。 /// /// 模组名称 /// 是否以Info等级打印信息 public void SetEventLevel(string module, bool isInfo) { var moduleName = ModuleHelper.Converter(module); if (_dicModulePostInfo.ContainsKey(moduleName)) _dicModulePostInfo[moduleName] = isInfo; } /// /// 对指定的DO的操作是否满足互锁条件。 /// /// 待操作的DO名称。 /// /// 指定的输出。 /// True:输出有效电平 ///
/// False:清除有效电平输出 /// /// /// 如果触发互锁限制,输出互锁限制的原因。 /// /// public bool CanSetDo(string doName, bool onOff, out string reason) { reason = string.Empty; var moduleName = GetModuleFromIo(doName); Debug.Assert(moduleName != ModuleName.UnDefined, $"Interlock Manager CanSetDo() undesired module name {ModuleName.UnDefined}"); var isBypassInterlock = GetScBypassInterlockValue(moduleName); if (isBypassInterlock) return true; foreach (var action in _lstActions.Where(action => action.IsSame(doName, onOff))) { return action.CanDo(out reason); } return true; } /// /// 获取系统配置中指定Module的ByPassInterlock参数设置值。 /// /// /// 模组名称, /// /// public static bool GetScBypassInterlockValue(ModuleName module) { return GetScBypassInterlockValue(module.ToString()); } /// /// 获取系统配置中指定Module的ByPassInterlock参数设置值。 /// /// 模组名称 /// public static bool GetScBypassInterlockValue(string module) { if (ModuleHelper.IsPm(module)) return SC.SafeGetValue($"PM.{module}.BypassInterlock", false); else return SC.SafeGetValue($"{module}.BypassInterlock", false); } #endregion } }