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