using Aitex.Core.Common.DeviceData; using Aitex.Core.RT.DataCenter; using Aitex.Core.RT.Event; using Aitex.Core.RT.IOCore; using Aitex.Core.RT.Log; using Aitex.Core.RT.SCCore; using Aitex.Core.Util; using MECF.Framework.Common.Event; using System; using System.Diagnostics; using System.Xml; using static Aitex.Core.Util.SubscriptionAttribute; namespace Aitex.Core.RT.Device.Unit { /// /// DO reset /// DI alarm signal /// public class IoAlarmSignal : BaseDevice, IDevice { private bool SignalFeedback { get { if (_diSignal != null) return _diSignal.Value; if (_aiSignal != null && !string.IsNullOrEmpty(_condition)) { if (_condition == "H") return _aiSignal.FloatValue > _limitValue; if (_condition == "L") return _aiSignal.FloatValue < _limitValue; } return false; } set { } } private bool SignalSetPoint { get { if (_doReset != null) return _doReset.Value; return false; } set { if (_doReset != null) _doReset.Value = value; } } private AIAccessor _aiSignal = null; private DIAccessor _diSignal = null; private DOAccessor _doReset = null; private Stopwatch _resetTimer = new Stopwatch(); public AlarmEventItem AlarmTriggered { get; set; } public AlarmEventItem AlarmRecovery { get; set; } private RD_TRIG _trigSignalOn = new RD_TRIG(); public RD_TRIG RrigSignalOn => _trigSignalOn; private bool _alarmTrigValue; public bool AlarmTrigValue => _alarmTrigValue; private DeviceTimer _alarmMonitorTimer = new DeviceTimer(); public bool IsAlarmAutoRecovery => _isAlarmAutoRecovery; public bool _isAlarmAutoRecovery; public string Level { get; set; } bool _ignoreSaveDB = false; public bool ignoreSaveDB { get { return _ignoreSaveDB; } set { _ignoreSaveDB = value; } } private float _delayTime;//大于0时,此时间段内一直满足条件才报警 private Stopwatch _delayTimer = new Stopwatch(); private float _limitValue;//大于0时,此时间段内一直满足条件才报警 private string _condition; public AITSensorData DeviceData { get { AITSensorData data = new AITSensorData() { DeviceName = Name, DeviceSchematicId = DeviceID, DisplayName = Display, Value = SignalFeedback, }; return data; } } public bool Value => SignalFeedback; public IoAlarmSignal(string module, string name, DIAccessor diSignal, bool alarmTrigValue = true, bool isAlarmAutoRecovery = false) { base.Module = module; base.Name = name; _diSignal = diSignal; _alarmTrigValue = alarmTrigValue; _isAlarmAutoRecovery = isAlarmAutoRecovery; Initialize(); } public IoAlarmSignal(string module, XmlElement node, string ioModule = "") { base.Module = string.IsNullOrEmpty(node.GetAttribute("module")) ? module : node.GetAttribute("module"); base.Name = ioModule.ToLower().StartsWith("gasline") ? $"{ioModule}{node.GetAttribute("id")}" : node.GetAttribute("id"); base.Display = node.GetAttribute("display"); base.DeviceID = node.GetAttribute("schematicId"); Level = node.GetAttribute("level"); ignoreSaveDB = string.IsNullOrEmpty(node.GetAttribute("ignoreSaveDB")) ? false : Convert.ToBoolean(node.GetAttribute("ignoreSaveDB")); _doReset = ParseDoNode("doReset", node, ioModule); _diSignal = ParseDiNode("diSignal", node, ioModule); _aiSignal = ParseAiNode("aiSignal", node, ioModule); if (_diSignal == null) _diSignal = ParseDiNode("di", node, ioModule); _alarmTrigValue = Convert.ToBoolean(string.IsNullOrEmpty(node.GetAttribute("alarmTrigValue")) ? "true" : node.GetAttribute("alarmTrigValue")); _isAlarmAutoRecovery = Convert.ToBoolean(string.IsNullOrEmpty(node.GetAttribute("alarmAutoRecovery")) ? "false" : node.GetAttribute("alarmAutoRecovery")); _delayTime = Convert.ToSingle(string.IsNullOrEmpty(node.GetAttribute("delay")) ? "0" : node.GetAttribute("delay")); _limitValue = Convert.ToSingle(string.IsNullOrEmpty(node.GetAttribute("limitValue")) ? "0" : node.GetAttribute("limitValue")); _condition = node.GetAttribute("condition"); } public bool Initialize() { //AlarmTriggered = SubscribeAlarm($"{Module}.{Name}.AlarmTriggered", $"{Name} alarm triggered", ResetAlarmChecker); DATA.Subscribe($"{Module}.{Name}.DeviceData", () => DeviceData, FLAG.IgnoreSaveDB); DATA.Subscribe($"{Module}.{Name}.Value", () => SignalFeedback,FLAG.IgnoreSaveDB); // DATA.Subscribe($"{Module}.{Name}.ignoreSaveDB", () => ignoreSaveDB); _alarmMonitorTimer.Start(2000); return true; } private bool ResetAlarmChecker() { if (SignalFeedback) { if (!SignalSetPoint) { _resetTimer.Restart(); SignalSetPoint = true; } } return !SignalFeedback; } public void Terminate() { } public void Monitor() { if (SC.ContainsItem("System.BypassInterlock") && SC.GetValue("System.BypassInterlock")) return; //两秒后才检测,防止有报警是false值的时候,PLC还没读取数值就报警 if (!_alarmMonitorTimer.IsTimeout()) return; if (AlarmTriggered != null) { if (_delayTime > 0) { if (_alarmTrigValue == SignalFeedback) { if (!_delayTimer.IsRunning) _delayTimer.Restart(); if (_delayTimer.ElapsedMilliseconds > _delayTime * 1000) _trigSignalOn.CLK = true; else _trigSignalOn.CLK = false; } else { _trigSignalOn.CLK = false; _delayTimer.Stop(); } } else { _trigSignalOn.CLK = _alarmTrigValue ? SignalFeedback : !SignalFeedback; } if (_trigSignalOn.R) { AlarmTriggered?.Set(); } if (_trigSignalOn.T) { AlarmTriggered?.Set(); if (!ignoreSaveDB) { EV.ClearAlarmEvent(AlarmTriggered.EventEnum); } LOG.Write($"{AlarmTriggered.EventEnum} is auto recovered"); } if (SignalSetPoint) { if (!SignalFeedback) { AlarmTriggered.Reset(); SignalSetPoint = false; _resetTimer.Stop(); } if (SignalFeedback && _resetTimer.IsRunning && _resetTimer.ElapsedMilliseconds > 5 * 1000) { _resetTimer.Stop(); EV.PostWarningLog(Module, $"Can not reset {Display} in 5 seconds"); SignalSetPoint = false; } } } } public void Reset() { _trigSignalOn.RST = true; if (AlarmTriggered != null) AlarmTriggered.IsAcknowledged = true; } public void SetIgnoreError(bool ignore) { AlarmTriggered.SetIgnoreError(ignore); } } }