Sic.Framework-Nanjing-Baishi/MECF.Framework.Common/Aitex/Core/RT/Device/ErrorDetectableBaseDevice.cs

208 lines
6.5 KiB
C#
Raw Normal View History

using System;
using System.Xml;
using Aitex.Core.RT.Device;
using Aitex.Core.RT.Event;
using Aitex.Core.RT.IOCore;
using Aitex.Core.RT.SCCore;
using Aitex.Core.RT.Tolerance;
using Aitex.Core.Util;
using MECF.Framework.Common.Event;
namespace MECF.Framework.Common.Aitex.Core.RT.Device
{
/// <summary>
/// 具有SetPoint、FeedBack误差实时检测功能的设备基类。
/// <para>注意在子类中注册FeedbackGetter、SetPointGetter、RampTimerGetter</para>
/// </summary>
public class ErrorDetectableBaseDevice : BaseDevice, IDevice
{
#region Variable
private readonly R_TRIG _alarmTrigger;
/// <summary>
/// 是否启用误差检测
/// </summary>
private readonly bool _isEnableErrDetection;
/// <summary>
/// 误差报警超限阈值
/// </summary>
private readonly double _alarmRange;
/// <summary>
/// 误差报警超限持续时间
/// </summary>
private readonly double _alarmTime;
/// <summary>
/// 误差警告超限阈值
/// </summary>
private readonly double _warningRange;
/// <summary>
/// 误差警告超限持续时间
/// </summary>
private readonly double _warningTime;
protected readonly DIAccessor DiAlarm;
protected readonly string AlarmText;
/// <summary>
/// 误差超限警告检查器
/// </summary>
protected readonly ToleranceChecker ErrWarningChecker;
/// <summary>
/// 误差超限报警检查器
/// </summary>
protected readonly ToleranceChecker ErrAlarmChecker;
private readonly AlarmEventItem _alarmEvent;
private readonly AlarmEventItem _warningEvent;
#endregion
#region Constructors
public ErrorDetectableBaseDevice(string module, XmlElement node, string ioModule = "")
{
var attrModule = node.GetAttribute("module");
Module = string.IsNullOrEmpty(attrModule) ? module : attrModule;
Unit = node.GetAttribute("unit");
Name = node.GetAttribute("id");
Display = node.GetAttribute("display");
DeviceID = node.GetAttribute("schematicId");
// 获取diAlarm
DiAlarm = ParseDiNode("diAlarm", node, ioModule);
// 获取Alarm Text
AlarmText = node.GetAttribute("AlarmText");
var scBasePath = node.GetAttribute("scBasePath");
scBasePath = string.IsNullOrEmpty(scBasePath) ? $"{Module}.{Name}" : scBasePath.Replace("{module}", Module);
ScBasePath = scBasePath;
_isEnableErrDetection =
ParseScNode("scEnableAlarm", node, ioModule, $"{scBasePath}.{Display}.EnableAlarm")?.BoolValue ?? false;
_alarmRange =
ParseScNode("scAlarmRange", node, ioModule, $"{scBasePath}.AlarmRange")?.DoubleValue ??
double.NaN;
_alarmTime = ParseScNode("scAlarmTime", node, ioModule, $"{scBasePath}.AlarmTime")?.IntValue ??
int.MinValue;
_warningRange = SC.GetConfigItem($"{scBasePath}.WarningRange")?.DoubleValue ?? double.NaN;
_warningTime = SC.GetConfigItem($"{scBasePath}.WarningTime")?.IntValue ?? int.MinValue;
_alarmTrigger = new R_TRIG();
ErrWarningChecker = new ToleranceChecker();
ErrAlarmChecker = new ToleranceChecker();
_warningEvent = SubscribeAlarm($"{Module}.{Display}.ToleranceWarning", "", ResetWarningChecker,
EventLevel.Warning);
_alarmEvent = SubscribeAlarm($"{Module}.{Display}.ToleranceAlarm", "", ResetAlarmChecker);
}
#endregion
#region Properties
protected string Unit
{
get; set;
}
#endregion
#region Methods
private bool ResetWarningChecker()
{
ErrWarningChecker.Reset(_warningTime);
return true;
}
private bool ResetAlarmChecker()
{
ErrAlarmChecker.Reset(_alarmTime);
return true;
}
/// <summary>
/// 监测设置值和反馈值误差
/// </summary>
public virtual void MonitorSpFbError(bool allowErrorCheck, double setPoint, double feedback)
{
_alarmTrigger.CLK = DiAlarm != null && DiAlarm.Value;
if (_alarmTrigger.Q)
{
EV.PostAlarmLog(Module, AlarmText);
}
if (!_isEnableErrDetection || !allowErrorCheck)
{
ErrWarningChecker.RST = true;
ErrAlarmChecker.RST = true;
return;
}
// Out-of-rang Alarm detection
var alarmLow = (setPoint * Math.Abs(100 - _alarmRange) / 100);
var alarmHigh = (setPoint * Math.Abs(100 + _alarmRange) / 100);
ErrAlarmChecker.Monitor(feedback, alarmLow, alarmHigh, _alarmTime);
if (ErrAlarmChecker.Trig)
{
_alarmEvent.Description = $"{Display} feedback ({feedback:F1}{Unit}) out of range {alarmLow} - {alarmHigh} {Unit} in {_alarmTime:F0} seconds";
_alarmEvent.Set();
}
// 如果报Alarm不再检查Warning。
if (_alarmEvent.IsTriggered)
return;
// Out-of-rang warning detection
var warnLow = (setPoint * Math.Abs(100 - _warningRange) / 100);
var warnHigh = (setPoint * Math.Abs(100 + _warningRange) / 100);
ErrWarningChecker.Monitor(feedback, warnLow, warnHigh, _warningTime);
if (ErrWarningChecker.Trig)
{
_warningEvent.Description = $"{Display} feedback ({feedback:F1}{Unit}) out of range {warnLow} - {warnHigh} {Unit} in {_warningTime:F0} seconds";
_warningEvent.Set();
}
}
public virtual bool Initialize()
{
return true;
}
public virtual void Monitor()
{
}
public virtual void Terminate()
{
}
public virtual void Reset()
{
_alarmTrigger.RST = true;
ErrAlarmChecker.Reset(_alarmTime);
ErrWarningChecker.Reset(_warningTime);
_warningEvent.Reset();
_alarmEvent.Reset();
}
#endregion
}
}