using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Collections; using CyberX8_Core; using CyberX8_RT.Modules; using MECF.Framework.Common.CommonData; using MECF.Framework.Common.Equipment; using MECF.Framework.Common.SubstrateTrackings; using Aitex.Sorter.Common; using Aitex.Core.Common; using Aitex.Core.RT.SCCore; using Aitex.Core.RT.Log; using Aitex.Core.Util; using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Robot; using CyberX8_RT.Devices.YASKAWA; using System.Collections.Concurrent; using System.Diagnostics; using System.Data.SqlTypes; using System.Windows.Media.Media3D; using System.ComponentModel; namespace CyberX8_RT.Devices.EFEM { public class SunWayEfem : EfemBase { #region 常量 private const string NONE = "None"; #endregion private RState _status; private bool _IsHomed; private bool _bIsUnloadClamp; private RobotMoveInfo _robotMoveInfo = new RobotMoveInfo(); private readonly Loadport[] _LPMs = new Loadport[3]; private readonly SignalTower _signalT = new SignalTower(); private readonly AsyncSocket _socket; private EfemMessage _currentMsg; private EfemMessage _revMsg; private string _error; private bool _LiftIsUp = false; private bool _LiftIsDown = false; private R_TRIG _busyTrig = new R_TRIG(); private Stopwatch _busyWatch = new Stopwatch(); private bool _isComm; public override RState Status { get { _busyTrig.CLK = _status == RState.Running; if (_busyTrig.Q) { _busyWatch.Restart(); } else if (_busyTrig.M) { int timeOut = 5000; if(_currentMsg.Operation==EfemOperation.Home||_currentMsg.Operation==EfemOperation.Load|| _currentMsg.Operation==EfemOperation.Map) { timeOut = 30000; } if (_busyWatch.ElapsedMilliseconds > timeOut) { _busyWatch.Stop(); _status = RState.Timeout; } } return _status; } } public override bool IsHomed { get { return _IsHomed; } } public override RobotMoveInfo TMRobotMoveInfo { get { return _robotMoveInfo; } } public override ILoadport this[ModuleName mod] { get { if (!ModuleHelper.IsLoadPort(mod)) throw new ApplicationException($"{mod} is NOT Loadport"); return _LPMs[mod - ModuleName.LP1]; } } public override bool LiftIsUp { get { return _LiftIsUp; } } public override bool LiftIsDown { get { return _LiftIsDown; } } private BlockingCollection blockingCollection = new BlockingCollection(); private string _address = ""; public SunWayEfem() { _socket = new AsyncSocket("","\r",DataType.Ascii,true); try { _address = SC.GetStringValue($"EFEM.IPAddress"); _socket.Connect(_address); _socket.OnConnect += Socket_OnConnect; _socket.OnDataChanged += OnReceiveMessage; _socket.OnErrorHappened += OnErrorHappen; } catch(Exception ex) { LOG.WriteLog(eEvent.ERR_EFEM_COMMON_FAILED, "EFEM", ex.Message); } _status = RState.Init; _IsHomed = false; _busyTrig.RST = true; _isComm = false; _LPMs[0] = new Loadport(ModuleName.LP1, this); _LPMs[1] = new Loadport(ModuleName.LP2, this); _LPMs[2] = new Loadport(ModuleName.LP3, this); CarrierManager.Instance.SubscribeLocation(ModuleName.LP1.ToString(), 1); CarrierManager.Instance.SubscribeLocation(ModuleName.LP2.ToString(), 1); CarrierManager.Instance.SubscribeLocation(ModuleName.LP3.ToString(), 1); WaferManager.Instance.SubscribeLocation(ModuleName.EfemRobot, 2); WaferManager.Instance.SubscribeLocation(ModuleName.Aligner1, 1); WaferManager.Instance.SubscribeLocation(ModuleName.LP1, SC.GetValue("EFEM.LoadPort.SlotNumber")); WaferManager.Instance.SubscribeLocation(ModuleName.LP2, SC.GetValue("EFEM.LoadPort.SlotNumber")); WaferManager.Instance.SubscribeLocation(ModuleName.LP3, SC.GetValue("EFEM.LoadPort.SlotNumber")); Task.Run(() => { foreach (var data in blockingCollection.GetConsumingEnumerable()) { _robotMoveInfo.Action = data.Action; _robotMoveInfo.ArmTarget = data.Hand == Hand.Blade1 ? RobotArm.ArmA : (data.Hand == Hand.Both ? RobotArm.Both : RobotArm.ArmB); _robotMoveInfo.BladeTarget = $"{_robotMoveInfo.ArmTarget}.{data.Target}"; System.Threading.Thread.Sleep(600); } }); } private void Socket_OnConnect() { LOG.WriteBackgroundLog(eEvent.EV_EFEM_COMMON_INFO, Module.ToString(), $"connect {_address} success"); } public override void Monitor() { } public override void Terminate() { } public override void Reset() { _status = RState.End; } public override void SetOnline(bool online) { } public override void SetOnline(ModuleName mod, bool online) { } public override void SetBusy(ModuleName mod, bool online) { _status = RState.Running; } public override bool HomeAll() { if (_status == RState.Running&&_currentMsg!=null) { LOG.WriteLog(eEvent.ERR_EFEM_COMMON_FAILED, Module.ToString(), $"Current Msg {_currentMsg.Operation} is Running,cannot home All"); return false; } //判断socket是否链接 if (!_socket.IsConnected) { LOG.WriteLog(eEvent.ERROR_EFEM_COMMUNICATION, Module.ToString(), $"Socket is not Conntected"); return false ; } //判断机台是否准备就绪 if (!_isComm) { LOG.WriteLog(eEvent.ERROR_EFEM_NOREADY, Module.ToString(), "No \"CommReady\" Message Received,Cannot Execute Action"); return false; } _currentMsg = new EfemMessage { Module = ModuleName.EFEM, Operation = EfemOperation.Home, Head = EfemMessage.MsgHead.MOV, Parameters = new List { SunWayMessageHandler.Instance.ModuleString[ModuleName.EFEM] } }; _status = RState.Running; string data = _currentMsg.ToString(); SetRobotMovingInfo(RobotAction.Homing, Hand.Both, ModuleName.EFEM); return _socket.Write(data); } public override bool Home(ModuleName mod) { if (_status == RState.Running && _currentMsg != null) { LOG.WriteLog(eEvent.ERR_EFEM_COMMON_FAILED, Module.ToString(), $"Current Msg {_currentMsg.Operation} is Running,cannot home {mod}"); return false; } //判断socket是否链接 if (!_socket.IsConnected) { LOG.WriteLog(eEvent.ERROR_EFEM_COMMUNICATION, Module.ToString(), $"Socket is not Conntected"); return false; } //判断机台是否准备就绪 if (!_isComm) { LOG.WriteLog(eEvent.ERROR_EFEM_NOREADY, Module.ToString(), "No \"CommReady\" Message Received,Cannot Execute Action"); return false; } _currentMsg = new EfemMessage { Module = mod, Operation = EfemOperation.Home, Head = EfemMessage.MsgHead.MOV, Parameters = new List { SunWayMessageHandler.Instance.ModuleString[mod] } }; if(mod == ModuleName.EfemRobot) SetRobotMovingInfo(RobotAction.Homing, Hand.Blade1, ModuleName.EfemRobot); _status = RState.Running; return _socket.Write(_currentMsg.ToString()); } public override bool OriginalSearch(ModuleName mod) { return true; } public override bool CheckWaferPresence() { if (!CheckEfemStatus()) return false; _currentMsg = new EfemMessage { Module = ModuleName.EFEM, Operation = EfemOperation.StateTrack, Head = EfemMessage.MsgHead.GET, Parameters = new List { "TRACK" } }; _status = RState.Running; return _socket.Write(_currentMsg.ToString()); } public override string GetWaferPresence() { return ""; } public override bool Halt() { //判断socket是否链接 if (!_socket.IsConnected) { LOG.WriteLog(eEvent.ERROR_EFEM_COMMUNICATION, Module.ToString(), $"Socket is not Conntected"); return false; } _currentMsg = new EfemMessage { Module = ModuleName.EFEM, Operation = EfemOperation.Abort, Head = EfemMessage.MsgHead.MOV, }; return _socket.Write(_currentMsg.ToString()); } public override bool ClearError() { //判断机台是否准备就绪 if (!_isComm) { LOG.WriteLog(eEvent.ERROR_EFEM_NOREADY, Module.ToString(), "No \"CommReady\" Message Received,Cannot Execute Action"); return false; } //判断socket是否链接 if (!_socket.IsConnected) { LOG.WriteLog(eEvent.ERROR_EFEM_COMMUNICATION, Module.ToString(), $"Socket is not Conntected"); return false; } _currentMsg = new EfemMessage { Module = ModuleName.EFEM, Operation = EfemOperation.ClearError, Head = EfemMessage.MsgHead.SET, Parameters = new List { "CLEAR" } }; _status = RState.Running; return _socket.Write(_currentMsg.ToString()); } public override bool CloseBuzzer() { //判断机台是否准备就绪 if (!_isComm) { LOG.WriteLog(eEvent.ERROR_EFEM_NOREADY, Module.ToString(), "No \"CommReady\" Message Received,Cannot Execute Action"); return false; } //判断socket是否链接 if (!_socket.IsConnected) { LOG.WriteLog(eEvent.ERROR_EFEM_COMMUNICATION, Module.ToString(), $"Socket is not Conntected"); return false; } _currentMsg = new EfemMessage { Module = ModuleName.EFEM, Operation = EfemOperation.Light, Head = EfemMessage.MsgHead.SET, Parameters = new List { Constant.STOWER, LightType.BUZZER1.ToString(), "OFF" } }; _status = RState.Running; return _socket.Write(_currentMsg.ToString()); } public override bool PickExtend(ModuleName chamber, int slot, Hand hand) { LOG.WriteLog(eEvent.ERR_EFEM_COMMON_FAILED, Module.ToString(), $"System cannot support {EfemConstant.OperationString[EfemOperation.Extend]}"); return false; } public override bool PickRetract(ModuleName chamber, int slot, Hand hand) { LOG.WriteLog(eEvent.ERR_EFEM_COMMON_FAILED, Module.ToString(), $"System cannot support {EfemConstant.OperationString[EfemOperation.Extend]}"); return false; } public override bool PlaceExtend(ModuleName chamber, int slot, Hand hand) { LOG.WriteLog(eEvent.ERR_EFEM_COMMON_FAILED, Module.ToString(), $"System cannot support {EfemConstant.OperationString[EfemOperation.Extend]}"); return false; } public override bool PlaceRetract(ModuleName chamber, int slot, Hand hand) { LOG.WriteLog(eEvent.ERR_EFEM_COMMON_FAILED, Module.ToString(), $"System cannot support {EfemConstant.OperationString[EfemOperation.Extend]}"); return false; } public override bool GotoMap(ModuleName mod, Hand hand,string extend="EX") { LOG.WriteLog(eEvent.ERR_EFEM_COMMON_FAILED, Module.ToString(), $"System cannot support GotoMap"); return false; } public override bool RequestMapResult(ModuleName mod) { LOG.WriteLog(eEvent.ERR_EFEM_COMMON_FAILED, Module.ToString(), $"System cannot support RequestMapResult"); return false; } public override bool Pick(ModuleName station, int slot, Hand hand) { //判断机台是否准备就绪 if (!_isComm) { LOG.WriteLog(eEvent.ERROR_EFEM_NOREADY, Module.ToString(), "No \"CommReady\" Message Received,Cannot Execute Action"); return false; } //判断socket是否链接 if (!_socket.IsConnected) { LOG.WriteLog(eEvent.ERROR_EFEM_COMMUNICATION, Module.ToString(), $"Socket is not Conntected"); return false; } //判断Loadport的门是否打开 if (ModuleHelper.IsLoadPort(station) && !_LPMs[station - ModuleName.LP1].IsDoorOpened) { LOG.WriteLog(eEvent.ERR_EFEM_COMMON_FAILED, Module.ToString(), $"{station}'s Door is Closed, Cannot Execute Pick Action"); return false; } if (!CheckEfemStatus()) return false; Position SrcPos = new Position { Module = station, Slot = (byte)slot }; _currentMsg = new EfemMessage { Operation = EfemOperation.Pick, Head = EfemMessage.MsgHead.MOV, Parameters = new List { SunWayMessageHandler.Instance.ToHWString(SrcPos), SunWayMessageHandler.Instance.ArmString[hand] } }; _status = RState.Running; SetRobotMovingInfo(RobotAction.Picking, hand, station); return _socket.Write(_currentMsg.ToString()); } public override bool Place(ModuleName station, int slot, Hand hand) { //判断机台是否准备就绪 if (!_isComm) { LOG.WriteLog(eEvent.ERROR_EFEM_NOREADY, Module.ToString(), "No \"CommReady\" Message Received,Cannot Execute Action"); return false; } //判断socket是否链接 if (!_socket.IsConnected) { LOG.WriteLog(eEvent.ERROR_EFEM_COMMUNICATION, Module.ToString(), $"Socket is not Conntected"); return false; } //判断Loadport的门是否打开 if (ModuleHelper.IsLoadPort(station) && !_LPMs[station - ModuleName.LP1].IsDoorOpened) { LOG.WriteLog(eEvent.ERR_EFEM_COMMON_FAILED, Module.ToString(), $"{station}'s Door is Closed, Cannot Execute Pick Action"); return false; } if (!CheckEfemStatus()) return false; Position DestPos = new Position { Module = station, Slot = (byte)slot }; _currentMsg = new EfemMessage { Operation = EfemOperation.Place, Head = EfemMessage.MsgHead.MOV, Parameters = new List { SunWayMessageHandler.Instance.ToHWString(DestPos), SunWayMessageHandler.Instance.ArmString[hand] } }; _status = RState.Running; SetRobotMovingInfo(RobotAction.Placing, hand, station); return _socket.Write(_currentMsg.ToString()); } public override bool Goto(ModuleName station, Hand hand, string updown = "UP") { if (!CheckEfemStatus()) return false; //判断socket是否链接 if (!_socket.IsConnected) { LOG.WriteLog(eEvent.ERROR_EFEM_COMMUNICATION, Module.ToString(), $"Socket is not Conntected"); return false; } Position DestPos = new Position { Module = station, Slot = (byte)0 }; _currentMsg = new EfemMessage { Operation = EfemOperation.Goto, Head = EfemMessage.MsgHead.MOV, Parameters = new List { SunWayMessageHandler.Instance.ToHWString(DestPos), SunWayMessageHandler.Instance.ArmString[hand], updown } }; _status = RState.Running; return _socket.Write(_currentMsg.ToString()); } public override bool Grip(Hand blade, bool isGrip) { LOG.WriteLog(eEvent.ERR_EFEM_COMMON_FAILED, Module.ToString(), $"System cannot support {EfemConstant.OperationString[EfemOperation.Grip]}"); return false; } public override bool Map(ModuleName mod) { //判断机台是否准备就绪 if (!_isComm) { LOG.WriteLog(eEvent.ERROR_EFEM_NOREADY, Module.ToString(), "No \"CommReady\" Message Received,Cannot Execute Action"); return false; } //判断socket是否链接 if (!_socket.IsConnected) { LOG.WriteLog(eEvent.ERROR_EFEM_COMMUNICATION, Module.ToString(), $"Socket is not Conntected"); return false; } if (!CheckEfemStatus()) return false; _currentMsg = new EfemMessage { Operation = EfemOperation.Map, Head = EfemMessage.MsgHead.MOV, Parameters = new List { SunWayMessageHandler.Instance.ModuleString[mod] } }; _status = RState.Running; return _socket.Write(_currentMsg.ToString()); } public override bool Vacuum(ModuleName mod,bool VacuumState) { //判断机台是否准备就绪 if (!_isComm) { LOG.WriteLog(eEvent.ERROR_EFEM_NOREADY, Module.ToString(), "No \"CommReady\" Message Received,Cannot Execute Action"); return false; } //判断socket是否链接 if (!_socket.IsConnected) { LOG.WriteLog(eEvent.ERROR_EFEM_COMMUNICATION, Module.ToString(), $"Socket is not Conntected"); return false; } string strVacuum = VacuumState ? "ON" : "OFF"; _currentMsg = new EfemMessage { Operation = EfemOperation.Vacuum, Head = EfemMessage.MsgHead.MOV, Parameters = new List { SunWayMessageHandler.Instance.ModuleString[mod],strVacuum } }; _status = RState.Running; return _socket.Write(_currentMsg.ToString()); } public override bool GetWaferSize(ModuleName mod) { if (!CheckEfemStatus()) return false; //判断机台是否准备就绪 if (!_isComm) { LOG.WriteLog(eEvent.ERROR_EFEM_NOREADY, Module.ToString(), "No \"CommReady\" Message Received,Cannot Execute Action"); return false; } //判断socket是否链接 if (!_socket.IsConnected) { LOG.WriteLog(eEvent.ERROR_EFEM_COMMUNICATION, Module.ToString(), $"Socket is not Conntected"); return false; } _currentMsg = new EfemMessage { Operation = EfemOperation.Size, Head = EfemMessage.MsgHead.GET, Parameters = new List { SunWayMessageHandler.Instance.ModuleString[mod] } }; _status = RState.Running; return _socket.Write(_currentMsg.ToString()); } public override bool SetWaferSize(ModuleName mod, int WaferSize) { if (!CheckEfemStatus()) return false; //判断机台是否准备就绪 if (!_isComm) { LOG.WriteLog(eEvent.ERROR_EFEM_NOREADY, Module.ToString(), "No \"CommReady\" Message Received,Cannot Execute Action"); return false; } //判断socket是否链接 if (!_socket.IsConnected) { LOG.WriteLog(eEvent.ERROR_EFEM_COMMUNICATION, Module.ToString(), $"Socket is not Conntected"); return false; } _currentMsg = new EfemMessage { Operation = EfemOperation.Size, Head = EfemMessage.MsgHead.SET, Parameters = new List { SunWayMessageHandler.Instance.ModuleString[mod], WaferSize.ToString() } }; _status = RState.Running; return _socket.Write(_currentMsg.ToString()); } public override bool SetPinUp(ModuleName mod) { LOG.WriteLog(eEvent.ERR_EFEM_COMMON_FAILED, Module.ToString(), $"System cannot support {EfemConstant.OperationString[EfemOperation.Lift]}"); return false; } public override bool SetPinDown(ModuleName mod) { LOG.WriteLog(eEvent.ERR_EFEM_COMMON_FAILED, Module.ToString(), $"System cannot support {EfemConstant.OperationString[EfemOperation.Lift]}"); return false; } public override bool SetAlignAngle(ModuleName mod, double angle) { if (!CheckEfemStatus()) return false; //判断机台是否准备就绪 if (!_isComm) { LOG.WriteLog(eEvent.ERROR_EFEM_NOREADY, Module.ToString(), "No \"CommReady\" Message Received,Cannot Execute Action"); return false; } //判断socket是否链接 if (!_socket.IsConnected) { LOG.WriteLog(eEvent.ERROR_EFEM_COMMUNICATION, Module.ToString(), $"Socket is not Conntected"); return false; } _currentMsg = new EfemMessage { Operation = EfemOperation.Align, Head = EfemMessage.MsgHead.SET, Parameters = new List { SunWayMessageHandler.Instance.ModuleString[mod], angle.ToString("000.00") } }; _status = RState.Running; return _socket.Write(_currentMsg.ToString()); } public override bool SetRobotSpeed(ModuleName mod, int speed) { if (!CheckEfemStatus()) return false; //判断机台是否准备就绪 if (!_isComm) { LOG.WriteLog(eEvent.ERROR_EFEM_NOREADY, Module.ToString(), "No \"CommReady\" Message Received,Cannot Execute Action"); return false; } //判断socket是否链接 if (!_socket.IsConnected) { LOG.WriteLog(eEvent.ERROR_EFEM_COMMUNICATION, Module.ToString(), $"Socket is not Conntected"); return false; } _currentMsg = new EfemMessage { Operation = EfemOperation.Speed, Head = EfemMessage.MsgHead.SET, Parameters = new List { SunWayMessageHandler.Instance.ModuleString[mod], speed.ToString() } }; _status = RState.Running; return _socket.Write(_currentMsg.ToString()); } public override bool RobotPowerOn(ModuleName mod, bool Status) { //判断机台是否准备就绪 if (!_isComm) { LOG.WriteLog(eEvent.ERROR_EFEM_NOREADY, Module.ToString(), "No \"CommReady\" Message Received,Cannot Execute Action"); return false; } //判断socket是否链接 if (!_socket.IsConnected) { LOG.WriteLog(eEvent.ERROR_EFEM_COMMUNICATION, Module.ToString(), $"Socket is not Conntected"); return false; } if (!CheckEfemStatus()) return false; string status = "ON"; if (!Status) { status = "OFF"; } _currentMsg = new EfemMessage { Operation = EfemOperation.PowerOn, Head = EfemMessage.MsgHead.MOV, Parameters = new List { SunWayMessageHandler.Instance.ModuleString[mod], status } }; _status = RState.Running; return _socket.Write(_currentMsg.ToString()); } public override bool Align(ModuleName mod, double angle, float delayTime, WaferSize size) { //判断机台是否准备就绪 if (!_isComm) { LOG.WriteLog(eEvent.ERROR_EFEM_NOREADY, Module.ToString(), "No \"CommReady\" Message Received,Cannot Execute Action"); return false; } //判断socket是否链接 if (!_socket.IsConnected) { LOG.WriteLog(eEvent.ERROR_EFEM_COMMUNICATION, Module.ToString(), $"Socket is not Conntected"); return false; } if (!CheckEfemStatus()) return false; _currentMsg = new EfemMessage { Operation = EfemOperation.Align, Head = EfemMessage.MsgHead.MOV, Parameters = new List { SunWayMessageHandler.Instance.ModuleString[mod] } }; _status = RState.Running; return _socket.Write(_currentMsg.ToString()); } public override bool SetLamp(LightType light, LightStatus status) { if (!_isComm) { return false; } //判断socket是否链接 if (!_socket.IsConnected) { return false; } EfemMessage currentMsg = new EfemMessage { Module = ModuleName.EFEM, Operation = EfemOperation.Light, Head = EfemMessage.MsgHead.SET, Parameters = new List { Constant.STOWER, light.ToString(), status.ToString() } }; return _socket.Write(currentMsg.ToString()); } public override bool Load(ModuleName mod) { //判断机台是否准备就绪 if (!_isComm) { LOG.WriteLog(eEvent.ERROR_EFEM_NOREADY, Module.ToString(), "No \"CommReady\" Message Received,Cannot Execute Action"); return false; } //判断socket是否链接 if (!_socket.IsConnected) { LOG.WriteLog(eEvent.ERROR_EFEM_COMMUNICATION, Module.ToString(), $"Socket is not Conntected"); return false; } if (!CheckEfemStatus()) return false; _currentMsg = new EfemMessage { Module = mod, Operation = EfemOperation.Load, Head = EfemMessage.MsgHead.MOV, Parameters = new List { SunWayMessageHandler.Instance.ModuleString[mod] } }; _status = RState.Running; return _socket.Write(_currentMsg.ToString()); } public override bool Unload(ModuleName mod) { //判断机台是否准备就绪 if (!_isComm) { LOG.WriteLog(eEvent.ERROR_EFEM_NOREADY, Module.ToString(), "No \"CommReady\" Message Received,Cannot Execute Action"); return false; } //判断socket是否链接 if (!_socket.IsConnected) { LOG.WriteLog(eEvent.ERROR_EFEM_COMMUNICATION, Module.ToString(), $"Socket is not Conntected"); return false; } if (!CheckEfemStatus()) return false; _currentMsg = new EfemMessage { Module = mod, Operation = EfemOperation.Unload, Head = EfemMessage.MsgHead.MOV, Parameters = new List { SunWayMessageHandler.Instance.ModuleString[mod] } }; _status = RState.Running; return _socket.Write(_currentMsg.ToString()); } public override bool ReadCarrierId(ModuleName mod) { //判断机台是否准备就绪 if (!_isComm) { LOG.WriteLog(eEvent.ERROR_EFEM_NOREADY, Module.ToString(), "No \"CommReady\" Message Received,Cannot Execute Action"); return false; } //判断socket是否链接 if (!_socket.IsConnected) { LOG.WriteLog(eEvent.ERROR_EFEM_COMMUNICATION, Module.ToString(), $"Socket is not Conntected"); return false; } if (!CheckEfemStatus()) return false; _currentMsg = new EfemMessage { Module = mod, Operation = EfemOperation.CarrierId, Head = EfemMessage.MsgHead.GET, Parameters = new List { SunWayMessageHandler.Instance.ModuleString[mod] } }; _status = RState.Running; return _socket.Write(_currentMsg.ToString()); } public override bool WriteCarrierId(ModuleName mod, string id) { if (!CheckEfemStatus()) return false; //判断机台是否准备就绪 if (!_isComm) { LOG.WriteLog(eEvent.ERROR_EFEM_NOREADY, Module.ToString(), "No \"CommReady\" Message Received,Cannot Execute Action"); return false; } //判断socket是否链接 if (!_socket.IsConnected) { LOG.WriteLog(eEvent.ERROR_EFEM_COMMUNICATION, Module.ToString(), $"Socket is not Conntected"); return false; } _currentMsg = new EfemMessage { Module = mod, Operation = EfemOperation.CarrierId, Head = EfemMessage.MsgHead.SET, Parameters = new List { SunWayMessageHandler.Instance.ModuleString[mod], id } }; _status = RState.Running; return _socket.Write(_currentMsg.ToString()); } public override bool ReadTagData(ModuleName mod) { return ReadCarrierId(mod); } public override bool WriteTagData(ModuleName mod, string tagData) { return WriteCarrierId(mod, tagData); } public override bool Dock(ModuleName mod) { //判断机台是否准备就绪 if (!_isComm) { LOG.WriteLog(eEvent.ERROR_EFEM_NOREADY, Module.ToString(), "No \"CommReady\" Message Received,Cannot Execute Action"); return false; } //判断socket是否链接 if (!_socket.IsConnected) { LOG.WriteLog(eEvent.ERROR_EFEM_COMMUNICATION, Module.ToString(), $"Socket is not Conntected"); return false; } if (!CheckEfemStatus()) return false; _currentMsg = new EfemMessage { Module = mod, Operation = EfemOperation.Dock, Head = EfemMessage.MsgHead.MOV, Parameters = new List { SunWayMessageHandler.Instance.ModuleString[mod] } }; _status = RState.Running; return _socket.Write(_currentMsg.ToString()); } public override bool Undock(ModuleName mod) { //判断机台是否准备就绪 if (!_isComm) { LOG.WriteLog(eEvent.ERROR_EFEM_NOREADY, Module.ToString(), "No \"CommReady\" Message Received,Cannot Execute Action"); return false; } //判断socket是否链接 if (!_socket.IsConnected) { LOG.WriteLog(eEvent.ERROR_EFEM_COMMUNICATION, Module.ToString(), $"Socket is not Conntected"); return false; } if (!CheckEfemStatus()) return false; _currentMsg = new EfemMessage { Module = mod, Operation = EfemOperation.Undock, Head = EfemMessage.MsgHead.MOV, Parameters = new List { SunWayMessageHandler.Instance.ModuleString[mod] } }; _status = RState.Running; return _socket.Write(_currentMsg.ToString()); } public override bool Clamp(ModuleName mod, bool isUnloadClamp) { //判断机台是否准备就绪 if (!_isComm) { LOG.WriteLog(eEvent.ERROR_EFEM_NOREADY, Module.ToString(), "No \"CommReady\" Message Received,Cannot Execute Action"); return false; } //判断socket是否链接 if (!_socket.IsConnected) { LOG.WriteLog(eEvent.ERROR_EFEM_COMMUNICATION, Module.ToString(), $"Socket is not Conntected"); return false; } if (!CheckEfemStatus()) return false; _currentMsg = new EfemMessage { Module = mod, Operation = EfemOperation.Clamp, Head = EfemMessage.MsgHead.MOV, Parameters = new List { SunWayMessageHandler.Instance.ModuleString[mod] } }; _status = RState.Running; _bIsUnloadClamp = isUnloadClamp; return _socket.Write(_currentMsg.ToString()); } public override bool Unclamp(ModuleName mod) { //判断机台是否准备就绪 if (!_isComm) { LOG.WriteLog(eEvent.ERROR_EFEM_NOREADY, Module.ToString(), "No \"CommReady\" Message Received,Cannot Execute Action"); return false; } //判断socket是否链接 if (!_socket.IsConnected) { LOG.WriteLog(eEvent.ERROR_EFEM_COMMUNICATION, Module.ToString(), $"Socket is not Conntected"); return false; } if (!CheckEfemStatus()) return false; _currentMsg = new EfemMessage { Module = mod, Operation = EfemOperation.Unclamp, Head = EfemMessage.MsgHead.MOV, Parameters = new List { SunWayMessageHandler.Instance.ModuleString[mod] } }; _status = RState.Running; return _socket.Write(_currentMsg.ToString()); } public override bool SetThickness(ModuleName mod, string thickness) { LOG.WriteLog(eEvent.ERR_EFEM_COMMON_FAILED, Module.ToString(), $"System cannot support {EfemConstant.OperationString[EfemOperation.SetThickness]}"); return false; } public override void SetRobotMovingInfo(RobotAction action, Hand hand, ModuleName target) { blockingCollection.Add(new RobotAnimationData(action, hand, target)); } private void OnReceiveMessage(string RevMsg) { LOG.WriteBackgroundLog(eEvent.EV_EFEM_COMMON_INFO, Module.ToString(), RevMsg.Replace("\r","")); if (!_isComm) { //检验是否收到CommReady信号 if (RevMsg.IndexOf("COMM", StringComparison.OrdinalIgnoreCase) >= 0) { _isComm = true; } } string[] msgs = RevMsg.Split('\r'); foreach (var msg in msgs) { if (string.IsNullOrWhiteSpace(msg)) continue; EfemMessage rec_msg = SunWayMessageHandler.Instance.ToMessage(msg); switch (rec_msg.Head) { case EfemMessage.MsgHead.ACK: if (msg.Contains("ERROR")) { _revMsg = rec_msg; } break; case EfemMessage.MsgHead.INF: // 收到INF之后发送ACK确认 string strACK = rec_msg.RawString.Replace("INF", "ACK"); SendBack(strACK); LOG.WriteBackgroundLog(eEvent.EV_EFEM_COMMON_INFO, Module.ToString(), strACK); //提示当前机械臂速度设置情况 if (strACK.Contains("SPEED")) { string[] SpeedInf = rec_msg.RawString.Split('/'); LOG.Write(eEvent.INFO_PROCESS, ModuleName.Robot, $"Robot Speed is {SpeedInf[SpeedInf.Length-1]}"); } //提示当前机械臂电源情况 if (strACK.Contains("SERVOS")) { string[] PowerInf = rec_msg.RawString.Split('/'); LOG.Write(eEvent.INFO_PROCESS, ModuleName.Robot, $"Robot Power is {PowerInf[PowerInf.Length - 1]}"); } EfemMessage ack_msg = SunWayMessageHandler.Instance.ToMessage(strACK); ack_msg.Direct = MsgDirection.To; _revMsg = rec_msg; OnCommandUpdated(rec_msg); SetRobotMovingInfo(RobotAction.None, Hand.Both, ModuleName.EfemRobot); break; case EfemMessage.MsgHead.EVT: OnEventUpdated(new EfemEventArgs { EvtStr = rec_msg.ToParamString(), Module = rec_msg.Module, CommandType = rec_msg.Operation, DataList = rec_msg.Data }); if (rec_msg.Operation == EfemOperation.Home) { SetRobotMovingInfo(RobotAction.Homing, Hand.Both, ModuleName.EFEM); } if (rec_msg.Operation == EfemOperation.Error) { OnErrorOccurred(rec_msg); } break; case EfemMessage.MsgHead.NAK: case EfemMessage.MsgHead.CAN: case EfemMessage.MsgHead.ABS: OnErrorOccurred(rec_msg); break; } } } private void OnErrorHappen(ErrorEventArgs args) { _status = RState.Failed; if(_error!=args.Reason) { _error=args.Reason; LOG.Write(eEvent.ERR_EFEM_COMMON_FAILED, Module, $"{Module} {_error}"); } Singleton.Instance.EFEM.PostMsg(EfemEntity.MSG.Error); } private void OnErrorOccurred(EfemMessage message) { string description = string.Empty; string str = ""; switch (message.Head) { case EfemMessage.MsgHead.NAK: description = Constant.SunWayFactorString.ContainsKey(message.Factor) ? Constant.SunWayFactorString[message.Factor]:message.Factor; break; case EfemMessage.MsgHead.CAN: description = Constant.SunWayFactorString.ContainsKey(message.Factor) ? Constant.SunWayFactorString[message.Factor] : message.Factor; str = message.Data.Count != 0 ? message.Data[0] : ""; break; case EfemMessage.MsgHead.ABS: description = message.Factor; str = message.Data.Count != 0 ? String.Join(" ", message.Data.ToArray()):""; break; case EfemMessage.MsgHead.EVT: str= message.Data.Count != 0 ? String.Join(" ", message.Data.ToArray()) : ""; break; } _status = RState.Failed; Singleton.Instance.EFEM.PostMsg(EfemEntity.MSG.Error,description); if (message.Head == EfemMessage.MsgHead.NAK || message.Head == EfemMessage.MsgHead.CAN) { eEvent eEvent = GetFactorEventId(message.Factor); LOG.Write(eEvent, ModuleName.EFEM, $"{description}, [{str}]"); } else { LOG.Write(eEvent.ERR_EFEM_COMMON_FAILED, ModuleName.EFEM, $"{description}, [{str}]"); } } /// /// 根据Factor获取相应的eEventId /// /// /// private eEvent GetFactorEventId(string factor) { string str = $"ERR_EFEM_{factor}"; if(Enum.TryParse(str,out eEvent result)) { return result; } else { return eEvent.ERR_EFEM_COMMON_FAILED; } } private void OnEventUpdated(EfemEventArgs eArg) { switch (eArg.CommandType) { case EfemOperation.SigStatus: // EVT:SIGSTAT/Parameter/DATA1/DATA2; string sParam = eArg.DataList[0]; // DATA1 & DATA2 int nData1 = Convert.ToInt32(eArg.DataList[1], 16); int nData2 = Convert.ToInt32(eArg.DataList[2], 16); BitArray baData1 = new BitArray(new int[] { nData1 }); BitArray baData2 = new BitArray(new int[] { nData2 }); if (0 == string.Compare(sParam, Constant.SYS, true)) { // EVT:SIGSTAT/System/00000000/00000004; // DATA1 if (!baData1[0]) // Bit[0] ON=Normal, OFF=Abnormal { string error = "EFEM Door is OFF Alarm"; LOG.Write(eEvent.ERR_EFEM_COMMON_FAILED, ModuleName.EFEM, error); Singleton.Instance.EFEM.PostMsg(EfemEntity.MSG.Error,error); } if (!baData1[1]) // Bit[0] ON=Normal, OFF=Abnormal { string error = "EFEM Vacuum Detection is OFF Alarm"; LOG.Write(eEvent.ERR_EFEM_COMMON_FAILED, ModuleName.EFEM, error); Singleton.Instance.EFEM.PostMsg(EfemEntity.MSG.Error, error); } if (!baData1[2]) // Bit[2] ON=Normal, OFF=Abnormal { string error = "EFEM Air Detection is OFF Alarm"; LOG.Write(eEvent.ERR_EFEM_COMMON_FAILED, ModuleName.EFEM, error); Singleton.Instance.EFEM.PostMsg(EfemEntity.MSG.Error,error); } if (!baData1[3]) // Bit[3] ON=Normal, OFF=Abnormal { string error = "EFEM OnlineMode is OFF Alarm"; LOG.Write(eEvent.ERR_EFEM_COMMON_FAILED, ModuleName.EFEM, error); Singleton.Instance.EFEM.PostMsg(EfemEntity.MSG.Error,error); } if (baData1[4]) // Bit[4] ON=Abnormal, OFF=Normal { string error = "EFEM MaintenanceMode is ON Alarm"; LOG.Write(eEvent.ERR_EFEM_COMMON_FAILED, ModuleName.EFEM, error); Singleton.Instance.EFEM.PostMsg(EfemEntity.MSG.Error, error); } if (baData1[5]) // Bit[5] ON=Abnormal, OFF=Normal { string error = "EFEM System Wafer Stick-out1 Alarm"; LOG.Write(eEvent.ERR_EFEM_COMMON_FAILED, ModuleName.EFEM, error); Singleton.Instance.EFEM.PostMsg(EfemEntity.MSG.Error, error); } if (baData1[6]) // Bit[6] ON=Abnormal, OFF=Normal { string error = "EFEM System Wafer Stick-out2 Alarm"; LOG.Write(eEvent.ERR_EFEM_COMMON_FAILED, ModuleName.EFEM, error); Singleton.Instance.EFEM.PostMsg(EfemEntity.MSG.Error,error); } if (baData1[7]) // Bit[7] ON=Abnormal, OFF=Normal { string error = "EFEM Emergency Stop Signal Alarm"; LOG.Write(eEvent.ERR_EFEM_COMMON_FAILED, ModuleName.EFEM,error); Singleton.Instance.EFEM.PostMsg(EfemEntity.MSG.Error,error); } // DATA2 _signalT.ChangeLightStatus(LightType.BUZZER1, baData2[0] ? LightStatus.ON : LightStatus.OFF); _signalT.ChangeLightStatus(LightType.BLUE, baData2[1] ? LightStatus.ON : LightStatus.OFF); _signalT.ChangeLightStatus(LightType.GREEN, baData2[2] ? LightStatus.ON : LightStatus.OFF); _signalT.ChangeLightStatus(LightType.YELLOW, baData2[3] ? LightStatus.ON : LightStatus.OFF); _signalT.ChangeLightStatus(LightType.RED, baData2[4] ? LightStatus.ON : LightStatus.OFF); _signalT.ChangeLightStatus(LightType.BLUE, baData2[6] ? LightStatus.BLINK : LightStatus.OFF); _signalT.ChangeLightStatus(LightType.GREEN, baData2[7] ? LightStatus.BLINK : LightStatus.OFF); _signalT.ChangeLightStatus(LightType.YELLOW, baData2[8] ? LightStatus.BLINK : LightStatus.OFF); _signalT.ChangeLightStatus(LightType.RED, baData2[9] ? LightStatus.BLINK : LightStatus.OFF); //屏蔽LP光栅信号 /* EFEM 程序中目前没有实现 _RobotErr.CLK = baData2[27]; // bit 27 bool bArmNotExtendLLA = baData2[30]; // bit 30 bool bArmNotExtendLLB = baData2[31]; // bit 31 */ } // system event else { // placement & present bool bPlacement = baData1[0]; // bit 0 bool bPresence = baData1[0]; // bit 1 bool bArrived = bPlacement && bPresence; _LPMs[eArg.Module - ModuleName.LP1].UpdateWaferArrive(bArrived); _LPMs[eArg.Module - ModuleName.LP1].IsClamped = baData1[1]; _LPMs[eArg.Module - ModuleName.LP1].IsDocked = baData1[2]; _LPMs[eArg.Module - ModuleName.LP1].IsDoorOpened = !baData1[5]; //_LPMs[eArg.Module - ModuleName.LP1].HandleEvent(eArg); } // FOUP EVENT break; case EfemOperation.GetWaferInfo: //MADPT //lp if (ModuleHelper.IsLoadPort(eArg.Module)) { _LPMs[eArg.Module - ModuleName.LP1].HandleEvent(eArg); } // BF else { MapBufferHandleEvent(eArg); } //buffer break; case EfemOperation.Align: //ALIGN MapBufferHandleEvent(eArg); break; default: break; } } public void MapBufferHandleEvent(EfemEventArgs eArg) { string sWaferInfo = eArg.DataList[0]; for (byte index = 0; index < sWaferInfo.Length; index++) { int waferState = int.Parse(sWaferInfo.Substring(index, 1)); //合理的映射到内部支持的叠片/交叉片 if (waferState >= 7) waferState = 7; else if (waferState >= 2) waferState = 3; WaferStatus st = (WaferStatus)waferState; if (st != WaferStatus.Empty) { WaferManager.Instance.CreateWafer(eArg.Module, index, st); } else { WaferManager.Instance.DeleteWafer(eArg.Module, index); } } } private void OnCommandUpdated(EfemMessage message) { try { switch (message.Operation) { case EfemOperation.ClearError: case EfemOperation.Align: case EfemOperation.Pick: case EfemOperation.Place: case EfemOperation.Extend: case EfemOperation.Goto: case EfemOperation.Orgsh: case EfemOperation.EmsStop: case EfemOperation.Abort: case EfemOperation.Speed: case EfemOperation.Vacuum: case EfemOperation.PowerOn: _status = RState.End; break; case EfemOperation.Map: if (ModuleHelper.IsLoadPort(message.Module)) { _LPMs[message.Module - ModuleName.LP1].OnMaped(); } _status = RState.End; break; case EfemOperation.StateTrack: { string str = message.Data.Count >= 1 ? message.Data.First() : string.Empty; if (str.ToLower() == "track") { string strA = message.Data.Count > 1 ? message.Data[1].ToString() : string.Empty; if (strA.ToLower() != NONE.ToLower()) { if (WaferManager.Instance.CheckNoWafer(ModuleName.EfemRobot, 0)) { WaferManager.Instance.CreateWafer(ModuleName.EfemRobot, 0, WaferStatus.Normal); } } string strB = message.Data.Count > 2 ? message.Data[2].ToString() : string.Empty; if (strB.ToLower() != NONE.ToLower()) { if (WaferManager.Instance.CheckNoWafer(ModuleName.EfemRobot, 1)) { WaferManager.Instance.CreateWafer(ModuleName.EfemRobot, 1, WaferStatus.Normal); } } } _status = RState.End; } break; case EfemOperation.Home: { if (_currentMsg.Module == ModuleName.EFEM) { _LPMs[0].OnHomed(); _LPMs[1].OnHomed(); _LPMs[2].OnHomed(); } else if (ModuleHelper.IsLoadPort(_currentMsg.Module)) { _LPMs[_currentMsg.Module - ModuleName.LP1].OnHomed(); } _status = RState.End; } break; case EfemOperation.Load: { _LPMs[message.Module - ModuleName.LP1].OnLoaded(); _status = RState.End; } break; case EfemOperation.Unload: { _LPMs[message.Module - ModuleName.LP1].OnUnloaded(); _status = RState.End; } break; case EfemOperation.CarrierId: { if (message.Head == EfemMessage.MsgHead.GET) { _LPMs[message.Module - ModuleName.LP1].OnCarrierIDRead(message.Data.First()); } else { _LPMs[message.Module - ModuleName.LP1].OnCarrierIDWrite(message.Data.First()); } _status = RState.End; } break; case EfemOperation.Clamp: { _LPMs[message.Module - ModuleName.LP1].OnClamped(_bIsUnloadClamp); _status = RState.End; } break; case EfemOperation.Unclamp: { _LPMs[message.Module - ModuleName.LP1].OnUnclamped(); _status = RState.End; } break; case EfemOperation.Dock: { _LPMs[message.Module - ModuleName.LP1].OnDocked(); _status = RState.End; } break; case EfemOperation.Undock: { _LPMs[message.Module - ModuleName.LP1].OnUndocked(); _status = RState.End; } break; case EfemOperation.Ready: { Singleton.Instance.EFEM.PostMsg(EfemEntity.MSG.CommReady); } break; case EfemOperation.Size: { if (message.Data.Count != 0) { if(ModuleHelper.IsLoadPort(message.Module)) { string waferSize = message.Data[0]; if (waferSize == "200") { _LPMs[message.Module - ModuleName.LP1].UpdateWaferSize(WaferSize.WS8); } else if (waferSize == "300") { _LPMs[message.Module - ModuleName.LP1].UpdateWaferSize(WaferSize.WS12); } else { _LPMs[message.Module - ModuleName.LP1].UpdateWaferSize(WaferSize.WS0); } } } _status = RState.End; } break; } } catch(Exception ex) { string error = $"OnCommandUpdated meets {ex.Message}"; LOG.WriteLog(eEvent.ERR_EFEM_COMMON_FAILED, Module.ToString(), error); _status = RState.Failed; Singleton.Instance.EFEM.PostMsg(EfemEntity.MSG.Error,error); } } async void SendBack(string data) { await Task.Run(() => _socket.Write(data + '\r')); } } }