Sic.Framework-Nanjing-Baishi/MECF.Framework.RT.Equipment.../HardwareUnits/Temps/AKunTemp/AKunTemp.cs

355 lines
12 KiB
C#
Raw Normal View History

2023-04-13 11:51:03 +08:00
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.RT.SCCore;
using Aitex.Core.Util;
using Global;
using MECF.Framework.Common.Communications;
using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.LoadPorts.TDK;
using RTOverEthernetDevelopmentKit;
using SessionLayer;
using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Xml;
using System.Xml.Linq;
2023-04-13 11:51:03 +08:00
namespace MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Temps
{
/// 昂坤Viper-RTC测温数据交互流程简介
/// 1上位机连接昂坤软件启动的服务器昂坤服务器启用 工控机的IP + 53888固定端口上位机连接服务器获取温度数据
/// 2昂坤软件通过USB线连接主机盒子获取温度上位机不用干预
/// 3昂坤通讯特性上位机发送一条指令后服务器会一直安装设定频率一直发送数据上位机只接受就可以了
/// 4上位机读取数据通过昂坤提供的库调用连接和数据获取方法
/// 5断联分为昂坤软件服务器、USB两种断联和重连判断例如昂坤软件未打开或UBS线松动
/// 6继承ITempData接口上层使用接口获取数据方便以后扩展测温硬件
/// <summary>
/// 昂坤Viper-RTC测温
/// </summary>
public class AKunTemp : BaseDevice, IDevice, IConnection, ITempData
{
#region Variables
private IROverEthernet _ir;
2023-04-13 11:51:03 +08:00
private PeriodicJob _thread;//工作线程
TempBasFunction tempBasFunction;
2023-04-13 11:51:03 +08:00
/// <summary>
/// 连接昂坤软件服务器
/// </summary>
private readonly R_TRIG _trigConnServiceError = new R_TRIG();
/// <summary>
/// 机箱USB断联
/// </summary>
private readonly R_TRIG _trigUSBDataError = new R_TRIG();
/// <summary>
/// 机箱USB重连
/// </summary>
private readonly R_TRIG _trigUSBDataOK = new R_TRIG();
/// <summary>
/// 温度不发生变化
/// </summary>
private readonly R_TRIG _trigTempNoChange = new R_TRIG();
private int TempInvariantCount;
private int TempInvariantCountMax = 5;
2023-04-13 11:51:03 +08:00
private int _lastIntegTime;
public int TempMin { get; set; } = 600;
public int NumberOfChannels { get; set; } = 4;
public float[] TempDatasArray { get; set; }
2023-04-13 11:51:03 +08:00
#endregion
#region Constructors
public AKunTemp(string module, XmlElement node, string ioModule = "") : base(module, node, ioModule)
2023-04-13 11:51:03 +08:00
{
2023-04-13 11:51:03 +08:00
}
#endregion
#region Properties
public string Address
{
get;
private set;
}
private int port { get; set; }
public bool IsConnected => _ir.IsConnected;
/// <summary>
/// 获取系统配置中的积分时间。
/// </summary>
/// <returns></returns>
private int GetScIntegrationTime()
{
var integrationTime = SC.GetValue<int>($"{Name}.IntegrationTime"); // the minimum value should be 10ms.
if (integrationTime < 10)
integrationTime = 10;
return integrationTime;
}
public bool Connect()
{
try
{
_ir.Init(Address, port);
_ir.StopIR();
2023-04-13 11:51:03 +08:00
_lastIntegTime = GetScIntegrationTime();
_ir.SetIntegrationTime(_lastIntegTime);
_ir.StartIR();
return true;
}
catch (Exception ex)
{
return false;
}
}
private void Reconnect()
{
try
{
_ir.Close();
}
catch
{
}
finally { Connect(); }
}
public bool Initialize()
{
try
{
if (!SC.GetValue<bool>($"{ScBasePath}.EnableDevice"))
return true;
IniTemp();
IniData();
return true;
}
catch (Exception ex)
{
LOG.Error(ex.Message, ex);
return false;
}
}
private void IniTemp()
{
TempDatasArray = new float[NumberOfChannels];
for (int i = 0; i < NumberOfChannels; i++)//初始化温度下限
{
int indexer = i;
TempDatasArray[indexer] = TempMin;
DATA.Subscribe($"{Name}.t{indexer + 1}", () => TempDatasArray[indexer]);
}
}
private void IniData()
{
string[] data = SC.GetStringValue($"{ScBasePath}.Address").Split(':');
Address = data[0];
port = Convert.ToInt32(data[1]);
_ir = new IROverEthernet();
_trigUSBDataOK.CLK = true;//初始化重连信号
var scOnTime = SC.GetValue<int>($"TempDevice.OnTimer");
_thread = new PeriodicJob(scOnTime, OnTimer, "AKunTemp", true);
//添加参数设置
SC.RegisterValueChangedCallback($"TempDevice.OnTimer", (obj) => { _thread.ChangeInterval((int)obj); });
SC.RegisterValueChangedCallback($"{ScBasePath}.IntegrationTime", (obj) => { Set_Callback((int)obj); });
tempBasFunction = new TempBasFunction(Name, TempMin, NumberOfChannels);
tempBasFunction.SetPm1Pm2DoForInterlock(false);
}
public void Set_Callback(object obj)
{
_ir.StopIR();
_ir.SetIntegrationTime((int)obj);
_ir.StartIR();
}
2023-04-13 11:51:03 +08:00
private bool OnTimer()
{
try
{
//判断昂坤软件服务器断联和重连逻辑
if (!_ir.IsConnected)
{
Reconnect();
if (!_ir.IsConnected)//昂坤软件的服务器未打开
{
_trigConnServiceError.CLK = true;
if (_trigConnServiceError.Q)
{
Thread.Sleep(2000);//不加延时软件刚启动可能不打印
tempBasFunction.PM1PM2PostLog($"AKun Temp Software Maybe Not Open {Address} {Name}", EV.PostAlarmLog);
tempBasFunction.SetPm1Pm2DoForInterlock(true);
2023-04-13 11:51:03 +08:00
}
}
else//连接成功后不会再进入,只会提示一次
{
_trigConnServiceError.RST = true;
tempBasFunction.PM1PM2PostLog($"Connect OK with AKun Temp Software Form {Address} {Name}", EV.PostInfoLog);
tempBasFunction.SetPm1Pm2DoForInterlock(false);
}
Thread.Sleep(1000);
2023-04-13 11:51:03 +08:00
return true;
}
//使用厂商提供的属性值判断是否断联,反馈时间慢
2023-04-13 11:51:03 +08:00
//判断USB断联和重连 服务器未连接时不用判断USB
//if(_ir.Current.Status == 0)//Current.Status昂坤提供的SUB断联属性测试发现大约1分钟左右才会提示断联
//{
// _trigUSBDataOK.CLK = true;//USB连接提示置起
// if (_trigUSBDataOK.Q)
// {
// ConnectOK($"{Module} Connect OK with {Name} From USB");
// }
// _trigUSBDataError.RST = true;
//}
//else
//{
// _trigUSBDataOK.RST = true;//复位USB重连信号准备下次使用
// _trigUSBDataError.CLK = true;//置位USB断联信号准备报警
// if (_trigUSBDataError.Q)
// {
// System.Threading.Thread.Sleep(2000);
// ConnectError($"{Module} Can not connect with {Name} From USB");
// }
// return true;
//}
//上面判断都没问题就可以读取温度了
GetValues();
return true;
}
catch (Exception ex)
{
if (_trigConnServiceError.Q)
{
tempBasFunction.PM1PM2PostLog($"Unable to read data from viper RTC, {ex.Message}", EV.PostAlarmLog);
2023-04-13 11:51:03 +08:00
}
return true;
}
}
public void Terminate()
{
try
{
_ir.Close();
}
catch (Exception ex)
{
LOG.Write(ex);
}
}
public void Reset()
{
_trigConnServiceError.RST = true;
_trigUSBDataError.RST = true;
_trigTempNoChange.RST = true;
2023-04-13 11:51:03 +08:00
}
int CountNum = 0;//接受数据失败次数
private void GetValues()
{
try
{
var all = _ir.GetAllChannel();
//USB线断联和重连逻辑
{
//连接时使用次数报警,多次接收到空数据开始报警 此时发现正常连接时Count=0会出现频率是几分钟出现一次
if ( (all[0].Count == 0 && all[1].Count == 0 && all[2].Count == 0 && all[3].Count == 0) ||
_ir.Current.Status != 0)//首次打开上位机时测试昂坤软件打开且未连接USB时Count一直大于0所以此处添加厂商提供的属性值判断USB连接
2023-04-13 11:51:03 +08:00
{
CountNum++;
if (CountNum > 10)
{
_trigUSBDataOK.CLK = false;//复位USB重连信号
_trigUSBDataError.CLK = true;
if (_trigUSBDataError.Q)
tempBasFunction.PM1PM2PostLog($"Can not connect with {Name} From USB,Status:{_ir.Current.Status}", EV.PostAlarmLog);
2023-04-13 11:51:03 +08:00
CountNum = 0;
tempBasFunction.SetPm1Pm2DoForInterlock(true);
2023-04-13 11:51:03 +08:00
return;
}
return;
}
_trigUSBDataOK.CLK = true;
if (_trigUSBDataOK.Q)
{
tempBasFunction.PM1PM2PostLog($"Connect OK with {Name} From USB", EV.PostInfoLog);
2023-04-13 11:51:03 +08:00
_trigUSBDataError.RST = true;//复位USB断联信号
tempBasFunction.SetPm1Pm2DoForInterlock(false);
2023-04-13 11:51:03 +08:00
}
//有数据时必须复位
CountNum = 0;
}
//解析温度数值 昂坤屏蔽通道后依然返回四个数据
2023-04-13 11:51:03 +08:00
for (var i = 0; i < all.Count; i++)
{
float _temp = all[i].Average();
if (_temp <= 600)//设置温度下限
_temp = 600;
TempDatasArray[i] = _temp;
2023-04-13 11:51:03 +08:00
}
TempInvariantCount = tempBasFunction.TempInvariantCount(TempDatasArray, out string tempInvariantData);
_trigTempNoChange.CLK = TempInvariantCount >= TempInvariantCountMax ? true : false;
if (_trigTempNoChange.Q)
{
tempBasFunction.PM1PM2PostLog( $"{Name} {TempInvariantCount} temp no changeCount {tempInvariantData}", EV.PostWarningLog);
}
2023-04-13 11:51:03 +08:00
}
catch (Exception ex)
{
LOG.Write($"{Name} AKunTemp GetValues Error {ex}");
}
}
#endregion
#region Events
public bool Disconnect()
{
Terminate();
return true;
}
//
#endregion
}
}