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 System; using System.Collections.Concurrent; namespace MECF.Framework.RT.EquipmentLibrary.HardwareUnits.SMIFs.Fortrend { public abstract class SMIFBase : BaseDevice, IDevice { protected bool IsInstalled; private string _scRoot; private bool _enableLog; //完成标志 public bool IsDone = true; public bool IsHomeDone; public bool IsLoadDone; public bool IsUnloadDone; public bool IsLockDone; public bool IsUnLockDone; public bool IsSwitchDone; public bool IsCassetteExist => _diCassetteExist != null ? _diCassetteExist.Value : false; public string Mode; public string PortStatus; public bool IsPodPresent => _diPodInPlace != null ? _diPodInPlace.Value : false; public bool IsSMIFReady => _diReady != null ? _diReady.Value : false; public bool IsSMIFAlarm => _diAlarm != null ? _diAlarm.Value : true; public bool IsHomed; //当前错误码 public int CurErrorCode; protected DIAccessor _diReady = null; protected DIAccessor _diAlarm = null; protected DIAccessor _diPodInPlace = null; protected DIAccessor _diReadyToUnload = null; protected DIAccessor _diCassetteExist = null; public DOAccessor DoUnloadEnable = null; public DOAccessor DoStartRun = null; public DOAccessor DoPortLock = null; public DOAccessor DoLoadEnable = null; public DOAccessor DoHomeEnable = null; private SerialPortEx _serialPort; public bool IsConnected => _serialPort != null ? _serialPort.IsOpen : false; private R_TRIG _trigger = new R_TRIG(); public string Delimiter => _serialPort?.Delimiter; private readonly object _locker = new object(); private ConcurrentQueue _actionQueue = new ConcurrentQueue(); public SMIFBase() { } public SMIFBase(string module, string name) { Module = module; Name = name; } public virtual bool Initialize() { IsInstalled = SC.GetValue($"System.SetUp.Is{Module}Installed"); if(IsInstalled ) { InitSerialPort(); } return true; } private void InitSerialPort() { try { string portName = string.Empty; if (string.IsNullOrEmpty(_scRoot)) { portName = SC.GetStringValue($"{Name}.PortName"); _enableLog = SC.GetValue($"{Name}.EnableLogMessage"); } else { portName = SC.GetStringValue($"{_scRoot}.{Module}.{Name}.PortName"); _enableLog = SC.GetValue($"{_scRoot}.{Module}.{Name}.EnableLogMessage"); } _serialPort = new SerialPortEx(portName); _serialPort.Delimiter = "\r\n"; _serialPort.OnReceivedEvent += OnReceived; _serialPort.Connect(); } catch (Exception ex) { EV.PostAlarmLog(Module, $"{Module} connect IP:{_serialPort.PortName} failed"); LOG.Error(ex.Message, ex); } } public virtual void OnReceived(string msg) { } protected void AddActionToQueue(string msg) { if (IsConnected) _actionQueue.Enqueue(msg); } protected void ClearCmdQueue() { lock (_locker) { //ConcurrentQueue是线程安全的,所以它不会暴露或提供Clear方法清空 while (_actionQueue.TryDequeue(out _)) { } } } protected override void HandleMonitor() { if(!IsInstalled) { return; } //断连后将指令队列清空 _trigger.CLK = !_serialPort.IsOpen; if (_trigger.Q) { ClearCmdQueue(); EV.PostAlarmLog(Module, $"{_serialPort.PortName} Disconnected!"); } lock (_locker) { //连接成功 && SMIF不是Alarm && SMIF 空闲状态 if (_serialPort != null && _serialPort.IsOpen /*&& IsSMIFReady*/ && IsDone) { if (_actionQueue.Count > 0 && _actionQueue.TryDequeue(out string msg)) { IsDone = false; SendMessage(msg); } } } } private void SendMessage(string msg) { try { if (IsConnected) { _serialPort.Send(msg); if (!msg.StartsWith("FSR")) EV.PostInfoLog(Module, $"向{Name}发送指令:{msg.Replace("\r", "").Replace("\n", "")}"); } } catch (Exception ex) { LOG.Error(ex.Message); } } public virtual void Reset() { _serialPort?.Reset(); } public virtual void Terminate() { _serialPort?.Close(); } } }