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

537 lines
17 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using Aitex.Core.RT.DataCenter;
using Aitex.Core.RT.Device;
using Aitex.Core.RT.Event;
using Aitex.Core.RT.Log;
using Aitex.Core.RT.OperationCenter;
using Aitex.Core.RT.SCCore;
using Aitex.Core.RT.IOCore;
using Aitex.Core.Util;
using MECF.Framework.Common.Communications;
using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Temps.Omron;
using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.LoadPorts.TDK;
using System.Runtime.InteropServices;
using System.Xml;
using System.Net;
namespace MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Temps
{
public class AETemp : BaseDevice, IConnection, IDevice, ITempData
{
private AETempConnection _connection;
private bool _activeMonitorStatus;
private int _errorCode;
private R_TRIG _trigCommunicationError = new R_TRIG();
private R_TRIG _trigRetryConnect = new R_TRIG();
private R_TRIG _trigFewChannels = new R_TRIG();
private PeriodicJob _thread;
private LinkedList<HandlerBase> _lstHandler = new LinkedList<HandlerBase>();
private object _locker = new object();
private bool _enableLog = true;
public int TempMin { get; set; } = 600;
public int NumberOfChannels { get; set; } = 4;
public double[] TempDatasArray { get; set; }
/// <summary>
/// 设备通道启用
/// </summary>
bool[] ChannelInstalled { get; set; }
public string Address
{
get; set;
}
public bool IsConnected
{
get
{
return _connection != null && _connection.IsConnected;
}
}
public bool Connect()
{
return true;
}
public bool Disconnect()
{
return true;
}
public AETemp(string module, XmlElement node, string ioModule = "") : base(module, node, ioModule)
{
}
~AETemp()
{
_connection.Disconnect();
}
public void QueryTemp()
{
_lstHandler.AddLast(new AETempReadCommandHandler(this, "OUT", "1"));
}
public void ResetDevice()
{
}
public void QueryError()
{
EV.PostInfoLog(Module, "Query error");
}
public bool Initialize()
{
try
{
IniData();
IniTemp();
}
catch (Exception)
{
}
return true;
}
private void IniData()
{
Address = SC.GetStringValue($"{ScBasePath}.Address");
_enableLog = SC.GetValue<bool>($"{ScBasePath}.EnableLogMessage");
_connection = new AETempConnection(Address);
_connection.EnableLog(_enableLog);
_thread = new PeriodicJob(400, OnTimer, $"{Module}.{Name} MonitorHandler", true);
ConnectionManager.Instance.Subscribe($"{Name}", this);
}
private void IniTemp()
{
TempDatasArray = new double[NumberOfChannels];
ChannelInstalled = new bool[NumberOfChannels];
for (int i = 0; i < NumberOfChannels; i++)//初始化温度下限 初始化获取配置的通道是否禁用
{
TempDatasArray[i] = TempMin;
ChannelInstalled[i] = SC.GetValue<bool>($"TempDevice.{Name}.Channel{i+1}");
}
DATA.Subscribe($"{Name}.Data1", () => TempDatasArray[0]);
DATA.Subscribe($"{Name}.Data2", () => TempDatasArray[1]);
DATA.Subscribe($"{Name}.Data3", () => TempDatasArray[2]);
DATA.Subscribe($"{Name}.Data4", () => TempDatasArray[3]);
}
private bool OnTimer()
{
try
{
_connection.MonitorTimeout();
//
if (!_connection.IsConnected || _connection.IsCommunicationError)
{
lock (_locker)
{
_lstHandler.Clear();
}
//只要断开,就进行连接
if (!_connection.Connect())
{
_trigRetryConnect.CLK = !_connection.IsConnected;
if (_trigRetryConnect.Q)
{
LOG.Write($"{Module}.PMAETemp.SetPyroCommunicationError");
EV.PostAlarmLog(Module, $"Can not connect with {_connection.Address}, {Module}.{Name}");
IO.DO[$"PM1.DO_PyroCommunicationError"].Value = true;//新增断联后置位DO_220
IO.DO[$"PM2.DO_PyroCommunicationError"].Value = true;
//在Process模式和PreProcess模式下AE掉线直接Abort
object objStatus = DATA.Poll($"{Module}.Status");
if (objStatus != null)
{
string moduleStatus = objStatus.ToString();
if (moduleStatus == "PreProcess" || moduleStatus == "Process")
{
OP.DoOperation($"{Module}.Abort");
EV.PostAlarmLog("PM1", $"Can not connect with {_connection.Address}, {Module}.{Name}, Abort!");
EV.PostAlarmLog("PM2", $"Can not connect with {_connection.Address}, {Module}.{Name}, Abort!");
}
else
{
//EV.PostWarningLog(Module, $"Can not connect with {_connection.Address}, {Module}.{Name}");
LOG.Write(Module + $"Can not connect with {_connection.Address}, {Module}.{Name}");
}
}
else
{
LOG.Write(Module + $"Can not connect with {_connection.Address}, {Module}.{Name}");
}
}
_connection.ForceClear();
Thread.Sleep(1000);//重连延时
return true;
}
else
{
//连接成功后不会再进入所以也只是写入一次LOG
LOG.Write($"{Module} {Name} Connected");
EV.PostInfoLog(Module, $"{Name} Connected");
IO.DO[$"PM1.DO_PyroCommunicationError"].Value = false;//新增连接后复位DO_220
IO.DO[$"PM2.DO_PyroCommunicationError"].Value = false;
}
_trigRetryConnect.CLK = !_connection.IsConnected;
_connection.ForceClear();
return true;
}
//
HandlerBase handler = null;
lock (_locker)
{
if (_lstHandler.Count == 0)
QueryTemp();
if (_lstHandler.Count > 0 && !_connection.IsBusy)
{
handler = _lstHandler.First.Value;
_lstHandler.RemoveFirst();
if (handler != null)
{
_connection.Execute(handler);
}
}
}
}
catch (Exception ex)
{
LOG.Write(ex);
}
return true;
}
internal void NoteError()
{
}
public void ParseCommandInfo(string command, string Message)
{
try
{
switch (command)
{
case "OUT":
{
if (Message != null)
{
if (Message.Contains(" "))
{
var strs = Message.Split(' ');
if (strs.Length > 0 )
{
//判断AE温度通道启用和上位机设定通道启用是否相同
if (strs.Length != ChannelInstalled.Count(c => c == true))
{
_trigFewChannels.CLK = true;
if (_trigFewChannels.Q)
{
EV.PostAlarmLog("PM1", "AE Error: Too few channels.");
EV.PostAlarmLog("PM2", "AE Error: Too few channels.");
}
return;
}
//温度数组,根据通道是否屏蔽来赋值,
_trigFewChannels.RST = true;
for (int i = 0; i < strs.Length; i++)
{
if (ChannelInstalled[i] == true)
{
TempDatasArray[i] = Convert.ToDouble(strs[i]);
}
}
}
//if (strs.Length >= 4)
//{
// _trigFewChannels.CLK = false;
// //
// TempData1 = Convert.ToDouble(strs[0]);
// TempData2 = Convert.ToDouble(strs[1]);
// TempData3 = Convert.ToDouble(strs[2]);
// TempData4 = Convert.ToDouble(strs[3]);
//}
//else if (strs.Length >= 3)
//{
// _trigFewChannels.CLK = false;
// //
// TempData1 = Convert.ToDouble(strs[0]);
// TempData2 = Convert.ToDouble(strs[1]);
// TempData3 = Convert.ToDouble(strs[2]);
//}
//else
//{
// _trigFewChannels.CLK = true;
// if (_trigFewChannels.Q)
// {
// EV.PostAlarmLog("PM1", "AE Error: Too few channels.");
// EV.PostAlarmLog("PM2", "AE Error: Too few channels.");
// }
//}
}
}
}
break;
}
}
catch (Exception ex)
{
}
}
#region
//qbh 20220309
const int iQueCap = 10;
static Queue qWafInner = new Queue(iQueCap);
//static Queue qSusInner = new Queue(iQueCap);
static Queue qWafMiddle = new Queue(iQueCap);
//static Queue qSusMiddle = new Queue(iQueCap);
static Queue qWafOuter = new Queue(iQueCap);
//static Queue qSusOuter = new Queue(iQueCap);
const double dbThres = 20.0;
public static double TempFilter(string sName, double dbNewTemp)
{
//
Queue qTempData = new Queue();
switch (sName)
{
case "TempData1":
qTempData = qWafInner;
break;
case "TempData2":
qTempData = qWafMiddle;
break;
case "TempData3":
qTempData = qWafOuter;
break;
default:
break;
}
//
qTempData.Enqueue(dbNewTemp);
//
if (qTempData.Count < iQueCap)
{
return dbNewTemp;
}
else
{
//
while (qTempData.Count > iQueCap)
{
qTempData.Dequeue();
}
//
List<double> liTemp = new List<double>();
object[] objs = qTempData.ToArray();
foreach (object obj in objs)
{
liTemp.Add((double)obj);
}
liTemp.Sort();
if (liTemp.Count > 0)
{
liTemp.RemoveAt(0);
}
liTemp.Reverse();
if (liTemp.Count > 0)
{
liTemp.RemoveAt(0);
}
//
double dbAvg = 0.0;
foreach (double data in liTemp)
{
dbAvg += data;
}
dbAvg /= liTemp.Count;
//
return dbAvg;
}
//
}
/// <summary>
/// 均方根值法
/// </summary>
/// <param name="sName"></param>
/// <param name="dbNewTemp"></param>
/// <returns></returns>
public static double TempFilter2(string sName, double dbNewTemp)
{
//
Queue qTempData = new Queue();
switch (sName)
{
case "TempData1":
qTempData = qWafInner;
break;
case "TempData2":
qTempData = qWafMiddle;
break;
case "TempData3":
qTempData = qWafOuter;
break;
default:
break;
}
//
qTempData.Enqueue(dbNewTemp);
//
if (qTempData.Count < iQueCap)
{
return dbNewTemp;
}
else
{
//
while (qTempData.Count > iQueCap)
{
qTempData.Dequeue();
}
//
List<double> liTemp = new List<double>();
object[] objs = qTempData.ToArray();
foreach (object obj in objs)
{
liTemp.Add((double)obj);
}
liTemp.Sort();
if (liTemp.Count > 0)
{
liTemp.RemoveAt(0);
}
liTemp.Reverse();
if (liTemp.Count > 0)
{
liTemp.RemoveAt(0);
}
//均方根
double dbAvg = 0.0;
foreach (double data in liTemp)
{
dbAvg += data * data;
}
dbAvg /= liTemp.Count;
dbAvg = Math.Sqrt(dbAvg);
//
return dbAvg;
}
//
}
#endregion
public void Monitor()
{
try
{
_connection.EnableLog(_enableLog);
_trigCommunicationError.CLK = _connection.IsCommunicationError;
if (_trigCommunicationError.Q)
{
EV.PostAlarmLog("PM1", $"{Module}.{Name} communication error, {_connection.LastCommunicationError}");
EV.PostAlarmLog("PM2", $"{Module}.{Name} communication error, {_connection.LastCommunicationError}");
}
}
catch (Exception ex)
{
LOG.Write(ex);
}
}
public void Reset()
{
_connection.SetCommunicationError(false, "");
_enableLog = SC.GetValue<bool>($"AETemp.EnableLogMessage");
_trigCommunicationError.RST = true;
//_trigRetryConnect.RST = true;
_trigFewChannels.RST = true;
}
public void SetActiveMonitor(bool active)
{
_activeMonitorStatus = active;
}
public void SetErrorCode(int errorCode)
{
_errorCode = errorCode;
}
public void Terminate()
{
_connection.Disconnect();
}
}
}