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);
}
}
}