218 lines
5.5 KiB
C#
218 lines
5.5 KiB
C#
|
|
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<string> _actionQueue = new ConcurrentQueue<string>();
|
|||
|
|
|
|||
|
|
public SMIFBase()
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public SMIFBase(string module, string name)
|
|||
|
|
{
|
|||
|
|
Module = module;
|
|||
|
|
Name = name;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public virtual bool Initialize()
|
|||
|
|
{
|
|||
|
|
IsInstalled = SC.GetValue<bool>($"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<bool>($"{Name}.EnableLogMessage");
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
portName = SC.GetStringValue($"{_scRoot}.{Module}.{Name}.PortName");
|
|||
|
|
_enableLog = SC.GetValue<bool>($"{_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<T>是线程安全的,所以它不会暴露或提供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();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|