143 lines
3.7 KiB
C#
143 lines
3.7 KiB
C#
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.FloatValue : _ai.Value;
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
}
|
||
|
||
public float SetPoint
|
||
{
|
||
get
|
||
{
|
||
if (_ao != null)
|
||
{
|
||
return _isFloatAioType ? _ao.FloatValue : _ao.Value;
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
set
|
||
{
|
||
if (_ao != null)
|
||
{
|
||
if (_isFloatAioType)
|
||
_ao.FloatValue = 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);
|
||
//防止UI没启动,就进行EV.Post
|
||
Task.Delay(1000 * 30).ContinueWith((a) => _thread.Start());
|
||
|
||
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;
|
||
}
|
||
}
|
||
} |