using Aitex.Core.Common; using Aitex.Core.RT.DataCenter; using Aitex.Core.RT.Event; using Aitex.Core.RT.OperationCenter; using Aitex.Core.RT.SCCore; using Aitex.Core.Util; using Aitex.Sorter.Common; using MECF.Framework.Common.Equipment; using MECF.Framework.Common.SubstrateTrackings; using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.LoadPorts; using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using CyberX8_Core; using CyberX8_RT.Devices.YASKAWA; using CyberX8_RT.Modules; using Aitex.Core.RT.IOCore; using CyberX8_RT.Dispatch; using MECF.Framework.Common.IOCore; namespace CyberX8_RT.Devices.EFEM { sealed class Loadport : ILoadport { #region 常量 private const string CASSETE_200_PRESENT= "Cassete200Present"; private const string CASSETE_150_PRESENT = "Cassete150Present"; private const string CASSETE_100_PRESENT = "Cassete100Present"; #endregion private EfemEntity _controller => Singleton.Instance.EFEM; /// /// 变量是否初始化字典 /// private Dictionary _variableInitializeDic = new Dictionary(); private EfemBase _efemBase; //---------------------------------Properties------------------------------------ // public OnlineFlag OnlineFlag { get; set; } public ModuleName Module { get; set; } public DeviceState Status { get; set; } public WaferSize WaferSize { get; set; } public WaferStatus[] WaferInfo { get; set; } public bool HasCassette { get; set; } public bool Protrusion { get; set; } public bool IsMapped { get; set; } public bool JobDone { get; set; } public Stopwatch TimerNotifyJobDone { get; set; } public IE87CallBack LPCallBack { get { return _lpCallBack; } set { _lpCallBack = value; } } private IE87CallBack _lpCallBack; public bool IsThicknessValid { get { return !_enableThickness || !string.IsNullOrEmpty(_waferThicknessType); } } public string ThicknessType { get { return _waferThicknessType; } } public string PortId { get; private set; } public bool IsClamped { get; set; } public bool IsLoaded { get; set; } public bool IsDoorOpened { get; set; } public bool IsDocked { get; set; } public string CarrierId { get; set; } public string SmartTag { get; set; } public string LotId { get; set; } public bool IsBusy { get; set; } public bool IsError { get; set; } private string[] _slotMap = new string[25]; public string SlotMap { get { if (_slotMap == null) { _slotMap = new string[SC.GetValue("EFEM.LoadPort.SlotNumber")]; } for (int i = 0; i < _slotMap.Length; i++) { _slotMap[i] = ((int)WaferManager.Instance.GetWafer(Module, i).Status).ToString(); } return string.Join("", _slotMap); } } private string _waferThicknessType; private bool _enableThickness; private string AlarmWaferProtrude = "WaferProtrude"; private LoadPortFACallback _faCallback = new LoadPortFACallback(); private bool _cassete200Present = false; private bool _cassete150Present = false; private bool _cassete100Present = false; // Constructor // public Loadport(ModuleName mod, EfemBase efem) { Module = mod; PortId = ((int)mod - (int)ModuleName.LP1 + 1).ToString(); TimerNotifyJobDone = new Stopwatch(); _efemBase = efem; _enableThickness = false;// SC.GetValue("System.WaferThickness.EnableThickness"); EV.Subscribe(new EventItem("Event", AlarmWaferProtrude, "Wafer protrude", EventLevel.Alarm, EventType.HostNotification)); DATA.Subscribe($"{mod}.WaferSize", () => WaferSize.ToString(),SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{mod}.CassetteState", () => HasCassette ? LoadportCassetteState.Normal : LoadportCassetteState.Absent, SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{mod}.CassettePresent", () => HasCassette ? 1 : 0, SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{mod}.CassettePlaced", () => HasCassette,SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{mod}.SlotMap", () => SlotMap, SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{mod}.IsWaferProtrude", () => Protrusion ? 1 : 0,SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{mod}.IsMapped", () => IsMapped, SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{mod}.IsLoaded", () => IsLoaded, SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{mod}.IsClamped", () => IsClamped,SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{mod}.IsDocked", () => IsDocked, SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{mod}.IsDoorOpened", () => IsDoorOpened,SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{mod}.CarrierId", () => CarrierId, SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{mod}.SmartTag", () => SmartTag,SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{Module}.WaferThicknessType", () => _waferThicknessType,SubscriptionAttribute.FLAG.IgnoreSaveDB); OP.Subscribe($"{Module}.SetThick", (cmd, args) => { SetThick(); return true; }); OP.Subscribe($"{Module}.SetThin", (cmd, args) => { SetThin(); return true; }); SubscribeValueAction(); } /// /// 订阅变量数值发生变化 /// private void SubscribeValueAction() { BeckhoffIoSubscribeUpdateVariable(CASSETE_100_PRESENT); BeckhoffIoSubscribeUpdateVariable(CASSETE_150_PRESENT); BeckhoffIoSubscribeUpdateVariable(CASSETE_200_PRESENT); } /// /// 订阅IO变量 /// /// private void BeckhoffIoSubscribeUpdateVariable(string variable) { _variableInitializeDic[variable] = false; IOModuleManager.Instance.SubscribeModuleVariable($"{Module}", variable, UpdateVariableValue); } /// 更新变量数值 /// /// /// private void UpdateVariableValue(string variable, object value) { bool cassete=(bool)value; if (variable == CASSETE_200_PRESENT) { _cassete200Present = cassete; if (cassete) { WaferSize = WaferSize.WS8; } } else if (variable == CASSETE_150_PRESENT) { _cassete150Present = cassete; if (cassete&&!_cassete200Present) { WaferSize = WaferSize.WS6; } } else if (variable == CASSETE_100_PRESENT) { _cassete100Present = cassete; if (cassete && !_cassete200Present&&!_cassete150Present) { WaferSize = WaferSize.WS4; } } if (!_cassete100Present && !_cassete150Present && !_cassete200Present) { UpdateWaferArrive(false); } else { UpdateWaferArrive(true); } } // Methods // public void OnError() { IsError = true; IsBusy = false; } public void Abort() { IsError = false; IsBusy = false; } public void SetThick() { _waferThicknessType = "Thick"; SC.SetItemValue($"System.WaferThickness.{Module}WaferThicknessType", _waferThicknessType); _efemBase.SetThickness(Module, _waferThicknessType); } public void SetThin() { _waferThicknessType = "Thin"; SC.SetItemValue($"System.WaferThickness.{Module}WaferThicknessType", _waferThicknessType); _efemBase.SetThickness(Module, _waferThicknessType); } #region Home public void Home() { if (IsBusy) { EV.PostInfoLog(Module.ToString(), $"{Module} is busy can not home"); return; } IsBusy = true; _efemBase.Home(Module); } public void NoteJobStart() { JobDone = false; } public void NoteJobComplete() { TimerNotifyJobDone.Restart(); JobDone = true; } public void OnHomeFailed(string data) { IsError = true; IsBusy = false; } public void OnHomed() { IsError = false; IsBusy = false; IsClamped = false; IsLoaded = false; IsMapped = false; IsDocked = false; WaferManager.Instance.DeleteWafer(Module, 0, 25); } #endregion #region Load public bool Load() { if (IsLoaded) { EV.PostWarningLog(Module.ToString(), $"{Module} is loaded, can not load"); return false; } if (IsBusy) { EV.PostInfoLog(Module.ToString(), $"{Module} is busy, can not load"); return false; } if (IsError) { EV.PostInfoLog(Module.ToString(), $"{Module} is error, can not load"); return false; } IsBusy = true; _controller.SendEfemAutoCommand(EfemEntity.MSG.Load, Module); return true; } public void LoadStart() { if(_lpCallBack!=null) { _lpCallBack.LoadStart(); } } public void OnLoadFailed(string data) { IsError = true; IsBusy = false; _faCallback.LoadFailed(this); } public void OnLoaded() { IsError = false; IsBusy = false; IsDocked = true; IsLoaded = true; IsMapped = true; _faCallback.LoadComplete(this); if(_lpCallBack!=null) { _lpCallBack.LoadComplete(); } } #endregion #region unload public void Unload() { if (!IsLoaded) { EV.PostWarningLog(Module.ToString(), $"{Module} is not loaded, can not unload"); return; } if (IsBusy) { EV.PostInfoLog(Module.ToString(), $"{Module} is busy can not unload"); return; } if (IsError) { EV.PostInfoLog(Module.ToString(), $"{Module} is error can not unload"); return; } IsBusy = true; CycleManager.Instance.InitLpData(Module.ToString()); _controller.SendEfemAutoCommand(EfemEntity.MSG.Unload, Module); } public void UnloadStart() { if(_lpCallBack!=null) { _lpCallBack.UnLoadStart(); } } public void OnUnloadFailed(string data) { IsError = true; IsBusy = false; _faCallback.UnloadFailed(this); } public void OnUnloaded() { IsBusy = false; IsError = false; IsLoaded = false; IsDocked = false; IsMapped = false; WaferManager.Instance.DeleteWafer(Module, 0, 25); if (SC.GetValue("EFEM.AutoUnlockAfterUnload")) { _faCallback.UnloadComplete(this); } else { } } #endregion #region Get Wafer Size /// /// 获取Wafer尺寸 /// public bool GetWaferSize() { if (IsBusy) { EV.PostInfoLog(Module.ToString(), $"{Module} is busy can not get wafer size"); return false; } if (IsError) { EV.PostInfoLog(Module.ToString(), $"{Module} is error can not get wafer size"); return false; } IsBusy = true; return _efemBase.GetWaferSize(Module); } public void UpdateWaferSize(WaferSize waferSize) { WaferSize = waferSize; int count = WaferManager.Instance.GetSlotNumber(Module); for (int i = 0; i < count; i++) { WaferManager.Instance.UpdateWaferSize(Module, i, WaferSize); } IsBusy = false; IsError = false; } #endregion #region Dock public bool Dock() { if (IsBusy) { EV.PostInfoLog(Module.ToString(), $"{Module} is busy can not dock"); return false; } if (IsError) { EV.PostInfoLog(Module.ToString(), $"{Module} is error can not dock"); return false; } IsBusy = true; _controller.SendEfemAutoCommand(EfemEntity.MSG.Dock, Module); return true; } public void OnDocked() { IsBusy = false; IsError = false; } public void OnDockFailed(string data) { IsError = true; IsBusy = false; } #endregion #region Undock public void Undock() { if (IsBusy) { EV.PostInfoLog(Module.ToString(), $"{Module} is busy can not undock"); return; } if (IsError) { EV.PostInfoLog(Module.ToString(), $"{Module} is error can not undock"); return; } IsBusy = true; _controller.SendEfemAutoCommand(EfemEntity.MSG.Undock, Module); } public void OnUndocked() { IsBusy = false; IsError = false; } public void OnUndockFailed(string data) { IsError = true; IsBusy = false; } #endregion #region Clamp public void Clamp(bool isUnloadClamp) { if (IsBusy) { EV.PostInfoLog(Module.ToString(), $"{Module} is busy can not clamp"); return; } if (IsError) { EV.PostInfoLog(Module.ToString(), $"{Module} is error can not clamp"); return; } IsBusy = true; _controller.SendEfemAutoCommand(EfemEntity.MSG.Clamp, Module, isUnloadClamp); } public void OnClamped(bool isUnloadClamp) { IsBusy = false; IsError = false; if (isUnloadClamp) { _faCallback.UnloadComplete(this); } else { _faCallback.Clamped(this); } } public void OnClampFailed(string data) { IsError = true; IsBusy = false; } #endregion #region Unclamp public void Unclamp() { if (IsBusy) { EV.PostInfoLog(Module.ToString(), $"{Module} is busy can not unclamp"); return; } if (IsError) { EV.PostInfoLog(Module.ToString(), $"{Module} is error can not unclamp"); return; } IsBusy = true; _controller.SendEfemAutoCommand(EfemEntity.MSG.Unclamp, Module); } public void OnUnclamped() { IsBusy = false; IsError = false; _faCallback.Unclamped(this); } public void OnUnclampFailed(string data) { } #endregion #region map public void GotoMap(string extend) { if (IsBusy) { EV.PostInfoLog(Module.ToString(), $"{Module} is busy can not map"); return; } if (IsError) { EV.PostInfoLog(Module.ToString(), $"{Module} is error can not map"); return; } IsBusy = true; _controller.SendEfemAutoCommand(EfemEntity.MSG.GotoMap, Module,extend); } public void Map() { if (IsBusy) { EV.PostInfoLog(Module.ToString(), $"{Module} is busy can not map"); return; } if (IsError) { EV.PostInfoLog(Module.ToString(), $"{Module} is error can not map"); return; } IsBusy = true; _controller.SendEfemAutoCommand(EfemEntity.MSG.Map, Module); } public void OnMaped() { IsBusy = false; IsError = false; } #endregion #region carrierID public void ReadCarrierID() { if (IsBusy) { EV.PostInfoLog(Module.ToString(), $"{Module} is busy can not read carrier ID"); return; } if (IsError) { EV.PostInfoLog(Module.ToString(), $"{Module} is error can not read carrier ID"); return; } IsBusy = true; _controller.SendEfemAutoCommand(EfemEntity.MSG.ReadCarrierId, Module); } public void OnCarrierIDRead(string data) { IsBusy = false; IsError = false; //Regex rg = new Regex("(?<=(" + "LOT :" + "))[.\\s\\S]*?(?=(" + "QTY :" + "))", RegexOptions.Multiline | RegexOptions.Singleline); //string carrierID = rg.Match(data).Value.Replace(":", "").Trim(); //data = // "CST:C082259 TYPE:CST25_AU LOT:AF2403 QTY:24 FLOW:033000 STATUS:HOLD PRI:3-1 PD:0418A CSRLOT: CLEAN:2021/11/14 19:57:50 EQPGRP:DUMMY STAGE:CP-TEST1 RECIPE:DUMMY EMP:N "; var items = data.Split(new string[] { " ", "\t", "\r", "\n" }, StringSplitOptions.RemoveEmptyEntries); CarrierId = ""; foreach (var item in items) { if (item.StartsWith("CST:") && item.Length > 4) CarrierId = item.Substring(4).Trim(); if (item.StartsWith("LOT:") && item.Length > 4) LotId = item.Substring(4).Trim(); } if (string.IsNullOrEmpty(CarrierId)) { CarrierId = data; } SmartTag = data; _faCallback.IDRead(this); } public void OnCarrierIDReadFailed(string data) { IsError = true; IsBusy = false; _faCallback.ReadIDFailed(this); } public void WriteCarrierID(string id) { if (IsBusy) { EV.PostInfoLog(Module.ToString(), $"{Module} is busy can not write carrier ID"); return; } if (IsError) { EV.PostInfoLog(Module.ToString(), $"{Module} is error can not write carrier ID"); return; } IsBusy = true; _controller.SendEfemAutoCommand(EfemEntity.MSG.WriteCarrierID, Module, id); } public void OnCarrierIDWrite(string data) { IsBusy = false; IsError = false; var items = data.Split(new string[] { " ", "\t", "\r", "\n" }, StringSplitOptions.RemoveEmptyEntries); CarrierId = ""; foreach (var item in items) { if (item.StartsWith("CST:") && item.Length > 4) CarrierId = item.Substring(4); } if (string.IsNullOrEmpty(CarrierId)) { CarrierId = data; } SmartTag = data; _faCallback.IDWrite(this); } public void OnCarrierIDWriteFailed(string data) { IsError = true; IsBusy = false; _faCallback.WriteIDFailed(this); } #endregion #region event public void HandleEvent(EfemEventArgs eArg) { switch (eArg.CommandType) { case EfemOperation.GetWaferInfo: string sWaferInfo = eArg.DataList[0]; bool resultNormal = true; 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(this.Module, index, st); if (st == WaferStatus.Normal) { //EV.PostInfoLog(this.Module.ToString(), $"Found Wafer on Slot {index + 1} {WaferSize}"); } else { resultNormal = false; } } } UpdateMapResult(resultNormal); break; case EfemOperation.SigStatus: // EVT: SIGSTAT/P2/00000381/00000000; string sParam = eArg.DataList[0]; ModuleName mod = sParam.ToModule(); if (!ModuleHelper.IsLoadPort(mod)) return; // 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 }); // wafer size this.WaferSize = !baData1[6] ? WaferSize.WS3 : !baData1[7] ? WaferSize.WS4 : !baData1[8] ? WaferSize.WS6 : WaferSize.WS0; // placement & present bool bPlacement = baData1[0]; // bit 0 bool bPresence = !baData1[1]; // bit 1 bool bArrived = bPlacement && bPresence; UpdateWaferArrive(bArrived); this.Protrusion = !baData1[9]; if (Protrusion) { //EV.PostAlarmLog(Module.ToString(), "发现 wafer 突出"); //EV.Notify(AlarmWaferProtrude); //Singleton.Instance.EFEM.PostMsg(EfemEntity.MSG.Error); } // DATA2, loadport上面的LED 灯, 暂时不需要用到 break; default: break; } } public void UpdateMapResult(bool result) { if (result) { _faCallback.CarrierSlotMapComplete(this); } else { _faCallback.CarrierSlotMapFailed(this); } this.IsMapped = true; } /// /// 更新Wafer到达情况 /// /// public void UpdateWaferArrive(bool bArrived) { if (HasCassette) { if (!bArrived) { this.HasCassette = false; this.IsLoaded = false; this.IsMapped = false; //EV.PostInfoLog(mod.ToString(), "Cassette removed"); //OP.DoOperation("System.CassetteLeave"); //For unload light control off afer job done CarrierManager.Instance.DeleteCarrier(Module.ToString()); WaferManager.Instance.DeleteWafer(this.Module, 0, 25); _faCallback.CarrierRemoved(this); JobDone = false; _waferThicknessType = ""; } } else { if (bArrived) { this.HasCassette = true; IsLoaded = true; CarrierManager.Instance.CreateCarrier(Module.ToString()); _faCallback.CarrierArrived(this); JobDone = false; _waferThicknessType = ""; } } } #endregion #region TagData public void ReadTagData() { if (IsBusy) { EV.PostInfoLog(Module.ToString(), $"{Module} is busy can not read tag data"); return; } if (IsError) { EV.PostInfoLog(Module.ToString(), $"{Module} is error can not read tag data"); return; } IsBusy = true; _controller.SendEfemAutoCommand(EfemEntity.MSG.ReadTagData, Module); } public void OnTagDataRead(string data) { IsBusy = false; IsError = false; //Regex rg = new Regex("(?<=(" + "LOT :" + "))[.\\s\\S]*?(?=(" + "QTY :" + "))", RegexOptions.Multiline | RegexOptions.Singleline); //string carrierID = rg.Match(data).Value.Replace(":", "").Trim(); //data = // "CST:C082259 TYPE:CST25_AU LOT:AF2403 QTY:24 FLOW:033000 STATUS:HOLD PRI:3-1 PD:0418A CSRLOT: CLEAN:2021/11/14 19:57:50 EQPGRP:DUMMY STAGE:CP-TEST1 RECIPE:DUMMY EMP:N "; var items = data.Split(new string[] { " ", "\t", "\r", "\n" }, StringSplitOptions.RemoveEmptyEntries); CarrierId = ""; foreach (var item in items) { if (item.StartsWith("CST:") && item.Length > 4) CarrierId = item.Substring(4); if (item.StartsWith("LOT:") && item.Length > 4) LotId = item.Substring(4).Trim(); } if (string.IsNullOrEmpty(CarrierId)) { CarrierId = data; } SmartTag = data; _faCallback.TagDataRead(this); } public void OnTagDataReadFailed(string data) { IsError = true; IsBusy = false; _faCallback.ReadTagDataFailed(this); } public void WriteTagData(string tagData) { if (IsBusy) { EV.PostInfoLog(Module.ToString(), $"{Module} is busy can not write tag data"); return; } if (IsError) { EV.PostInfoLog(Module.ToString(), $"{Module} is error can not write tag data"); return; } IsBusy = true; _controller.SendEfemAutoCommand(EfemEntity.MSG.WriteTagData, Module, tagData); } public void OnTagDataWrite(string data) { IsBusy = false; IsError = false; var items = data.Split(new string[] { " ", "\t", "\r", "\n" }, StringSplitOptions.RemoveEmptyEntries); CarrierId = ""; foreach (var item in items) { if (item.StartsWith("CST:") && item.Length > 4) CarrierId = item.Substring(4); } if (string.IsNullOrEmpty(CarrierId)) { CarrierId = data; } SmartTag = data; _faCallback.TagDataWrite(this); } public void OnTagDataWriteFailed(string data) { IsError = true; IsBusy = false; _faCallback.WriteTagDataFailed( this); } #endregion public void SetOnline(bool online) { OnlineFlag = online ? OnlineFlag.Online : OnlineFlag.Offline; } sealed class LoadPortFACallback { private string CARRIER_ARRIVED = "CARRIER_ARRIVED"; private string CARRIER_REMOVED = "CARRIER_REMOVED"; private string SLOT_MAP_AVAILABLE = "SLOT_MAP_AVAILABLE"; private string SLOT_MAP_FAILED = "SLOT_MAP_FAILED"; private const string CARRIER_LOADED = "CARRIER_LOADED"; private const string PortLoadFailed = "PortLoadFailed"; private const string CARRIER_UNLOADED = "CARRIER_UNLOADED"; private const string PortUnloadFailed = "PortUnloadFailed"; private const string PortClamped = "PortClamped"; private const string PortUnclamped = "PortUnclamped"; private const string CARRIER_ID_READ = "CARRIER_ID_READ"; private const string PortReadIDFailed = "PortReadIDFailed"; private const string PortIDWrite = "PortIDWrite"; private const string PortWriteIDFailed = "PortWriteIDFailed"; private const string PortTagDataRead = "PortTagDataRead"; private const string PortReadTagDataFailed = "PortReadTagDataFailed"; private const string PortTagDataWrite = "PortTagDataWrite"; private const string PortWriteTagDataFailed = "PortWriteTagDataFailed"; public LoadPortFACallback() { EV.Subscribe(new EventItem("Event", CARRIER_ARRIVED, "Carrier Arrived")); EV.Subscribe(new EventItem("Event", CARRIER_REMOVED, "Carrier Removed")); EV.Subscribe(new EventItem("Event", SLOT_MAP_AVAILABLE, "Slot map available")); EV.Subscribe(new EventItem("Event", SLOT_MAP_FAILED, "Slot map failed")); EV.Subscribe(new EventItem("Event", CARRIER_LOADED, "Carrier Loaded")); EV.Subscribe(new EventItem("Event", PortLoadFailed, PortLoadFailed)); EV.Subscribe(new EventItem("Event", CARRIER_UNLOADED, "Carrier Unloaded")); EV.Subscribe(new EventItem("Event", PortUnloadFailed, PortUnloadFailed)); EV.Subscribe(new EventItem("Event", PortClamped, "Port Clamped")); EV.Subscribe(new EventItem("Event", PortUnclamped, PortUnclamped)); EV.Subscribe(new EventItem("Event", CARRIER_ID_READ, "Carrier Id Read")); EV.Subscribe(new EventItem("Event", PortReadIDFailed, PortReadIDFailed)); EV.Subscribe(new EventItem("Event", PortIDWrite, PortIDWrite)); EV.Subscribe(new EventItem("Event", PortWriteIDFailed, PortWriteIDFailed)); EV.Subscribe(new EventItem("Event", PortTagDataRead, PortTagDataRead)); EV.Subscribe(new EventItem("Event", PortReadTagDataFailed, PortReadTagDataFailed)); EV.Subscribe(new EventItem("Event", PortTagDataWrite, PortTagDataWrite)); EV.Subscribe(new EventItem("Event", PortWriteTagDataFailed, PortWriteTagDataFailed)); } public void CarrierArrived(Loadport lp) { SerializableDictionary dvid = new SerializableDictionary(); dvid["PortID"] = lp.PortId; EV.Notify(CARRIER_ARRIVED, dvid); } public void CarrierRemoved(Loadport lp) { SerializableDictionary dvid = new SerializableDictionary(); dvid["PortID"] = lp.PortId; dvid["CarrierID"] = lp.CarrierId ?? ""; EV.Notify(CARRIER_REMOVED, dvid); } public void CarrierSlotMapComplete(Loadport lp) { SerializableDictionary dvid = new SerializableDictionary(); dvid["SlotMap"] = lp.SlotMap; dvid["PortID"] = lp.PortId; dvid["CarrierID"] = lp.CarrierId ?? ""; EV.Notify(SLOT_MAP_AVAILABLE, dvid); } public void CarrierSlotMapFailed(Loadport lp) { } public void LoadComplete(Loadport lp) { ModuleName moduleName = lp.Module; var dvid = new SerializableDictionary { ["CarrierID"] = lp.CarrierId ?? "", ["PortID"] = lp.PortId.ToString() }; EV.Notify(CARRIER_LOADED, dvid); } public void LoadFailed(Loadport lp) { } public void UnloadComplete(Loadport lp) { ModuleName moduleName = lp.Module; var dvid = new SerializableDictionary { ["CarrierID"] = lp.CarrierId ?? "", ["PortID"] = lp.PortId.ToString() }; EV.Notify(CARRIER_UNLOADED, dvid); } public void UnloadFailed(Loadport lp) { } public void Clamped(Loadport lp) { } public void Unclamped(Loadport lp) { } public void IDRead(Loadport lp) { } public void ReadIDFailed(Loadport lp) { } public void IDWrite(Loadport lp) { } public void WriteIDFailed(Loadport lp) { } public void TagDataRead(Loadport lp) { } public void ReadTagDataFailed(Loadport lp) { } public void TagDataWrite(Loadport lp) { } public void WriteTagDataFailed(Loadport lp) { } } } }