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; namespace MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Temps.AE { 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 int tempCount = 1; private LinkedList _lstHandler = new LinkedList(); private object _locker = new object(); private bool _enableLog = true; private string _scRoot; public double TempData1 { get; set; } public double TempData2 { get; set; } public double TempData3 { get; set; } public double TempData4 { 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, string name, string scRoot) : base(module, name, name, name) { _scRoot = scRoot; _activeMonitorStatus = true; } ~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(string address, bool enableLogMessage) { DATA.Subscribe($"PM1.{Name}.Middle", () => TempData1); DATA.Subscribe($"PM1.{Name}.Outer", () => TempData2); DATA.Subscribe($"PM2.{Name}.Middle", () => TempData3); DATA.Subscribe($"PM2.{Name}.Outer", () => TempData4); Address = address; _enableLog = enableLogMessage; _connection = new AETempConnection(address); _connection.EnableLog(enableLogMessage); _thread = new PeriodicJob(400, OnTimer, $"{Module}.{Name} MonitorHandler", true); ConnectionManager.Instance.Subscribe($"{Name}", this); return true; } 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}"); //在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"); } _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 >= 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 { _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 liTemp = new List(); 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; } // } /// /// 均方根值法 /// /// /// /// 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 liTemp = new List(); 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($"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(); } public bool Initialize() { return true; } } }