using Aitex.Core.RT.Routine; using Aitex.Core.RT.SCCore; using Aitex.Core.Util; using Aitex.Sorter.Common; using DocumentFormat.OpenXml.Bibliography; using MECF.Framework.Common.Equipment; using MECF.Framework.Common.Schedulers; using MECF.Framework.Common.SubstrateTrackings; using MECF.Framework.RT.EquipmentLibrary.LogicUnits; using System; using System.Collections.Generic; using FurnaceRT.Equipments.FIMSs; using FurnaceRT.Equipments.LPs; using FurnaceRT.Equipments.Stockers; using FurnaceRT.Equipments.Systems; using FurnaceRT.Equipments.WaferRobots; using static FurnaceRT.Equipments.FIMSs.FIMSModule; namespace FurnaceRT.Equipments.CarrierRobots { public class CarrierRobotPlace : ModuleRoutine, IRoutine { enum RoutineStep { SetLPLoad, SetLPUnload, SetBufferTargetPosition, SetBufferMoveTo, Delay, Goto, Place, DoorOpen, DoorClose, RobotRequestCassettePresent, CheckCassetteInfoByRobotSensor, SetStageLock, SetStageUnlock, CheckBeforePlace, CheckGotoFinish, SetRobotActionCommand, } private CarrierRobotModule _cassetteRobotModule; private ModuleName _destination; private int _destinationSlot; private Hand _blade; private int _timeout = 0; private RD_TRIG _holdTrig = new RD_TRIG(); private R_TRIG _emergencyStopTrig = new R_TRIG(); private R_TRIG _pauseTrig = new R_TRIG(); private R_TRIG _resumeTrig = new R_TRIG(); private RoutineStep _routineStep; private double _durationTime = 0; private bool _isHasAlarm = false; private bool _needStartCheck = true; public CarrierRobotPlace(CarrierRobotModule cassetteModule) { _cassetteRobotModule = cassetteModule; Module = cassetteModule.Module; Name = "Place"; } public void Init(ModuleName destination, int destinationSlot, Hand blade, bool isHasAlarm) { _destination = destination; _destinationSlot = destinationSlot; _blade = blade; var para = new List { _destination, _destinationSlot, _blade, true }; _cassetteRobotModule.PlaceCassetteFailAlarm.RetryMessage = (int)CarrierRobotModule.MSG.PlaceRetry; _cassetteRobotModule.PlaceCassetteFailAlarm.RetryMessageParas = para.ToArray(); _cassetteRobotModule.PlaceCassetteTimeoutAlarm.RetryMessage = (int)CarrierRobotModule.MSG.PlaceRetry; _cassetteRobotModule.PlaceCassetteTimeoutAlarm.RetryMessageParas = para.ToArray(); _cassetteRobotModule.RequestCassettePresentFailAlarm.RetryMessage = (int)CarrierRobotModule.MSG.PlaceRetry; _cassetteRobotModule.RequestCassettePresentFailAlarm.RetryMessageParas = para.ToArray(); _cassetteRobotModule.RequestCassettePresentTimeoutAlarm.RetryMessage = (int)CarrierRobotModule.MSG.PlaceRetry; _cassetteRobotModule.RequestCassettePresentTimeoutAlarm.RetryMessageParas = para.ToArray(); _cassetteRobotModule.SetStageValveFailAlarm.RetryMessage = (int)CarrierRobotModule.MSG.PlaceRetry; _cassetteRobotModule.SetStageValveFailAlarm.RetryMessageParas = para.ToArray(); _cassetteRobotModule.SetStageValveTimeout.RetryMessage = (int)CarrierRobotModule.MSG.PlaceRetry; _cassetteRobotModule.SetStageValveTimeout.RetryMessageParas = para.ToArray(); _cassetteRobotModule.RobotHasError.RetryMessage = (int)CarrierRobotModule.MSG.PlaceRetry; _cassetteRobotModule.RobotHasError.RetryMessageParas = para.ToArray(); _cassetteRobotModule.ShutterOpenTimeoutAlarm.RetryMessage = (int)CarrierRobotModule.MSG.PlaceRetry; _cassetteRobotModule.ShutterOpenTimeoutAlarm.RetryMessageParas = para.ToArray(); _cassetteRobotModule.ShutterCloseTimeoutAlarm.RetryMessage = (int)CarrierRobotModule.MSG.PlaceRetry; _cassetteRobotModule.ShutterCloseTimeoutAlarm.RetryMessageParas = para.ToArray(); _isHasAlarm = isHasAlarm; if (!_isHasAlarm) _needStartCheck = true; } public Result Start(params object[] objs) { // 抛出过alarm就不reset if (!_isHasAlarm) { Reset(); } else { _historySteps.Remove((int)_routineStep); _isHasAlarm = false; ResetState(); } _holdTrig.RST = true; _emergencyStopTrig.RST = true; _pauseTrig.RST = true; _resumeTrig.RST = true; _timeout = SC.GetValue($"{Module}.MotionTimeout"); if (_needStartCheck) { if(!Singleton.Instance.Modules.ContainsKey(_destination)) { _cassetteRobotModule.PlaceCassetteFailAlarm.Set($"place to {_destination} failed for not install"); return Result.FAIL; } if (ModuleHelper.IsLoadPort(_destination)) { var lpModule = Singleton.Instance.Modules[_destination] as LoadPortModule; if (lpModule == null) { _cassetteRobotModule.PlaceCassetteFailAlarm.Set($"place to {_destination} failed for not install"); return Result.FAIL; } if (lpModule != null && !lpModule.CheckReadyForTransfer(ModuleHelper.Converter(Module), _blade, _destinationSlot, EnumTransferType.Place, out string reason)) { _cassetteRobotModule.PlaceCassetteFailAlarm.Set($"place to {_destination} failed for {reason}"); return Result.FAIL; } } else if (_destination == ModuleName.FIMS1 || _destination == ModuleName.FIMS2) { var fims = Singleton.Instance.Modules[_destination] as FIMSModule; if (fims == null) { _cassetteRobotModule.PlaceCassetteFailAlarm.Set($"place to {_destination} failed for not install"); return Result.FAIL; } if (fims != null && !fims.CheckReadyForTransfer(ModuleHelper.Converter(Module), _blade, _destinationSlot, EnumTransferType.Place, out string reason)) { _cassetteRobotModule.PlaceCassetteFailAlarm.Set($"place to {_destination} failed for {reason}"); return Result.FAIL; } if (!SC.GetValue("System.IsSimulatorMode")) { if (fims != null && fims.IsFoupExist) { _cassetteRobotModule.PlaceCassetteFailAlarm.Set($"place to {_destination} failed for carrier is present"); return Result.FAIL; } } } else { var stockerModule = Singleton.Instance.Modules[_destination] as StockerModule; if (stockerModule == null) { _cassetteRobotModule.PlaceCassetteFailAlarm.Set($"place to {_destination} failed for not install"); return Result.FAIL; } if (!SC.GetValue("System.IsSimulatorMode")) { if (stockerModule != null && stockerModule.IsFoupPresent) { _cassetteRobotModule.PlaceCassetteFailAlarm.Set($"place to {_destination} failed for carrier is present"); return Result.FAIL; } } } if (SC.GetValue("System.IsSimulatorMode")) { if (!CarrierManager.Instance.CheckHasCarrier(ModuleName.CarrierRobot, 0)) { _cassetteRobotModule.BladeCassetteNotPresentWarning.Set($"{ModuleName.CarrierRobot} cassette not present"); return Result.FAIL; } } else { if (!_cassetteRobotModule.CarrierRobotDevice.IsWaferPresenceOnBlade1 || !CarrierManager.Instance.CheckHasCarrier(ModuleName.CarrierRobot, 0)) { _cassetteRobotModule.BladeCassetteNotPresentWarning.Set($"{ModuleName.CarrierRobot} cassette not present"); return Result.FAIL; } } if (!CarrierManager.Instance.CheckNoCarrier(_destination, 0)) { _cassetteRobotModule.PlaceCassetteFailAlarm.Set($"place to {_destination} failed for carrier is present"); return Result.FAIL; } } Notify($"Start"); return Result.RUN; } public void Abort() { _cassetteRobotModule.ResetRobotActionCommand(); _cassetteRobotModule.Stop(); (Singleton.Instance.Modules[_destination] as ITransferTarget)?.NoteTransferStop(ModuleHelper.Converter(_cassetteRobotModule.Module), _blade, _destinationSlot, EnumTransferType.Place); } public override Result Monitor() { try { PauseRountine(_cassetteRobotModule.CarrierRobotDevice.IsPause); if (_cassetteRobotModule.CarrierRobotDevice.IsPause) return Result.RUN; CheckBeforePlace((int)RoutineStep.CheckBeforePlace, _destination, _destinationSlot, _blade); if (ModuleHelper.IsBufferStocker(_destination)) { Goto((int)RoutineStep.Goto, _destination, _destinationSlot, _blade, false, _timeout); SetBufferTargetPosition((int)RoutineStep.SetBufferTargetPosition, _destination, _timeout); SetBufferMoveTo((int)RoutineStep.SetBufferMoveTo, _destination, _timeout); CheckGotoFinish((int)RoutineStep.CheckGotoFinish, _destination, _timeout); } if (_destination == ModuleName.LP1 || _destination == ModuleName.LP2) { Goto((int)RoutineStep.Goto, _destination, _destinationSlot, _blade, false, _timeout); SaferDoorOpen((int)RoutineStep.DoorOpen, true, _timeout); CheckGotoFinish((int)RoutineStep.CheckGotoFinish, _destination, _timeout); SetLPLoad((int)RoutineStep.SetLPLoad, _destination, _timeout); } if (_cassetteRobotModule.TrigActionCommand != null) SetRobotActionCommand((int)RoutineStep.SetRobotActionCommand, _destination, _timeout); Place((int)RoutineStep.Place, _destination, _destinationSlot, _blade, _timeout); if (_destination == ModuleName.LP1 || _destination == ModuleName.LP2) { SetLPUnload((int)RoutineStep.SetLPUnload, _destination, _timeout); SaferDoorOpen((int)RoutineStep.DoorClose, false, _timeout); } //RobotRequestCassettePresent((int)RoutineStep.RobotRequestCassettePresent, _blade, _timeout); CheckCassetteInfoByRobotSensor((int)RoutineStep.CheckCassetteInfoByRobotSensor, _blade, false); } catch (RoutineBreakException) { return Result.RUN; } catch (RoutineFaildException ex) { _cassetteRobotModule.ResetRobotActionCommand(); PlaceEndInfo(); return Result.FAIL; } _cassetteRobotModule.ResetRobotActionCommand(); PlaceEndInfo(); Notify("Finished"); return Result.DONE; } private void PlaceEndInfo() { (Singleton.Instance.Modules[_destination] as ITransferTarget)?.NoteTransferStop(ModuleHelper.Converter(_cassetteRobotModule.Module), _blade, _destinationSlot, EnumTransferType.Place); var stockerModule = Singleton.Instance.Modules[_destination] as StockerModule; var stockerFoupInfo = CarrierManager.Instance.GetCarrier(_destination); stockerFoupInfo.UICarrierStatusEnum = CarrierStatus.READY; Singleton.Instance.SetVisibility(stockerFoupInfo, true); var carrierRobotFoupInfo = CarrierManager.Instance.GetCarrier(ModuleName.CarrierRobot); Singleton.Instance.SetVisibility(carrierRobotFoupInfo, false); } private void SetLPLoad(int id, ModuleName source, int timeout) { Tuple ret = ExecuteAndWait(id, () => { Notify($"Set {source} load"); var lp = Singleton.Instance.Modules[source] as LoadPortModule; if (lp != null) lp.LPDevice.Load(out string reason); return true; }, () => { return true; }, timeout * 1000); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { throw (new RoutineFaildException()); } else if (ret.Item2 == Result.TIMEOUT) //timeout { throw (new RoutineFaildException()); } else throw (new RoutineBreakException()); } } private void SetLPUnload(int id, ModuleName source, int timeout) { Tuple ret = ExecuteAndWait(id, () => { Notify($"Set {source} unload"); var lp = Singleton.Instance.Modules[source] as LoadPortModule; if (lp != null) lp.LPDevice.Unload(out string reason); return true; }, () => { return true; }, timeout * 1000); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { throw (new RoutineFaildException()); } else if (ret.Item2 == Result.TIMEOUT) //timeout { throw (new RoutineFaildException()); } else throw (new RoutineBreakException()); } } private void SetRobotActionCommand(int id, ModuleName source, int timeout) { _routineStep = (RoutineStep)Enum.Parse(typeof(RoutineStep), id.ToString()); Tuple ret = ExecuteAndWait(id, () => { Notify($"Set robot action command target position {source}"); _cassetteRobotModule.SetRobotActionCommand(source, EnumTransferType.Place); return true; }, () => { return _cassetteRobotModule.CheckRobotActionCommand(source, EnumTransferType.Place); }, timeout * 1000); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { _cassetteRobotModule.PlaceCassetteTimeoutAlarm.Set($"place to {source} failed for robot action command interlock"); throw (new RoutineFaildException()); } else if (ret.Item2 == Result.TIMEOUT) //timeout { _cassetteRobotModule.PlaceCassetteTimeoutAlarm.Set($"timeout over {timeout} seconds"); throw (new RoutineFaildException()); } else throw (new RoutineBreakException()); } } private void SetBufferTargetPosition(int id, ModuleName source, int timeout) { _routineStep = (RoutineStep)Enum.Parse(typeof(RoutineStep), id.ToString()); Tuple ret = ExecuteAndWait(id, () => { Notify($"Set buffer target position {source}"); _cassetteRobotModule.SetBufferTargetPosition(source.ToString()); return true; }, () => { return _cassetteRobotModule.CheckBufferTargetPosition(source.ToString()); }, timeout * 1000); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { _cassetteRobotModule.PlaceCassetteFailAlarm.Set($"place to {source} failed for set buffer target position"); throw (new RoutineFaildException()); } else if (ret.Item2 == Result.TIMEOUT) //timeout { _cassetteRobotModule.PlaceCassetteFailAlarm.Set($"timeout over {timeout} seconds"); throw (new RoutineFaildException()); } else throw (new RoutineBreakException()); } } private void SetBufferMoveTo(int id, ModuleName target, int timeout) { _routineStep = (RoutineStep)Enum.Parse(typeof(RoutineStep), id.ToString()); Tuple ret = ExecuteAndWait(id, () => { Notify($"Set buffer move to {target}"); _cassetteRobotModule.SetBufferMoveTo(); return true; }, () => { return _cassetteRobotModule.BufferDevice.IsReady && _cassetteRobotModule.BufferDevice.IsInPosition; }, timeout * 1000); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { _cassetteRobotModule.PlaceCassetteFailAlarm.Set($"place to {target} failed for robot error, error code={_cassetteRobotModule.CarrierRobotDevice.ErrorCode}"); throw (new RoutineFaildException()); } else if (ret.Item2 == Result.TIMEOUT) //timeout { _cassetteRobotModule.PlaceCassetteTimeoutAlarm.Set($"timeout over {timeout} seconds"); throw (new RoutineFaildException()); } else throw (new RoutineBreakException()); } } private void Place(int id, ModuleName target, int slot, Hand hand, int timeout) { _routineStep = (RoutineStep)Enum.Parse(typeof(RoutineStep), id.ToString()); Tuple ret = ExecuteAndWait(id, () => { Notify($"Send place to {target} command to robot device"); string reason; (Singleton.Instance.Modules[target] as ITransferTarget)?.NoteTransferStart(ModuleHelper.Converter(_cassetteRobotModule.Module), hand, slot, EnumTransferType.Place); if (!_cassetteRobotModule.RobotPlace(target, slot, hand, out reason)) { //_cassetteRobotModule.PlaceCassetteFailAlarm.Description = reason; _cassetteRobotModule.PlaceCassetteFailAlarm.Set(reason); return false; } return true; }, () => { if (_cassetteRobotModule.CarrierRobotDevice.IsReady() && !_cassetteRobotModule.CarrierRobotDevice.IsError) { return true; } return false; }, timeout * 1000); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { //_cassetteRobotModule.PlaceCassetteFailAlarm.Description = $"{_cassetteRobotModule.CassetteRobotDevice.ErrorCode}"; _cassetteRobotModule.PlaceCassetteFailAlarm.Set($"place to {target} failed for robot error, error code={_cassetteRobotModule.CarrierRobotDevice.ErrorCode}"); throw (new RoutineFaildException()); } else if (ret.Item2 == Result.TIMEOUT) //timeout { //_cassetteRobotModule.PlaceCassetteTimeoutAlarm.Description = $"timeout over {timeout} seconds"; _cassetteRobotModule.PlaceCassetteTimeoutAlarm.Set($"timeout over {timeout} seconds"); throw (new RoutineFaildException()); } else throw (new RoutineBreakException()); } } private void RobotRequestCassettePresent(int id, Hand hand, int timeout) { Tuple ret = ExecuteAndWait(id, () => { Notify("Request cassette present"); if (!_cassetteRobotModule.RequestCassettePresent(hand, out string reason)) { //_cassetteRobotModule.RequestCassettePresentFailAlarm.Description = reason; _cassetteRobotModule.RequestCassettePresentFailAlarm.Set(reason); return false; } return true; }, () => { if (_cassetteRobotModule.CarrierRobotDevice.IsReady() && !_cassetteRobotModule.CarrierRobotDevice.IsError) { return true; } return false; }, timeout * 1000); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { throw (new RoutineFaildException()); } else if (ret.Item2 == Result.TIMEOUT) //timeout { //_cassetteRobotModule.RequestCassettePresentTimeoutAlarm.Description = $"timeout over {timeout} seconds"; _cassetteRobotModule.RequestCassettePresentTimeoutAlarm.Set($"timeout over {timeout} seconds"); throw (new RoutineFaildException()); } else throw (new RoutineBreakException()); } } private void CheckCassetteInfoByRobotSensor(int id, Hand hand, bool isAfterPick) { Tuple ret = Execute(id, () => { Notify($"Check cassette info by robot RQ present"); if (SC.GetValue("System.IsSimulatorMode")) return true; if (hand == Hand.Blade1 || hand == Hand.Both) { if (!isAfterPick && _cassetteRobotModule.CarrierRobotDevice.IsWaferPresenceOnBlade1) { //_cassetteRobotModule.RobotSensorFoundCassetteOnBladeAfterPlaceAlarm.Description = "Cassette Robot sensor found cassette on blade 1"; _cassetteRobotModule.RobotSensorFoundCassetteOnBladeAfterPlaceAlarm.Set("Cassette Robot sensor found cassette on blade 1"); return false; } if (isAfterPick && !_cassetteRobotModule.CarrierRobotDevice.IsWaferPresenceOnBlade1) { //_cassetteRobotModule.RobotSensorNotFoundCassetteOnBladeAfterPickAlarm.Description = "Cassette Robot sensor no cassette on blade 1"; _cassetteRobotModule.RobotSensorNotFoundCassetteOnBladeAfterPickAlarm.Set("Cassette Robot sensor no cassette on blade 1"); return false; } } if (hand == Hand.Blade2 || hand == Hand.Both) { if (!isAfterPick && _cassetteRobotModule.CarrierRobotDevice.IsWaferPresenceOnBlade2) { //_cassetteRobotModule.RobotSensorFoundCassetteOnBladeAfterPlaceAlarm.Description = "Cassette Robot sensor found cassette on blade 2"; _cassetteRobotModule.RobotSensorFoundCassetteOnBladeAfterPlaceAlarm.Set("Cassette Robot sensor found cassette on blade 2"); return false; } if (isAfterPick && !_cassetteRobotModule.CarrierRobotDevice.IsWaferPresenceOnBlade2) { //_cassetteRobotModule.RobotSensorNotFoundCassetteOnBladeAfterPickAlarm.Description = "Cassette Robot sensor no cassette on blade 2"; _cassetteRobotModule.RobotSensorNotFoundCassetteOnBladeAfterPickAlarm.Set("Cassette Robot sensor no cassette on blade 2"); return false; } } return true; }); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { //_cassetteRobotModule.CheckCassetteInformationFailAlarm.Description = $"check cassette info failed."; _cassetteRobotModule.CheckCassetteInformationFailAlarm.Set($"check cassette info failed."); throw (new RoutineFaildException()); } else throw (new RoutineBreakException()); } } private void CheckBeforePlace(int id, ModuleName target, int slot, Hand blade) { Tuple ret = Execute(id, () => { Notify($"Check place to {target} condition"); string reason = string.Empty; if (_cassetteRobotModule.CarrierRobotDevice.IsError) { _cassetteRobotModule.PlaceCassetteFailAlarm.Set($"place to {target} failed for robot error, error code={_cassetteRobotModule.CarrierRobotDevice.ErrorCode}"); return false; } if (!_cassetteRobotModule.CarrierRobotDevice.IsReady()) { _cassetteRobotModule.PlaceCassetteFailAlarm.Set($"place to {target} failed for robot isn't Ready"); return false; } if (!CarrierManager.Instance.CheckNoCarrier(_destination, 0)) { _cassetteRobotModule.PlaceCassetteFailAlarm.Set($"place to {_destination} failed for pod is present"); return false; } if (blade == Hand.Blade1) { if (!CarrierManager.Instance.CheckNoCarrier(target, 0)) { _cassetteRobotModule.PlaceCassetteFailAlarm.Set($"place to {target} failed for {target} has carrier"); return false; } if (!CarrierManager.Instance.CheckHasCarrier(Module, 0)) { _cassetteRobotModule.PlaceCassetteFailAlarm.Set($"place to {target} failed for blade no carrier"); return false; } } else if (blade == Hand.Blade2) { if (!CarrierManager.Instance.CheckNoCarrier(target, 0)) { _cassetteRobotModule.PlaceCassetteFailAlarm.Set($"place to {target} failed for {target} has carrier"); return false; } if (!CarrierManager.Instance.CheckHasCarrier(Module, 0)) { _cassetteRobotModule.PlaceCassetteFailAlarm.Set($"place to {target} failed for blade no carrier"); return false; } } else { if (!CarrierManager.Instance.CheckNoCarrier(target, 0)) { _cassetteRobotModule.PlaceCassetteFailAlarm.Set($"place to {target} failed for {target} has carrier"); return false; } if (!CarrierManager.Instance.CheckHasCarrier(Module, 0)) { _cassetteRobotModule.PlaceCassetteFailAlarm.Set($"place to {target} failed for blade no carrier"); return false; } } return true; }); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { throw (new RoutineFaildException()); } } _needStartCheck = false; } private void Goto(int id, ModuleName target, int slot, Hand hand, bool isPickReady, int timeout) { _routineStep = (RoutineStep)Enum.Parse(typeof(RoutineStep), id.ToString()); Tuple ret = ExecuteAndWait(id, () => { Notify($"Send goto to {target} command to robot device"); string reason; _cassetteRobotModule.RobotGoto(target, slot, hand, isPickReady, out reason); return true; }, () => { return true; }, timeout * 1000); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { _cassetteRobotModule.GotoFailAlarm.Set($"goto to {target} failed for robot error, error code={_cassetteRobotModule.CarrierRobotDevice.ErrorCode}"); throw (new RoutineFaildException()); } else if (ret.Item2 == Result.TIMEOUT) //timeout { _cassetteRobotModule.GotoTimeoutAlarm.Set($"timeout over {timeout} seconds"); throw (new RoutineFaildException()); } else throw (new RoutineBreakException()); } } private void CheckGotoFinish(int id, ModuleName target, int timeout) { Tuple ret = ExecuteAndWait(id, () => { Notify($"Check goto to {target} command finish"); return true; }, () => { if (_cassetteRobotModule.CarrierRobotDevice.IsError) return null; if (_cassetteRobotModule.CarrierRobotDevice.IsReady() && !_cassetteRobotModule.CarrierRobotDevice.IsError) { return true; } return false; }, timeout * 1000); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { _cassetteRobotModule.GotoFailAlarm.Set($"goto to {target} failed for robot error, error code={_cassetteRobotModule.CarrierRobotDevice.ErrorCode}"); throw (new RoutineFaildException()); } else if (ret.Item2 == Result.TIMEOUT) //timeout { _cassetteRobotModule.GotoTimeoutAlarm.Set($"timeout over {timeout} seconds"); throw (new RoutineFaildException()); } else throw (new RoutineBreakException()); } } private void SaferDoorOpen(int id, bool isOpen, int timeout) { Tuple ret = ExecuteAndWait(id, () => { Notify($"Shutter Door {(isOpen ? "Open" : "Close")}"); if (isOpen) _cassetteRobotModule.DoorDevice.Open(); else _cassetteRobotModule.DoorDevice.Close(); if (isOpen) (Singleton.Instance.Modules[_destination] as LoadPortModule)?.LPDevice.Unclamp(out _); return true; }, () => { return isOpen ? _cassetteRobotModule.DoorDevice.OpenCloseStatus == Devices.DeviceStatus.Open && (Singleton.Instance.Modules[_destination] as LoadPortModule).IsReleased : _cassetteRobotModule.DoorDevice.OpenCloseStatus == Devices.DeviceStatus.Close; }, timeout * 1000); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { throw new RoutineFaildException(); } else if (ret.Item2 == Result.TIMEOUT) //timeout { if (isOpen) _cassetteRobotModule.ShutterOpenTimeoutAlarm.Set($"timeout over {timeout} seconds"); else _cassetteRobotModule.ShutterCloseTimeoutAlarm.Set($"timeout over {timeout} seconds"); throw (new RoutineFaildException()); } else throw new RoutineBreakException(); } } } }