SIC-12/Framework/MECF.Framework.RT.EquipmentLibrary/Devices/IoHeartBeat.cs

146 lines
3.8 KiB
C#
Raw Normal View History

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 System;
using System.Threading.Tasks;
using System.Xml;
namespace Aitex.Core.RT.Device.Devices
{
internal class IoHeartBeat : BaseDevice, IDevice
{
public float Feedback
{
get
{
if (_ai != null)
{
return _isFloatAioType ? _ai.Value : _ai.Value;
}
return 0;
}
}
public float SetPoint
{
get
{
if (_ao != null)
{
return _isFloatAioType ? _ao.Value : _ao.Value;
}
return 0;
}
set
{
if (_ao != null)
{
if (_isFloatAioType)
_ao.Value = value;
else
_ao.Value = (short)value;
}
}
}
//IO
private AIAccessor _ai = null;
private AOAccessor _ao = null;
private bool _isFloatAioType = false;
private readonly DeviceTimer _timHeartBeatOfRange = new();
private readonly R_TRIG _trigHeartBeatError = new();
private short _counter = 0;
private PeriodicJob _thread;
private bool _isModuleInstalled;
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()
{
_thread = new PeriodicJob(1000, OnTimer, "PLC Write Thread", false);
_isModuleInstalled= SC.SafeGetValue($"System.SetUp.Is{Module}Installed", false);
if (!SC.SafeGetValue($"System.IsSimulatorMode", false))//获取不到值时,也要开启心跳
Task.Delay(1000 * 30).ContinueWith((a) => _thread.Start()); //防止UI没启动就进行EV.Post
return true;
}
public bool OnTimer()
{
try
{
if (!_isModuleInstalled)//模块未安装直接退出
return true;
if (Feedback != SetPoint && _timHeartBeatOfRange.IsIdle())//检测值是否相等
_timHeartBeatOfRange.Start(1000 * 10);
if (Feedback == SetPoint)//有数据搬运机制把AO中的数值映射到AI中所以二者会实时相同
{
SetHeartBeatValue();//执行每秒自加一
_timHeartBeatOfRange.Stop();
}
_trigHeartBeatError.CLK = _timHeartBeatOfRange.IsTimeout();//超时后才会置true
if (_trigHeartBeatError.Q)
EV.PostAlarmLog(Module, $"Alarm:PLC heartbeat error , Time ovre 10s");
}
catch (Exception ex)
{
LOG.Write(ex);
}
return true;
}
private void SetHeartBeatValue()
{
_counter++;
if (_counter > 1000)
_counter = 0;
SetPoint = _counter;
}
public void Terminate()
{
}
public void Monitor()
{
}
public void Reset()
{
_trigHeartBeatError.RST = true;
}
}
}