207 lines
5.6 KiB
C#
207 lines
5.6 KiB
C#
using Aitex.Core.Common.DeviceData;
|
|
using Aitex.Core.RT.DataCenter;
|
|
using Aitex.Core.RT.Device;
|
|
using Aitex.Core.RT.Event;
|
|
using Aitex.Core.RT.IOCore;
|
|
using Aitex.Core.RT.Log;
|
|
using Aitex.Core.Util;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Xml;
|
|
|
|
namespace SicPM.Devices
|
|
{
|
|
public class IoSensor : BaseDevice, IDevice
|
|
{
|
|
#region Variables
|
|
|
|
public event Action<IoSensor, bool> OnSignalChanged;
|
|
|
|
private readonly DIAccessor _di = null;
|
|
private readonly DOAccessor _do = null;
|
|
|
|
private readonly string _warningText;
|
|
private readonly string _alarmText;
|
|
private readonly string _infoText;
|
|
|
|
private readonly bool _textOutTrigValue;
|
|
private readonly int _respDelayInSec = 0;
|
|
private readonly R_TRIG _trigTextOut;
|
|
|
|
private bool _previousValue;
|
|
private Dictionary<DateTime, bool> _dictValues;
|
|
|
|
|
|
#endregion
|
|
|
|
#region Constructors
|
|
|
|
public IoSensor(string module, XmlElement node, string ioModule = "")
|
|
{
|
|
var attrModule = node.GetAttribute("module");
|
|
base.Module = string.IsNullOrEmpty(attrModule) ? module : attrModule;
|
|
base.Name = node.GetAttribute("id");
|
|
base.Display = node.GetAttribute("display");
|
|
base.DeviceID = node.GetAttribute("schematicId");
|
|
|
|
_di = ParseDiNode("di", node, ioModule);
|
|
_do = ParseDoNode("do", node, ioModule);
|
|
|
|
if (!int.TryParse(node.GetAttribute("respDelayInSec"),
|
|
out _respDelayInSec))
|
|
_respDelayInSec = 0;
|
|
|
|
_infoText = node.GetAttribute("infoText");
|
|
_warningText = node.GetAttribute("warningText");
|
|
_alarmText = node.GetAttribute("alarmText");
|
|
|
|
if(!bool.TryParse(node.GetAttribute("textOutTrigValue"), out _textOutTrigValue))
|
|
_textOutTrigValue = false;
|
|
|
|
_trigTextOut = new R_TRIG();
|
|
_dictValues = new Dictionary<DateTime, bool>();
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Properites
|
|
|
|
public DIAccessor SensorDI => _di;
|
|
|
|
public DOAccessor SensorDO => _do;
|
|
|
|
public bool AlarmTrigValue => _textOutTrigValue && !string.IsNullOrEmpty(_alarmText);
|
|
|
|
|
|
public Action WarningAction
|
|
{
|
|
get;
|
|
set;
|
|
}
|
|
|
|
|
|
public bool Value
|
|
{
|
|
get
|
|
{
|
|
if (_di != null)
|
|
return _di.Value;
|
|
|
|
if (_do != null)
|
|
return _do.Value;
|
|
|
|
return false;
|
|
}
|
|
}
|
|
|
|
private AITSensorData DeviceData
|
|
{
|
|
get
|
|
{
|
|
var data = new AITSensorData()
|
|
{
|
|
DeviceName = Name,
|
|
DeviceSchematicId = DeviceID,
|
|
DisplayName = Display,
|
|
Value = Value,
|
|
};
|
|
|
|
return data;
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Methods
|
|
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
/// <param name="realtimeValue"></param>
|
|
/// <returns></returns>
|
|
private bool Hysteresis(bool realtimeValue)
|
|
{
|
|
if (_respDelayInSec <= 0)
|
|
return realtimeValue;
|
|
|
|
_dictValues.Add(DateTime.Now, realtimeValue);
|
|
var beginMom = DateTime.Now.AddSeconds(-1 * _respDelayInSec);
|
|
|
|
// 剔除记录时间超过设定的迟滞时长的数据点
|
|
foreach (var s in _dictValues.Where(kv => kv.Key < beginMom).ToList())
|
|
_dictValues.Remove(s.Key);
|
|
|
|
// 检查数据缓冲中是否同时存在true和false
|
|
var values = _dictValues.Select(kv => kv.Value).Distinct().ToList();
|
|
if(values.Count == 1)
|
|
return values[0];
|
|
|
|
// 如果信号波动,返回无效电平,表示没有收到有效信号。
|
|
return !_textOutTrigValue;
|
|
}
|
|
|
|
|
|
|
|
public bool Initialize()
|
|
{
|
|
DATA.Subscribe($"{Module}.{Name}.DeviceData", () => DeviceData);
|
|
DATA.Subscribe($"{Module}.{Name}.Value", () => Value);
|
|
|
|
return true;
|
|
}
|
|
|
|
public void Terminate()
|
|
{
|
|
}
|
|
|
|
public void Monitor()
|
|
{
|
|
try
|
|
{
|
|
_trigTextOut.CLK = (Hysteresis(Value) == _textOutTrigValue);
|
|
|
|
if (_trigTextOut.Q)
|
|
{
|
|
if (WarningAction != null)
|
|
{
|
|
WarningAction();
|
|
}
|
|
else if (!string.IsNullOrEmpty(_warningText.Trim()))
|
|
{
|
|
EV.PostWarningLog(Module, _warningText);
|
|
}
|
|
else if (!string.IsNullOrEmpty(_alarmText.Trim()))
|
|
{
|
|
EV.PostAlarmLog(Module, _alarmText);
|
|
}
|
|
else if (!string.IsNullOrEmpty(_infoText.Trim()))
|
|
{
|
|
EV.PostInfoLog(Module, _infoText);
|
|
}
|
|
}
|
|
|
|
if (_previousValue != Value)
|
|
{
|
|
if (OnSignalChanged != null)
|
|
OnSignalChanged(this, Value);
|
|
_previousValue = Value;
|
|
}
|
|
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
LOG.Write(ex);
|
|
|
|
}
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
_trigTextOut.RST = true;
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
}
|