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

216 lines
7.1 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 System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using Aitex.Core.RT.Event;
using Aitex.Core.RT.IOCore.Interlock.Actions;
using Aitex.Core.RT.SCCore;
using MECF.Framework.Common.Equipment;
namespace Aitex.Core.RT.IOCore.Interlock
{
/// <summary>
/// 互锁管理器。
/// <remarks>
/// 互锁管理器作为独立工作的设备,被系统的后台循环调度。
/// <br/>
/// 当监测到某个InterlockLimit被触发时和该Limit相关的所有Action中定义的DO均被
/// 置为Action节点Value属性中定义电平的反向电平。
/// </remarks>
/// </summary>
public class InterlockManager : InterlockManagerBase<InterlockAction>
{
#region Variables
/// <summary>
/// 以Module为单位当设置该Module所属的DO并触发互锁时是否输出Info而不是Warning。
/// </summary>
private Dictionary<ModuleName, bool> _dicModulePostInfo;
#endregion
#region Constructors
/// <summary>
/// 互锁管理器的构造函数。
/// </summary>
public InterlockManager()
{
RootNodeName = "Interlock";
_dicModulePostInfo = new();
}
#endregion
#region Methods
/// <summary>
/// 初始化互锁管理器。
/// </summary>
/// <param name="configFie">互锁配置文件。</param>
/// <param name="doMap">DO点表。</param>
/// <param name="diMap">DI点表。</param>
/// <param name="aoMap">AO点表。</param>
/// <param name="aiMap">AI点表。</param>
/// <param name="reason">初始化失败原因。</param>
/// <returns></returns>
public override bool Initialize(string configFie,
Dictionary<string, DOAccessor> doMap,
Dictionary<string, DIAccessor> diMap,
Dictionary<string, AIAccessor> aiMap,
Dictionary<string, AOAccessor> aoMap,
out string reason)
{
reason = "";
var succeeded = base.Initialize(configFie, doMap, diMap, aiMap, aoMap, out reason);
if (!succeeded)
return false;
_dicModulePostInfo = _dictINTLKActionsPerModule.Keys.ToDictionary(x => x, x => false);
return true;
}
/// <summary>
/// 背景扫描线程执行的任务。
/// </summary>
public override void Monitor()
{
// 按Module扫描Interlock Limit
foreach (var moduleName in _dictINTLKActionsPerModule.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 _dictLIMTPerModule[moduleName].ToList())
{
// 如果互锁没被触发
if (!limit.IsTriggered())
continue;
var reverseInfo = new StringBuilder();
var module = "System";
if (!_dictLIMT2INTLKActionMap.ContainsKey(limit))//新增判断集合中是否包含,防止异常报错
continue;
var actions = _dictLIMT2INTLKActionMap[limit].ToList();
foreach (var action in actions)
{
// 尝试根据Action定义复位该互锁限制条件对应的所有DO的电平
if (((InterlockAction)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.Description} 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'));
}
}
}
}
/// <summary>
/// 设置指定Module的Interlock打印信息等级。
/// </summary>
/// <param name="module">模组名称</param>
/// <param name="isPostInfo">是否以Info等级打印信息</param>
public void SetEventLevel(string module, bool isPostInfo)
{
var moduleName = ModuleHelper.Converter(module);
if (_dicModulePostInfo.ContainsKey(moduleName))
_dicModulePostInfo[moduleName] = isPostInfo;
}
/// <summary>
/// 对指定的DO的操作是否满足互锁条件。
/// </summary>
/// <param name="doName">待操作的DO名称。</param>
/// <param name="onOff">
/// 指定的输出。
/// <value>True输出有效电平</value>
/// <br/>
/// <value>False清除有效电平输出</value>
/// </param>
/// <param name="reason">
/// 如果触发互锁限制,输出互锁限制的原因。
/// </param>
/// <returns></returns>
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;
if (_dictINTLKActionsFileLoader.TryGetValue((doName, onOff), out var ilAction))
ilAction.CanDo(out reason);
/*
foreach (var action in _lstActions.Where(action => action.IsSame(doName, onOff)))
{
return action.CanDo(out reason);
}
*/
return true;
}
/// <summary>
/// 获取系统配置中指定Module的ByPassInterlock参数设置值。
/// </summary>
/// <param name="module">
/// 模组名称, <see cref="ModuleName"/>
/// </param>
/// <returns></returns>
public static bool GetScBypassInterlockValue(ModuleName module)
{
return GetScBypassInterlockValue(module.ToString());
}
/// <summary>
/// 获取系统配置中指定Module的ByPassInterlock参数设置值。
/// </summary>
/// <param name="module">模组名称</param>
/// <returns></returns>
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
}
}