121 lines
3.3 KiB
C#
121 lines
3.3 KiB
C#
using System;
|
||
using System.Xml;
|
||
using Aitex.Core.RT.Event;
|
||
using Aitex.Core.RT.IOCore;
|
||
using Aitex.Core.Util;
|
||
|
||
namespace Aitex.Core.RT.Device.Unit
|
||
{
|
||
/// <summary>
|
||
/// 心跳包机制
|
||
///
|
||
/// 功能:
|
||
/// 1.C#送出给PLC,如果PLC检测到C#心跳信号停止,则判定C#程序运行异常,从而触发安全逻辑动作.
|
||
/// 2.C#检测PLC返回的心跳包信号,如果检测到PLC心跳信号停止,则判定PLC程序运行异常,从而进行报警处理.
|
||
/// </summary>
|
||
public class IoHeartbeat : BaseDevice, IDevice
|
||
{
|
||
public float Feedback
|
||
{
|
||
get
|
||
{
|
||
return _isFloatAioType ? _ai.FloatValue : _ai.Value;
|
||
}
|
||
}
|
||
|
||
public float SetPoint
|
||
{
|
||
get
|
||
{
|
||
return _isFloatAioType ? _ao.FloatValue : _ao.Value;
|
||
}
|
||
set
|
||
{
|
||
if (_isFloatAioType)
|
||
_ao.FloatValue = value;
|
||
else
|
||
{
|
||
_ao.Value = (short)value;
|
||
}
|
||
}
|
||
}
|
||
private int PLC_Heart_Beat_Timeout_ms = 1000* 120;
|
||
//IO
|
||
private AIAccessor _ai = null;
|
||
private AOAccessor _ao = null;
|
||
|
||
private DeviceTimer _updateTimer = new DeviceTimer(); //更新 AO信号 给PLC
|
||
|
||
private int MAX = 0x7FFF;
|
||
private float _prevAiValue = 0;
|
||
|
||
private DeviceTimer _connectTimer = new DeviceTimer();
|
||
private R_TRIG _trigConnectionLost = new R_TRIG();
|
||
private bool _isFloatAioType = false;
|
||
|
||
public IoHeartbeat(string module, XmlElement node, string ioModule = "")
|
||
{
|
||
base.Module = module;
|
||
base.Name = node.GetAttribute("id");
|
||
base.Display = node.GetAttribute("display");
|
||
base.DeviceID = node.GetAttribute("schematicId");
|
||
|
||
_ai = ParseAiNode("ai", node, ioModule);
|
||
_ao = ParseAoNode("ao", node, ioModule);
|
||
|
||
|
||
_isFloatAioType = !string.IsNullOrEmpty(node.GetAttribute("aioType")) && (node.GetAttribute("aioType") == "float");
|
||
|
||
}
|
||
|
||
public bool Initialize()
|
||
{
|
||
_updateTimer.Start(500);
|
||
_connectTimer.Start(PLC_Heart_Beat_Timeout_ms);
|
||
return true;
|
||
}
|
||
|
||
public void Terminate()
|
||
{
|
||
}
|
||
|
||
public void Monitor()
|
||
{
|
||
if (Math.Abs(_prevAiValue - Feedback) > 0.01)
|
||
{
|
||
_connectTimer.Start(PLC_Heart_Beat_Timeout_ms);
|
||
}
|
||
|
||
_trigConnectionLost.CLK = _connectTimer.IsTimeout();
|
||
if (_trigConnectionLost.Q)
|
||
{
|
||
EV.PostAlarmLog(Module, $"PLC heartbeat check failed");
|
||
}
|
||
|
||
_prevAiValue = Feedback;
|
||
|
||
//如果计时到达,则翻转心跳信号
|
||
if (_updateTimer.IsTimeout())
|
||
{
|
||
int value = (int)SetPoint;
|
||
value++;
|
||
if (value >= MAX)
|
||
{
|
||
value = 0;
|
||
}
|
||
|
||
SetPoint = value;
|
||
|
||
_updateTimer.Start(500); //500 ms
|
||
}
|
||
}
|
||
|
||
public void Reset()
|
||
{
|
||
_connectTimer.Start(PLC_Heart_Beat_Timeout_ms);
|
||
_trigConnectionLost.RST = true;
|
||
|
||
}
|
||
}
|
||
}
|