namespace Bridge300.E90
{
internal class SPJInfo
{
public SPJInfo()
{
matNameList = new List<string>();
}
public PRJobStateEnum m_PRJobStateEnum;
public string strJobID;
public List<string> matNameList;
};
internal class LocSubPair
{
public string strLoc;
public string strSubID;
};
internal class PMSubstrateInfo
{
public PMSubstrateInfo()
{
m_LocToSubstrIDMap = new List<LocSubPair>();
}
public string m_strModule;//PM1 ,PM2 etc
public List<LocSubPair> m_LocToSubstrIDMap;
};
internal class CarrierInfo
{
public CarrierInfo()
{
m_strSubstrIDs = new List<string>();
m_strSubstrLoc = new List<LocSubPair>();
}
public string m_strCarID;
public uint m_lPortNo;
public List<string> m_strSubstrIDs;
public List<LocSubPair> m_strSubstrLoc;
};
// 修改人:wangkai,修改日期:20231130,修改版本:1.8.0,修改原因:FA异常捕获
public class E90Manager : SingletonTemplate<E90Manager>
{
/// <remarks>
/// 修改人:田百强 修改时间:20240929 修改原因:单元测试去掉readonly 修改版本:***
/// </remarks>
public static ILog Log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
private List<string> PolledDataItem = new List<string>();
private static readonly int E87_ALARM_ID = 5018;
private static readonly int E90_ALARM_ID = 5019;
private static readonly int E90_TRANSITION_ALARM_ID = 5020;
private static readonly int E87_TRANSITION_ALARM_ID = 5021;
/// <summary>
/// Lock object
/// </summary>
private static readonly object objectLock = new object();
private List<PMSubstrateInfo> m_PMSubstrateInfoList = new List<PMSubstrateInfo>();
private List<CarrierInfo> m_CarInfoList = new List<CarrierInfo>();
private List<SPJInfo> m_PJInfoList = new List<SPJInfo>();
private int m_ulNumPortModules;
private static IE30Server E30Server;
private static IE90Server E90Server;
private static IE87Server E87Server;
private static E90Manager e90Manager;
private E90EquipmentEventHandler e90EquipmentEventHandler = new E90EquipmentEventHandler();
private E90RemoteEventHandler e90RemoteEventHandler = new E90RemoteEventHandler();
/// <summary>
/// 修改人:田百强 修改时间:2024-10-26 修改原因:用于单元测试 修改版本:***
/// </summary>
public E90EquipmentEventHandler E90ManagerEquipmentEventHandler
{
get { return e90EquipmentEventHandler; }
}
// 修改人:wangkai,修改日期:20231211,修改版本:1.8.0rc03,修改原因:单例模板增加私有构造函数
protected E90Manager()
{
}
/// <summary>
/// 单元测试设置log对象
/// </summary>
/// <param name="logger"></param>
/// <remarks>
/// 修改人:田百强 修改时间:20240929 修改原因:单元测试使用 修改版本:***
/// </remarks>
public void SetLogForUnitTest(ILog logger)
{
Log = logger;
}
public void Init()
{
Log.Info("E90_Bridge module start init...");
try
{
E87Manager.GetIns().OnLoadPortLoaded += new loadedSubscribeSubstrateStateChange(this.SubscribeSubstrateStateChange);
E87Manager.GetIns().OnLoadPortUnloaded += new unloadedUnSubscribeSubstrateStateChange(this.UnSubscribeSubstrateStateChange);
GetE30ServerFromiLink();
//get the E90Server interface
GetE90ServerFromiLink();
//get the E87Server interface
GetE87ServerFromiLink();
// e90RemoteEventHandler.Init(this);
e90EquipmentEventHandler.Init(E90Server, E87Server);
//FA init create physical location object
CreatePhysicalLocations();
InitializePMLocationsList();
// 修改人:my,修改日期:2020624,修改版本:2.0.1,修改原因:同步二刻58事件不上报共性问题,将如下代码注释后,移植ConrtorlApp.cs中
////Register the MatLocationChange,此DataItem提供Wafe移动信息,matname,srcmod,srcslot,destmod,destslot。
//if (!RegisterMatLocationChange())
//{
// Log.Error("Init E90Manager Fail!");
// return;
//}
////Register the TransferMatStatus,此DataItem提供Wafer的Processing状态。
////if (!RegisterMatMatStatus())
////{
//// Log.Error("Init E90Manager Fail!");
//// return;
////}
//m_ulNumPortModules = GetNumberOfPortModules();
////Register Pn.JobState channel
//RegisterJobAndLotStateIOs();
////Register SynFlag Channel
//RegisterSynFlag();
////Register Pn.CarrierAccessStatus、Pn.MID
//RegisterIOChannelsForE87Sync();
//DoE87Synchronization();
////RegisterIOChannelsForE90Sync();
//DoE90Synchronization();
}
catch
{
Log.Error("Init E90Manager Fail!");
}
}
private void RegisterSynFlag()
{
try
{
const string dataItemName = "SynFlag";
// 修改人:wangkai,修改日期:20231109,修改版本:1.7.0,修改原因:DataServer移动到DataCenter项目
DataServer.Instance.SubData("CTC", dataItemName, e90EquipmentEventHandler);
PolledDataItem.Add(dataItemName);
}
catch (System.Exception e)
{
Log.Error($"Register DataItem: SynFlag fail!{e.Message}");
}
}
private void SubscribeSubstrateStateChange(string portName)
{
IList<IRemoteModule> remoteModuleList = this.GetModuleList();
if (remoteModuleList == null)
{
return;
}
foreach (IRemoteModule reModule in remoteModuleList)
{
if (reModule.ModName.Equals(portName))
{
for (int i = 1; i <= reModule.Capacity; i++)
{
IRemoteWafer wafer = reModule.GetWaferInSlot(i);
try
{
if (wafer != null)
{
// 修改人:wangkai,修改日期:20231109,修改版本:1.7.0,修改原因:DataServer移动到DataCenter项目
MaterialServer.Instance.SubMatStatus(wafer, this.e90EquipmentEventHandler);
Log.Debug($"SubMatStatus Wafer {portName}_Slot{i} state.");
}
}
catch (System.Exception e)
{
Log.Error($"SubMatStatus Wafer State Fail! {e.Message}");
}
}
}
}
}
private void UnSubscribeSubstrateStateChange(string portName)
{
IList<IRemoteModule> remoteModuleList = this.GetModuleList();
if (remoteModuleList == null)
{
return;
}
foreach (IRemoteModule reModule in remoteModuleList)
{
if (reModule.ModName.Equals(portName))
{
for (int i = 1; i <= reModule.Capacity; i++)
{
IRemoteWafer wafer = reModule.GetWaferInSlot(i);
try
{
if (wafer != null)
{
// 修改人:wangkai,修改日期:20231109,修改版本:1.7.0,修改原因:DataServer移动到DataCenter项目
MaterialServer.Instance.UnSubMatStatus(wafer, this.e90EquipmentEventHandler);
Log.Debug($"SubMatStatus Wafer State: {portName}_Slot{i}");
}
}
catch (System.Exception e)
{
Log.Error($"UnSubMatStatus Wafer State Fail! {e.Message}");
}
}
}
}
}
public void SafeShutDown()
{
this.UnSubscribeDataItem();
e90RemoteEventHandler.RemoveE90Event();
}
/// <summary>
/// Register Fa E90 remote event
/// </summary>
public void RegisterE90RemoteEvent()
{
Log.Info("Register Fa E90 remote event");
e90RemoteEventHandler.Init(this);
}
private void UnSubscribeDataItem()
{
// 修改人:wangkai,修改日期:20231130,修改版本:1.8.0,修改原因:FA异常捕获
try
{
foreach (string dataItemName in PolledDataItem)
{
if (-1 != dataItemName.IndexOf("/"))
{
//该DataItem的Module Name是TM
DataServer.Instance.UnsubData("TM", dataItemName, e90EquipmentEventHandler);
}
else
{
//该DataItem的Module Name是CTC
DataServer.Instance.UnsubData("CTC", dataItemName, e90EquipmentEventHandler);
}
}
}
catch (Exception ex)
{
Log.Error($"UnSubscribeDataItem failed. Error: {ex}");
}
}
private int GetNumberOfPortModules()
{
int portNumber = 0;
//get the total of modules of type CL_cassette_module
List<PortModule> portModuleList = Globals.GetAllPortModuleList();
portNumber = portModuleList.Count;
if (0 == portNumber)
{
Log.Debug("No port modules are configured for the tool!");
}
return portNumber;
}
/// <summary>
/// 单元测试由private 改为public
/// </summary>
/// <returns></returns>
public bool InitCarrierInfo()
{
bool bRet = false;
List<PortModule> portModuleList = Globals.GetAllPortModuleList();
foreach (PortModule port in portModuleList)
{
CarrierInfo pCarrierInfo = new CarrierInfo();
pCarrierInfo.m_lPortNo = port.PortID;
InitCarrierLocations(pCarrierInfo, port);
m_CarInfoList.Add(pCarrierInfo);
bRet = true;
}
return bRet;
}
private bool InitCarrierLocations(CarrierInfo pCarrierInfo, PortModule port)
{
bool bRet = false;
int nCapacity = 0;
nCapacity = port.Capacity;
for (int i = 1; i <= nCapacity; i++)
{
string strLoc = "";
strLoc = $"_slot{i}";
LocSubPair pPair = new LocSubPair();
pPair.strLoc = strLoc;
pCarrierInfo.m_strSubstrLoc.Add(pPair);
bRet = true;
}
return bRet;
}
private bool InitializePMLocationsList()
{
bool bRet = false;
//get the total no of modules of type CL_process_module
IList<IRemoteModule> remoteModuleList = GetModuleList();
foreach (IRemoteModule module in remoteModuleList)
{
if (module.ModType == ModuleTypes.CL_process_module)
{
PMSubstrateInfo pPMSubstrateInfo = new PMSubstrateInfo();
pPMSubstrateInfo.m_strModule = module.ModName;
m_PMSubstrateInfoList.Add(pPMSubstrateInfo);
}
}
if (null == E90Server)
{
return false;
}
List<IE90SubstrateLocation> ie90SubstrateLocList = E90Server.GetAllSubstrateLocations();
for (int i = 0; i < ie90SubstrateLocList.Count; i++)
{
string strLocationID = "";
string strSubID = "";
try
{
IE90SubstrateLocation ie90SubstrateLocation = ie90SubstrateLocList[i];
strLocationID = ie90SubstrateLocation.GetSubstrateLocationID();
IE90Substrate ie90SubStrate = null;
ie90SubStrate = ie90SubstrateLocation.GetSubstrate();
if (null != ie90SubStrate)
{
strSubID = ie90SubStrate.GetSubstrateID();
}
}
catch
{
Log.Error("UNKNOWN ERROR in E90Manager::InitializePMLocationsList while retreving substrates!");
}
if (strLocationID.Length >= 2)
{
//check whether it is of type AL, TM, PM or carrier. in the case of a carrier
//the "_" will not occur in the third position..(Eg. A123456.Slot#)
if (IsPMLoc(strLocationID))
{
string strModule = strLocationID.Substring(0, 3);
AddLocation(strModule, strLocationID, strSubID);
bRet = true;
}
}
}
return bRet;
}
private void AddLocation(string strModule, string strLocationID, string strSubID)
{
//Check in PM and if yes add
string strPM = strModule;
foreach (PMSubstrateInfo pmSubInfo in m_PMSubstrateInfoList)
{
if (pmSubInfo.m_strModule.Equals(strPM))
{
LocSubPair pLoc = new LocSubPair();
pLoc.strLoc = strLocationID;
pLoc.strSubID = strSubID;
// 修改人:wangkai,修改日期:20231130,修改版本:1.8.0,修改原因:FA异常捕获
if (pmSubInfo.m_LocToSubstrIDMap != null)
{
pmSubInfo.m_LocToSubstrIDMap.Add(pLoc);
}
}
}
}
/// <summary>
/// 获取E30Server对象
/// </summary>
/// <remarks>
/// 修改人:田百强 修改时间:20241020 修改原因:单元测试由private 改为public
/// </remarks>
public void GetE30ServerFromiLink()
{
E90Manager.E30Server = BridgeAdapter.ConnectionServer.E30Server;
}
/// <summary>
/// 获取E90Server对象
/// </summary>
/// <remarks>
/// 修改人:田百强 修改时间:20241020 修改原因:单元测试由private 改为public
/// </remarks>
public void GetE90ServerFromiLink()
{
E90Manager.E90Server = BridgeAdapter.ConnectionServer.E90Server;
}
/// <summary>
/// 获取E87Server对象
/// </summary>
/// <remarks>
/// 修改人:田百强 修改时间:20241020 修改原因:单元测试由private 改为public
/// </remarks>
public void GetE87ServerFromiLink()
{
E90Manager.E87Server = BridgeAdapter.ConnectionServer.E87Server;
}
/// <summary>
/// Create Physical substrate location
/// </summary>
private void CreatePhysicalLocations()
{
try
{
List<RemoteSubstLocation> subLocList = new List<RemoteSubstLocation>();
int count = this.GetPhysicalLocationsSubstrates(ref subLocList);
E90Server.CreatePhysicalLocations(subLocList);
this.NotifyFAMaterialCount(count);
}
catch (System.Exception e)
{
Log.Error($"Registering of physical locations with E90 failed!{e.Message}");
}
}
public int GetPhysicalLocationsSubstrates(ref List<RemoteSubstLocation> subLocList)
{
Log.Debug("Bridge start Call GetPhysicalLocationsSubstrates ");
int MaterialPresentNum = 0;
subLocList = new List<RemoteSubstLocation>();
bool isPhysicalLocation = true;
try
{
IList<CtcCommonType.IRemoteModule> moduleList = null;
moduleList = GetModuleList();
if (null != moduleList)
{
foreach (CtcCommonType.IRemoteModule remoteModule in moduleList)
{
isPhysicalLocation = true;
IRemoteWafer remoteWafer = null;
string strModule = "";
strModule = remoteModule.ModName;
if (ModuleTypes.CL_cassette_module == remoteModule.ModType)
{
//continue;
string mapStatus = DataServer.Instance.ParseData(DataServer.Instance.GetDataValue("TM", $"/Control/TMCExports/Datas/{remoteModule.ModName}_MapStatus"));
string carrierID = DataServer.Instance.ParseData(DataServer.Instance.GetDataValue("TM", $"/Control/TMCExports/Datas/{remoteModule.ModName}_MID"));
if (!mapStatus.Equals("Mapped") || string.IsNullOrEmpty(carrierID))
{
continue;
}
IE87Carrier carrier = E87Server.GetCarrier(carrierID);
if (carrier == null || carrier.GetSlotMapVerificationStatus() != FADataModel.E87.SlotMapStatusEnum.SLOT_MAP_VERIFICATION_OK)
{
continue;
}
isPhysicalLocation = false;
strModule = carrierID;
}
for (int i = 1; i <= remoteModule.Capacity; i++)
{
RemoteSubstLocation substrateLocation = new RemoteSubstLocation();
substrateLocation.LocID = $"{strModule}_slot{i}";
substrateLocation.IsPhysicalLocation = isPhysicalLocation;
remoteWafer = remoteModule.GetWaferInSlot(i);
if (null != remoteWafer)
{
if (TransferMatStatus.none == remoteWafer.WaferStatus || TransferMatStatus.unknown == remoteWafer.WaferStatus)
{
substrateLocation.SubstID = string.Empty;
substrateLocation.State = SubstLocStateEnum.UnOccupied;
}
else
{
if (!string.IsNullOrEmpty(remoteWafer.LotId))
{
//substrateLocation.SubstID = remoteWafer.LotId + "." + remoteWafer.SrcSlot.ToString();
substrateLocation.SubstID = remoteWafer.WaferName;
}
else
{
substrateLocation.SubstID = string.Empty;
}
substrateLocation.State = SubstLocStateEnum.Occupied;
++MaterialPresentNum;
}
}
else
{
substrateLocation.SubstID = string.Empty;
substrateLocation.State = SubstLocStateEnum.UnOccupied;
}
subLocList.Add(substrateLocation);
}
}
}
}
catch (System.Exception e)
{
Log.Error($"Cannot get substrate location attribute from CTC! Register physical locations fail! {e.Message}");
return MaterialPresentNum;
}
Log.Debug("Bridge complete Call GetPhysicalLocationsSubstrates ");
return MaterialPresentNum;
}
public void NotifyFAMaterialCount(int count)
{
try
{
Log.Debug($"Set Value MaterialPresentNum is {count}");
E90Manager.E30Server.E30SetVariable("MaterialPresentNum", count.ToString());
Log.Debug("Fire event MaterialPresent to FA!");
E90Manager.E30Server.EventFire("E90", "MaterialPresent");
}
catch (System.Exception e)
{
Log.Error($"Fire Event MaterialPresent to FA Fail! {e.Message}");
}
}
private IList<IRemoteModule> GetModuleList()
{
IList<IRemoteModule> moduleList = null;
moduleList = BridgeAdapter.ConnectionServer.Coordinator.GetModuleManager().ModuleTable;
return moduleList;
}
private bool RegisterMatLocationChange()
{
try
{
const string dataItemName = "MatLocationChange";
//修改人:zhangn;修改内容:增加swapmove动作完成物料状态变化的信号量,将swap动作的完成时,所有片子位置变化拼接为一个字符串传给FA或者HistoryLog;修改时间:20240910;修改版本:1.8.0HotFix4
const string dataItemName_swapmove = "SwapMoveMatLocationChange";
// 修改人:wangkai,修改日期:20231109,修改版本:1.7.0,修改原因:DataServer移动到DataCenter项目
DataServer.Instance.SubData("CTC", dataItemName, e90EquipmentEventHandler);
PolledDataItem.Add(dataItemName);
DataServer.Instance.SubData("CTC", dataItemName_swapmove, e90EquipmentEventHandler);
PolledDataItem.Add(dataItemName_swapmove);
}
catch (System.Exception e)
{
Log.Error($"Register DataItem: MatLocationChange fail!{e.Message}");
return false;
}
return true;
}
/// <summary>
/// 修改人:田百强 修改时间:20241029 修改原因:单元测试private 改为public 修改版本:**
/// </summary>
/// <returns></returns>
public bool RegisterMatMatStatus()
{
try
{
List<PortModule> portModuleList = new List<PortModule>();
portModuleList = Globals.GetAllPortModuleList();
foreach (PortModule port in portModuleList)
{
for (int i = 1; i <= port.Capacity; i++)
{
string dataItemName = $"CTC_{port.Name}_S{i}_MatStatus";
// 修改人:wangkai,修改日期:20231109,修改版本:1.7.0,修改原因:DataServer移动到DataCenter项目
DataServer.Instance.SubData("CTC", dataItemName, e90EquipmentEventHandler);
Log.Info($"Bridge_E90 Subscribe Data: {dataItemName}");
PolledDataItem.Add(dataItemName);
}
}
}
catch (System.Exception e)
{
Log.Error($"Register DataItem: MatLocationChange fail!{e.Message}");
return false;
}
return true;
}
/// <summary>
///Create Pn.JobState Channel
/// </summary>
private void RegisterJobAndLotStateIOs()
{
string JobStateChannel = "";
try
{
List<PortModule> portModuleList = Globals.GetAllPortModuleList();
foreach (PortModule port in portModuleList)
{
JobStateChannel = $"{port.Name}_JobState";
// 修改人:wangkai,修改日期:20231109,修改版本:1.7.0,修改原因:DataServer移动到DataCenter项目
DataServer.Instance.SubData("CTC", JobStateChannel, e90EquipmentEventHandler);
PolledDataItem.Add(JobStateChannel);
}
}
catch
{
Log.Error($"Register{JobStateChannel}Channel fail!");
}
}
/// <summary>
/// Register Pn.CasSts、Pn.MID channel
/// </summary>
private void RegisterIOChannelsForE87Sync()
{
string TMDataItemPath = "/Control/TMCExports/Datas/";
string carrierAccessStatusChannel = "";
List<PortModule> portModeList = Globals.GetAllPortModuleList();
try
{
foreach (PortModule port in portModeList)
{
carrierAccessStatusChannel = $"{TMDataItemPath}{port.Name}_CasSts";
// 修改人:wangkai,修改日期:20231109,修改版本:1.7.0,修改原因:DataServer移动到DataCenter项目
DataServer.Instance.SubData("TM", carrierAccessStatusChannel, e90EquipmentEventHandler);
PolledDataItem.Add(carrierAccessStatusChannel);
//removed by lijj 20110914 for no use
//MIDChannel = TMDataItemPath + port.Name + "_MID";
//DataServer.Instance.SubData("TM", MIDChannel, e90EquipmentEventHandler);
//PolledDataItem.Add(MIDChannel);
}
}
catch
{
Log.Error("Register Pn_CasSts Channel fail!");
}
}
/// <summary>
/// 修改人:田百强 修改时间:20241029 修改原因:单元测试private 改为public 修改版本:**
/// </summary>
public void RegisterIOChannelsForE90Sync()
{
try
{
//Add code to get the list of all modules
IList<IRemoteModule> remoteModuleList = GetModuleList();
foreach (IRemoteModule module in remoteModuleList)
{
for (int i = 1; i <= module.Capacity; i++)
{
string dataItemName = $"CTC_{module.ModName}_S{i}_Wfr";
// 修改人:wangkai,修改日期:20231109,修改版本:1.7.0,修改原因:DataServer移动到DataCenter项目
DataServer.Instance.SubData("CTC", dataItemName, e90EquipmentEventHandler);
PolledDataItem.Add(dataItemName);
}
}
}
catch
{
Log.Error("Register SubstrateIOs fail!");
}
}
/// <summary>
/// Do E87Synchronization
/// </summary>
public void DoE87Synchronization()
{
// 修改人:wangkai,修改日期:20231130,修改版本:1.8.0,修改原因:FA异常捕获
try
{
string strIOValue;
//1. get the number of carriers and register for the ios
List<PortModule> portModeList = Globals.GetAllPortModuleList();
foreach (PortModule port in portModeList)
{
//2. Get the carrier presence/absence by reading the ios
strIOValue = ReadIOPortAccessStatus(port.Name);
//3. get the carrier inofrmation from E87server
bool bCarPresent = ReadILinkPortAccessStatus(port.PortID);
//4. compare the io values and the ilink information.and Post alarm.
if (strIOValue.Equals("Absent") && (bCarPresent))
{
//CTC says carrier absent, but ILink says carrier is present....
// 修改人:wangkai,修改日期:20240201,修改版本:***,修改原因:AlarmManager合并到DataCenter中
AlarmServer.Instance.PostAlarm(E87_TRANSITION_ALARM_ID.ToString());
//e90EquipmentEventHandler.DoRemoveCarrier(port.PortID);lijj
}
else if (strIOValue.Equals("Present") && (!bCarPresent))
{
//CTC says carrier present, but ILink says carrier is absent....
// 修改人:wangkai,修改日期:20240201,修改版本:***,修改原因:AlarmManager合并到DataCenter中
AlarmServer.Instance.PostAlarm(E87_ALARM_ID.ToString());
//e90EquipmentEventHandler.DoE87E90Synchronization();
}
else if (strIOValue.Equals("Unknown") && (bCarPresent))
{
// 修改人:wangkai,修改日期:20240201,修改版本:***,修改原因:AlarmManager合并到DataCenter中
AlarmServer.Instance.PostAlarm(E87_TRANSITION_ALARM_ID.ToString());
//e90EquipmentEventHandler.DoE87E90Synchronization();
}
}
}
catch (Exception ex)
{
Log.Error($"DoE87Synchronization failed! Error: {ex}");
}
}
/// <summary>
/// Do E90Synchronization
/// </summary>
public void DoE90Synchronization()
{
DoSubstrateComparison();
}
/// <summary>
/// Get the carrier presence/absence by reading the ios
/// </summary>
/// <param name="nPort"></param>
/// <returns></returns>
private string ReadIOPortAccessStatus(string portName)
{
string strRet = "";
// 修改人:wangkai,修改日期:20231130,修改版本:1.8.0,修改原因:FA异常捕获
try
{
//Get Pn_CasSts DataItem
string pnCasStsDataName = $"/Control/TMCExports/Datas/{portName}_CasSts";
// 修改人:wangkai,修改日期:20231109,修改版本:1.7.0,修改原因:DataServer移动到DataCenter项目
RemoteValueInfo dataValueInfo = DataServer.Instance.GetDataValue("TM", pnCasStsDataName);
strRet = DataServer.Instance.ParseData(dataValueInfo);
}
catch (Exception ex)
{
Log.Error($"ReadIOPortAccessStatus failed! Error: {ex}");
}
return strRet;
}
/// <summary>
/// get the carrier information from E87server
/// </summary>
/// <param name="nPort"></param>
/// <returns></returns>
private bool ReadILinkPortAccessStatus(uint nPort)
{
bool bRetCode = true;
try
{
IE87Port ie87Port = null;
ie87Port = E87Server.GetPort((int)nPort);
IE87Carrier ie87Carrier = null;
ie87Carrier = ie87Port.GetCarrier();
if (null == ie87Carrier)
{
return bRetCode = false;
}
}
catch (Exception e)
{
Log.Error($"Unknown error in getting the E87Carrier interface for the port{nPort}{e}");
}
return bRetCode;
}
/// <summary>
/// Do substrate comparison
/// </summary>
/// <returns></returns>
private bool DoSubstrateComparison()
{
bool bRetCode = false;
// 修改人:wangkai,修改日期:20231130,修改版本:1.8.0,修改原因:FA异常捕获
try
{
List<IE90SubstrateLocation> ie90SubstrateLoctionList;
ie90SubstrateLoctionList = E90Server.GetAllSubstrateLocations();
for (int i = 0; i < ie90SubstrateLoctionList.Count; i++)
{
IE90SubstrateLocation ie90SubstrateLocation = ie90SubstrateLoctionList[i];
string substrateLocationID = ie90SubstrateLocation.GetSubstrateLocationID();
if (substrateLocationID.Length < 2)
{
return false;
}
//check whether it is of type AL, TM, PM or carrier. in the case of a carrier
//the "_" will not occur in the third position..(Eg. A123456.Slot#)
int index = substrateLocationID.IndexOf("_");
if (-1 != index)
{
string strModule = substrateLocationID.Substring(0, index);
if (IsAnActualModule(strModule))
{
bRetCode = CheckModuleSubstrate(substrateLocationID, ie90SubstrateLocation);
}
else// if (-1 != substrateLocationID.IndexOf("."))
{
bRetCode = CheckCarrierSubstrate(substrateLocationID, ie90SubstrateLocation);
}
}
}
}
catch (Exception ex)
{
Log.Error($"DoSubstrateComparison failed! Error: {ex}");
}
return bRetCode;
}
private bool IsAnActualModule(string strModule)
{
bool bRetCode = false;
IList<IRemoteModule> moduleList = GetModuleList();
foreach (IRemoteModule module in moduleList)
{
if (module.ModName.Equals(strModule))
{
bRetCode = true;
break;
}
}
return bRetCode;
}
/// <summary>
/// Check E90Synchronization for equipment and FA
/// </summary>
/// <param name="strSubLocationID"></param>
/// <param name="pLocation"></param>
/// <returns></returns>
private bool CheckModuleSubstrate(string strSubLocationID, IE90SubstrateLocation pLocation)
{
bool bRetCode = false;
bool bSubstratePresent = false;
string strModule = "";
string slotNum = "";
//get the slot number here
int nSlot = -1;
// 修改人:wangkai,修改日期:20231130,修改版本:1.8.0,修改原因:FA异常捕获
try
{
int index = strSubLocationID.IndexOf("_");
if (-1 != index)
{
strModule = strSubLocationID.Substring(0, index);
slotNum = strSubLocationID.Replace($"{strModule}_slot", "");//
nSlot = int.Parse(slotNum);
}
IE90Substrate ie90Substrate = null;
ie90Substrate = pLocation.GetSubstrate();
if (null != ie90Substrate)
{
bSubstratePresent = true;
}
else
{
bSubstratePresent = false;
}
//read each slots wafer presence, and the substrate id from link
//if they don't match, return false
string strSubstratePresence = "WAFER_UNKNOWN";
strSubstratePresence = ReadSubstratePresenceIO(strModule, nSlot);
if (strSubstratePresence.Contains("WAFER_PRSENT") && !bSubstratePresent)
{
// 修改人:wangkai,修改日期:20240201,修改版本:***,修改原因:AlarmManager合并到DataCenter中
AlarmServer.Instance.PostAlarm(E90_ALARM_ID.ToString());
//e90EquipmentEventHandler.E90Synchronization();
}
else if (strSubstratePresence.Contains("WAFER_ABSENT") && bSubstratePresent)
{
// 修改人:wangkai,修改日期:20240201,修改版本:***,修改原因:AlarmManager合并到DataCenter中
AlarmServer.Instance.PostAlarm(E90_TRANSITION_ALARM_ID.ToString());
//e90EquipmentEventHandler.E90Synchronization();
}
else
{
//sonar
}
}
catch (Exception ex)
{
Log.Error($"CheckModuleSubstrate failed! Error: {ex}");
}
return bRetCode;
}
/// <summary>
///
/// </summary>
/// <param name="strSubLocationID"></param>
/// <param name="pLocation"></param>
/// <returns></returns>
private bool CheckCarrierSubstrate(string strSubLocationID, IE90SubstrateLocation pLocation)
{
bool bRetCode = false;
//get the slot number and carrier id (name) here
string strModule = "";
string slotNum = "";
string strCarName = "";
int nSlot = -1;
// 修改人:wangkai,修改日期:20231130,修改版本:1.8.0,修改原因:FA异常捕获
try
{
int index = strSubLocationID.IndexOf("_");
if (-1 != index)
{
strCarName = strSubLocationID.Substring(0, index);
slotNum = strSubLocationID.Replace($"{strCarName}_slot", "");//
nSlot = int.Parse(slotNum);
}
//read the value of the /Control/TMCExports/Datas/Pn_MID DataItem here
string strCarID = "";
List<PortModule> moduleList = Globals.GetAllPortModuleList();
foreach (PortModule port in moduleList)
{
strModule = "";
strCarID = "";
string dataItemName = $"/Control/TMCExports/Datas/{port.Name}_MID";
strCarID = ReadIOValueString(dataItemName);
if (!strCarID.Equals(""))
{
if (-1 != strCarName.IndexOf(strCarID))
{
strModule = port.Name;
break;
}
}
//strmodule is empty means, ilink doesn't have the carrier with it.
//if (!strModule.Equals(""))
//{
// bRetCode = CheckILinkSubstrateInformation(strModule, nSlot, pLocation);
//}
//else
//{
// if (strCarID.Equals(""))//MID is empty
// {
// bRetCode = CheckForILinkSubstratePresence(pLocation);
// }
// bRetCode = CheckForCTCSubstratePresence(port.Name);
//}
}
if (!strModule.Equals(""))
{
bRetCode = CheckILinkSubstrateInformation(strModule, nSlot, pLocation);
}
else
{
bRetCode = CheckForILinkSubstratePresence(pLocation);
//if (strCarID.Equals(""))//MID is empty
//{
// bRetCode = CheckForILinkSubstratePresence(pLocation);
//}
//else
//{
// //bRetCode = CheckForCTCSubstratePresence(port.Name);
//}
}
}
catch (Exception ex)
{
Log.Error($"CheckCarrierSubstrate failed! Error: {ex}");
}
return bRetCode;
}
public virtual string ReadSubstratePresenceIO(string strModule, int nSlot)
{
string channelName = $"CTC_{strModule}_S{nSlot}_Wfr";
string channelVal = "";
//Dictionary<string, IData> datas = new Dictionary<string, IData>();
//BridgeAdapter.ConnectionServer.DataManager.GetAllDatas(out datas);
//foreach (IData da in datas.Values)
//{
// // if(da.Name.Equals(name)
// // {
// Console.WriteLine(da.Name);
// // }
//}
// 修改人:wangkai,修改日期:20231109,修改版本:1.7.0,修改原因:DataServer移动到DataCenter项目
// 修改人:wangkai,修改日期:20231130,修改版本:1.8.0,修改原因:FA异常捕获
try
{
RemoteValueInfo dataInfo = DataServer.Instance.GetDataValue("CTC", channelName);
channelVal = DataServer.Instance.ParseData(dataInfo);
}
catch (Exception ex)
{
Log.Error($"ReadSubstratePresenceIO failed! Error: {ex}");
}
return channelVal;
}
private string ReadIOValueString(string DataItemName)
{
string strRet = "";
// 修改人:wangkai,修改日期:20231130,修改版本:1.8.0,修改原因:FA异常捕获
try
{
//如果Port中有Carrier,即presence,则读出相应的Carrier ID,如果为Absent,则返回空。
// 修改人:wangkai,修改日期:20231109,修改版本:1.7.0,修改原因:DataServer移动到DataCenter项目
RemoteValueInfo dataInfo = DataServer.Instance.GetDataValue("TM", DataItemName);
strRet = DataServer.Instance.ParseData(dataInfo);
}
catch (Exception ex)
{
Log.Error($"ReadIOValueString failed! Error: {ex}");
}
return strRet;
}
private bool CheckILinkSubstrateInformation(string strModule, int nSlot, IE90SubstrateLocation pLocation)
{
bool bRetCode = true;
bool bSubstratePresent = false;
IE90Substrate ie90Substrate = null;
try
{
ie90Substrate = pLocation.GetSubstrate();
if (null != ie90Substrate)
{
bSubstratePresent = true;
}
else
{
bSubstratePresent = false;
}
}
catch
{
Log.Error("Unknown error!");
}
string strSubstratePresence = "WAFER_UNKNOWN";
strSubstratePresence = ReadSubstratePresenceIO(strModule, nSlot);
if (strSubstratePresence.Contains("WAFER_PRESENT") && !bSubstratePresent)
{
bRetCode = false;
// 修改人:wangkai,修改日期:20240201,修改版本:***,修改原因:AlarmManager合并到DataCenter中
AlarmServer.Instance.PostAlarm(E90_ALARM_ID.ToString());
//e90EquipmentEventHandler.E90Synchronization();
}
else if (strSubstratePresence.Contains("WAFER_ABSENT") && bSubstratePresent)
{
bRetCode = false;
// 修改人:wangkai,修改日期:20240201,修改版本:***,修改原因:AlarmManager合并到DataCenter中
AlarmServer.Instance.PostAlarm(E90_TRANSITION_ALARM_ID.ToString());
//e90EquipmentEventHandler.E90Synchronization();
}
else
{
//sonar
}
return bRetCode;
}
private bool CheckForILinkSubstratePresence(IE90SubstrateLocation pLocation)
{
bool bRetCode = true;
IE90Substrate ie90Substrate = null;
try
{
ie90Substrate = pLocation.GetSubstrate();
if (null != ie90Substrate)
{
bRetCode = false;
// 修改人:wangkai,修改日期:20240201,修改版本:***,修改原因:AlarmManager合并到DataCenter中
AlarmServer.Instance.PostAlarm(E90_TRANSITION_ALARM_ID.ToString());
//e90EquipmentEventHandler.E90Synchronization();
}
else
{
bRetCode = true;
}
}
catch
{
Log.Error("Unknown error!");
}
return bRetCode;
}
/// <summary>
/// 修改人:田百强 修改时间:20240929 修改原因:单元测试private 改为public 修改版本:**
/// </summary>
/// <param name="portName"></param>
/// <returns></returns>
public bool CheckForCTCSubstratePresence(string portName)
{
bool bRetCode = true;
string strPortName = portName;
string strModule = portName;
int nCapacity = 0;
List<PortModule> portModuleList = Globals.GetAllPortModuleList();
foreach (PortModule port in portModuleList)
{
if (port.Name.Equals(portName))
{
nCapacity = port.Capacity;
break;
}
}
string strSubstratePresence = "WAFER_UNKNOWN";
for (int nSlot = 1; nSlot < nCapacity; nSlot++)
{
strSubstratePresence = ReadSubstratePresenceIO(strModule, nSlot);
if (strSubstratePresence.Contains("WAFER_PRESENT"))
{
bRetCode = false;
// 修改人:wangkai,修改日期:20240201,修改版本:***,修改原因:AlarmManager合并到DataCenter中
AlarmServer.Instance.PostAlarm(E90_ALARM_ID.ToString());
//e90EquipmentEventHandler.E90Synchronization();
break;
}
}
return bRetCode;
}
private bool IsPMLoc(string strLoc)
{
if (strLoc.Substring(0, 2).Equals("PM"))
{
return true;
}
else
{
return false;
}
}
public bool UpdateLocation(string strLocation, string subID)
{
bool bRet = false;
lock (objectLock)
{
if (IsPMLoc(strLocation))
{
LocSubPair pLocPair = null;
//在m_PMSubstrateInfoList查找PM的Location,并为Substrate ID和该Location ID建立映射关系
foreach (PMSubstrateInfo pmSubInfo in m_PMSubstrateInfoList)
{
foreach (LocSubPair locSubPair in pmSubInfo.m_LocToSubstrIDMap)
{
if (strLocation == locSubPair.strLoc)
{
pLocPair = locSubPair;
pLocPair.strSubID = subID;
bRet = true;
break;
}
}
}
}
else
{
//If its going to carrier location and was in PM clear it in PM
//如果该Location不是PM,那么一定是Carrier,则移动的Substrate是从PM中移动到了Carrier中
//则应该Clear PM,即在m_PMSubstrateInfoList中找到该PM,把其strSubID置为“”。
if (-1 != strLocation.IndexOf("_slot"))//判断该Location是否为Carrier中的SubstrateLocation
{
foreach (PMSubstrateInfo pmSubInfo in m_PMSubstrateInfoList)
{
foreach (LocSubPair locSubPair in pmSubInfo.m_LocToSubstrIDMap)
{
if (subID == locSubPair.strSubID)
{
locSubPair.strSubID = "";
break;
}
}
}
}
}
//if it go into a cassette update in CarrierInfo
//如果该Substrate进入了一个Carrier则更新该Carrier的信息。
if (false == bRet)
{
string strCarID = "";
string strSlot = "";
int index = -1;
index = strLocation.IndexOf("_slot");
if (-1 != index)
{
strCarID = strLocation.Substring(0, index);
strSlot = strLocation.Substring(index, strLocation.Length - index);
int nPortID = 0;
nPortID = GetPort(strCarID);
if (0 != nPortID)
{
//get carrier info for that port
CarrierInfo pCarrierInfo = null;
if (GetCarInfoForPort(nPortID, ref pCarrierInfo))
{
pCarrierInfo.m_strCarID = strCarID;
bRet = UpdateCarInfo(pCarrierInfo, strCarID, subID, strSlot);
}
}
}
}
}
return bRet;
}
private int GetPort(string strCarID)
{
int nPortID = 0;
try
{
if (null == E87Server)
{
return 0;
}
IE87Carrier ie87Carrier = null;
ie87Carrier = E87Server.GetCarrier(strCarID);
if (null != ie87Carrier)
{
IE87Port ie87Port = null;
ie87Port = ie87Carrier.GetPort();
if (null != ie87Port)
{
nPortID = (int)ie87Port.GetPort();
}
}
}
catch
{
Log.Error("UNKNOWN ERROR in E90Manager::GetPort while retreving ports!");
}
return nPortID;
}
private bool GetCarInfoForPort(int nPortID, ref CarrierInfo pCarInfo)
{
bool bRet = false;
foreach (CarrierInfo carrierInfo in m_CarInfoList)
{
CarrierInfo carInfo = null;
carInfo = carrierInfo;
if (null != carInfo)
{
if (carInfo.m_lPortNo == nPortID)
{
pCarInfo = carInfo;
bRet = true;
break;
}
}
}
return bRet;
}
private bool UpdateCarInfo(CarrierInfo carrierInfo, string strCarID, string subID, string strSlot)
{
bool bRet = false;
foreach (LocSubPair pLocSubPair in carrierInfo.m_strSubstrLoc)
{
if (strSlot == pLocSubPair.strLoc)
{
pLo这一段让类实例化且单例的是哪一句
最新发布