using System; using System.Collections.Generic; using Aitex.Core.RT.Event; using Aitex.Core.RT.SCCore; using Aitex.Core.Util; using MECF.Framework.Common.Equipment; namespace EFEM.RT.Modules { public class RobotOffsetConfig : Singleton { public enum MotionName { GET, PUT, EXCHANGE } private string[] scOffsetsLoadLock = new string[] { "Robot.OffsetForLL.LLAGET", "Robot.OffsetForLL.LLAPUT", "Robot.OffsetForLL.LLAEXCHANGE", "Robot.OffsetForLL.LLBGET", "Robot.OffsetForLL.LLBPUT", "Robot.OffsetForLL.LLBEXCHANGE", "Robot.OffsetForLL.LL1GET", "Robot.OffsetForLL.LL1PUT", "Robot.OffsetForLL.LL1EXCHANGE", "Robot.OffsetForLL.LL2GET", "Robot.OffsetForLL.LL2PUT", "Robot.OffsetForLL.LL2EXCHANGE", "Robot.OffsetForLL.LL3GET", "Robot.OffsetForLL.LL3PUT", "Robot.OffsetForLL.LL3EXCHANGE", "Robot.OffsetForLL.LL4GET", "Robot.OffsetForLL.LL4PUT", "Robot.OffsetForLL.LL4EXCHANGE", "Robot.OffsetForLL.LL5GET", "Robot.OffsetForLL.LL5PUT", "Robot.OffsetForLL.LL5EXCHANGE", "Robot.OffsetForLL.LL6GET", "Robot.OffsetForLL.LL6PUT", "Robot.OffsetForLL.LL6EXCHANGE", "Robot.OffsetForLL.LL7GET", "Robot.OffsetForLL.LL7PUT", "Robot.OffsetForLL.LL7EXCHANGE", "Robot.OffsetForLL.LL8GET", "Robot.OffsetForLL.LL8PUT", "Robot.OffsetForLL.LL8EXCHANGE", }; private string[] scOffsets = new string[] { "Robot.OffsetForLP.Type1", "Robot.OffsetForLP.Type2", "Robot.OffsetForLP.Type3", "Robot.OffsetForLP.Type4", "Robot.OffsetForLP.Type5", "Robot.OffsetForLP.Type6", "Robot.OffsetForLP.Type7", "Robot.OffsetForLP.Type8", "Robot.OffsetForLP.Type9", "Robot.OffsetForLP.Type10", "Robot.OffsetForLP.Type11", "Robot.OffsetForLP.Type12", "Robot.OffsetForLP.Type13", "Robot.OffsetForLP.Type14", "Robot.OffsetForLP.Type15", "Robot.OffsetForLP.Type16", "Robot.OffsetForLP.Type17", "Robot.OffsetForLP.Type18", "Robot.OffsetForLP.Type19", "Robot.OffsetForLP.Type20" }; private Dictionary> _offsetsForLoadLock = new Dictionary>(); private Dictionary> _offsetsForLoadPort = new Dictionary>(); /// /// Get offset for different cassette type /// /// Load Port Name /// Reference for x /// Reference for y /// Reference for z /// out reason /// return whether success or not public bool GetOffset(ModuleName chamber, ref int x, ref int y, ref int z, out string reason) { x = 0; y = 0; z = 0; reason = ""; if (!ModuleHelper.IsLoadPort(chamber)) return true; string scNameType = $"LoadPort.{chamber.ToString().Replace("LP", "LoadPort")}CassetteType"; if (!SC.ContainsItem(scNameType)) { reason = $"Not found {chamber} foup type system config item"; return false; } string type = SC.GetStringValue(scNameType); if (string.IsNullOrEmpty(type.Trim())) { reason = $"{chamber} foup type system config can not be empty"; return false; } UpdateOffsetConfigForLoadPort(); if (!_offsetsForLoadPort.ContainsKey(type)) { reason = $"did not find {chamber} {type} type robot offset config"; return false; } x = _offsetsForLoadPort[type].Item1; y = _offsetsForLoadPort[type].Item2; z = _offsetsForLoadPort[type].Item3; return true; } /// /// Get offset for get/put/exchange motion on Load Lock /// /// LLA/LLB /// MotionName /// Reference for x /// Reference for y /// Reference for z /// out reason /// return whether success or not public bool GetOffset(ModuleName chamber,MotionName ePutOrGet, ref int x, ref int y, ref int z, out string reason) { x = 0; y = 0; z = 0; reason = ""; string scNameType = $"Robot.OffsetForLL.{chamber.ToString()}{ePutOrGet.ToString()}"; if (!SC.ContainsItem(scNameType)) { reason = $"Not found {chamber} foup type system config item"; return false; } string type = SC.GetStringValue(scNameType); if (string.IsNullOrEmpty(type.Trim())) { reason = $"{chamber} foup type system config can not be empty"; return false; } UpdateOffsetConfigForLoadLock(); if (!_offsetsForLoadLock.ContainsKey(scNameType)) { reason = $"did not find {chamber} {type} type robot offset config"; return false; } x = _offsetsForLoadLock[scNameType].Item1; y = _offsetsForLoadLock[scNameType].Item2; z = _offsetsForLoadLock[scNameType].Item3; return true; } private void UpdateOffsetConfigForLoadPort() { _offsetsForLoadPort.Clear(); //有配置错误的SC,这里忽略。 foreach (var sc in scOffsets) { string[] config = SC.ContainsItem(sc) ? SC.GetStringValue(sc).Split(',') : null; if (config == null || config.Length != 4) { continue; } if (string.IsNullOrEmpty(config[0])) continue; int x = 0; int y = 0; int z = 0; if (!int.TryParse(config[1].Trim(), out x)) continue; if (!int.TryParse(config[2].Trim(), out y)) continue; if (!int.TryParse(config[3].Trim(), out z)) continue; if (x < SC.GetValue("Robot.Offset.OffsetXMin") || x > SC.GetValue("Robot.Offset.OffsetXMax") || y < SC.GetValue("Robot.Offset.OffsetYMin") || y > SC.GetValue("Robot.Offset.OffsetYMax") || z < SC.GetValue("Robot.Offset.OffsetZMin") || z > SC.GetValue("Robot.Offset.OffsetZMax")) { EV.PostWarningLog(ModuleNameString.System, $"Robot offset config {sc} value out of range"); continue; } _offsetsForLoadPort[config[0]] = Tuple.Create(x, y, z); } } private void UpdateOffsetConfigForLoadLock() { _offsetsForLoadLock.Clear(); var i = 0; //有配置错误的SC,这里忽略。 foreach (var sc in scOffsetsLoadLock) { string[] config = SC.ContainsItem(sc) ? SC.GetStringValue(sc).Split(',') : null; if (config == null || config.Length != 3) { continue; } int x = 0; int y = 0; int z = 0; if (!int.TryParse(config[0].Trim(), out x)) continue; if (!int.TryParse(config[1].Trim(), out y)) continue; if (!int.TryParse(config[2].Trim(), out z)) continue; if (x < SC.GetValue("Robot.Offset.OffsetXMin") || x > SC.GetValue("Robot.Offset.OffsetXMax") || y < SC.GetValue("Robot.Offset.OffsetYMin") || y > SC.GetValue("Robot.Offset.OffsetYMax") || z < SC.GetValue("Robot.Offset.OffsetZMin") || z > SC.GetValue("Robot.Offset.OffsetZMax")) { EV.PostWarningLog(ModuleNameString.System, $"Robot offset config {sc} value out of range"); continue; } _offsetsForLoadLock[scOffsetsLoadLock[i]] = Tuple.Create(x, y, z); i++; } } } }