Sic.Framework-Nanjing-Baishi/MECF.Framework.RT.Equipment.../HardwareUnits/Robots/HineAutomation/HAtmRobot.cs

817 lines
28 KiB
C#
Raw Normal View History

2023-04-13 11:51:03 +08:00
using Aitex.Core.RT.DataCenter;
using Aitex.Core.RT.Device;
using Aitex.Core.RT.Event;
using Aitex.Core.RT.Log;
using Aitex.Core.RT.OperationCenter;
using Aitex.Core.RT.SCCore;
using Aitex.Core.Util;
using Aitex.Sorter.Common;
using MECF.Framework.Common.Communications;
using MECF.Framework.Common.Equipment;
using MECF.Framework.Common.SubstrateTrackings;
using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Robot;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
namespace MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Robot.HineAutomation
{
public class HAtmRobot : Robot
{
#region properties
public override bool Error
{
get
{
return _exceuteErr;
}
}
public bool IsThetaBusy { get; set; }
public bool IsZBusy { get; set; }
public bool IsRadialBusy { get; set; }
public override bool Busy
{
get
{
return IsBusy || IsThetaBusy || IsZBusy || IsRadialBusy || (!_motionTimer.IsIdle() && _motionTimer.GetElapseTime() < _motionTime) /*|| ThetaAxisAddressPosition != _targetThetaAxisAddressPosition || ZAxisAddressPosition != _targetZAxisAddressPosition*/;
}
}
public override bool Moving
{
get
{
return IsBusy || IsThetaBusy || IsZBusy || IsRadialBusy || (!_motionTimer.IsIdle() && _motionTimer.GetElapseTime() < _motionTime) /*|| ThetaAxisAddressPosition != _targetThetaAxisAddressPosition || ZAxisAddressPosition != _targetZAxisAddressPosition*/;
}
}
public override bool WaferOnBlade1 => WaferPresentOnBlade1;
public bool IsBusy { private get; set; }
public bool IsRetract { get; set; }
public bool IsUp { get; set; }
public int ThetaAxisAddressPosition { get; set; }
public int ZAxisAddressPosition { get; set; }
public int RetractReqPos { get; set; }
public int RotateReqPos { get; set; }
public int ZReqPos { get; set; }
public int ZActPos { get; set; }
public string SlotMap { get; set; }
public Dictionary<string, string> ErrorCodeReference;
public R_TRIG IsRotationAxisUnreferencedTrig { get; set; }
public R_TRIG IsExtensionAxisUnreferencedTrig { get; set; }
public R_TRIG IsZAxisUnreferencedTrig { get; set; }
public bool IsHomed => _isHomed;
#endregion
#region fields
private HAtmConnection _connection;
private string _address;
private PeriodicJob _thread;
private LinkedList<HandlerBase> _lstHandler = new LinkedList<HandlerBase>();
private object _lockerHandlerList = new object();
private R_TRIG _trigError = new R_TRIG();
private R_TRIG _trigWarningMessage = new R_TRIG();
private string _lastError = string.Empty;
private int _errorCode;
private int _targetThetaAxisAddressPosition;
private int _targetZAxisAddressPosition;
private HandlerBase _waferMoveHandler;
private HandlerBase _homeHandler;
private bool _isHomed;
private bool _isSimulator;
//private bool _isFirstHome = true;
private bool _enableLog;
private bool _isPowerUp = true;
private DeviceTimer _motionTimer = new DeviceTimer();
private int _motionTime = 1000;
private Dictionary<string, int> _motionTimeDic;
private ModuleName _lastTarget;
private R_TRIG _zAxisHomeTrig = new R_TRIG();
#endregion
public HAtmRobot(string module)
: base(module, module, module, module, "", RobotType.HAtm)
{
IsRetract = true;
}
static bool CheckAddressPort(string s)
{
bool isLegal;
Regex regex = new Regex(@"^((2[0-4]\d|25[0-5]|[1]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[1]?\d\d?)\:([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-6][0-5][0-5][0-3][0-5])$");//CheckAddressPort
Match match = regex.Match(s);
if (match.Success)
{
isLegal = true;
}
else
{
isLegal = false;
}
return isLegal;
}
public override bool Initialize()
{
_address = SC.GetStringValue($"{Module}.Address");
_isSimulator = SC.GetValue<bool>("System.IsSimulatorMode");
_enableLog = SC.GetValue<bool>($"{Module}.EnableLogMessage");
_connection = new HAtmConnection(_address);
if (CheckAddressPort(_address))
{
if (_connection.Connect())
{
EV.PostInfoLog(Module, $"{Module} connected");
}
}
else EV.PostWarningLog(Module, $"{Module} Adress is illegal");
_thread = new PeriodicJob(50, OnTimer, $"{Module} MonitorHandler", true);
DATA.Subscribe($"{Name}.IsHomed", () => _isHomed);
DATA.Subscribe($"{Name}.IsConnected", () => _connection.IsConnected);
OP.Subscribe("Robot.QueryOperationalStatus", (string cmd, object[] args) =>
{
QueryOperationalStatus();
return true;
});
_motionTimeDic = new Dictionary<string, int>()
{
{ $"{ModuleName.Cassette}.{ModuleName.PM}.Picking",4000},
{ $"{ModuleName.PM}.{ModuleName.PM}.Picking",1500},
{ $"{ModuleName.PM}.{ModuleName.Cooling}.Picking",2400},
{ $"{ModuleName.Cooling}.{ModuleName.Cooling}.Picking",1500},
{ $"{ModuleName.Cooling}.{ModuleName.PM}.Picking",2400},
{ $"{ModuleName.Cassette}.{ModuleName.Cooling}.Picking",2200},
{ $"{ModuleName.Cooling}.{ModuleName.Cassette}.Picking",2200},
{ $"{ModuleName.Cassette}.{ModuleName.Cassette}.Picking",1500},
{ $"{ModuleName.PM}.{ModuleName.Cassette}.Picking",4000},
{ $"{ModuleName.TMRobot}.{ModuleName.Cassette}.Picking",5000},
{ $"{ModuleName.TMRobot}.{ModuleName.Cooling}.Picking",3700},
{ $"{ModuleName.TMRobot}.{ModuleName.PM}.Picking",2200},
{ $"System.{ModuleName.Cassette}.Picking",5000},
{ $"System.{ModuleName.Cooling}.Picking",3700},
{ $"System.{ModuleName.PM}.Picking",2200},
};
ErrorCodeReference = new Dictionary<string, string>()
{
{ "S0","Serial response timeout"},
{ "S1","Illegal sc interrupt"},
{ "S2","Parity Error"},
{ "S3","Input Buffer overflow"},
{ "C0","Command not recognized"},
{ "C1","Illegal Z-Axis Command Address"},
{ "C2","Illegal Radial Axis Command Address"},
{ "C3","Illegal Theta Axis Command Address"},
{ "C4","Illegal Pick wafer on pan"},
{ "C5","Illegal Place wafer not on pan"},
{ "C6","Illegal action command error present"},
{ "C7","Command overrun Hatm5.0 Busy"},
{ "C8","Illegal command not in learn mode"},
{ "C9","Illegal Search hardware not present"},
{ "CA","Illegal Fetch hardware not present"},
{ "CB","Illegal Action data not valid"},
{ "CC","Illegal Action Request Queue overrun"},
{ "CD","Illegal Action Overcurrent Latch Set"},
{ "CE","Illegal Action Interlock Open"},
{ "CF","Loss of Vacuum Detect"},
{ "D0","Illegal Pitch"},
{ "D1","Illegal Offset"},
{ "D2","Illegal number of slots"},
{ "D3","Illegal rotate position"},
{ "D4","Illegal difference value"},
{ "D5","Parameter missing"},
{ "D6","Illegal Set Command"},
{ "D7","Illegal Option"},
{ "D8","Illegal Category"},
{ "D9","Illegal Bias"},
{ "DA","Illegal Bias Set, Z not valid"},
{ "DB","Invalid rotational speed data(exceeded the legal percent range)"},
{ "DC","Invalid z-axis speed data (exceeded the legal percent range)"},
{ "I0","Z requested position is out of range"},
{ "I1","Theta requested position is out of range"},
{ "I2","Radial requested position is out of range"},
{ "I3","Illegal Z Position"},
{ "I4","Illegal Theta Position"},
{ "I5","Illegal Data"},
{ "A0","Theta Axis action timeout"},
{ "A1","Z-Axis action timeout"},
{ "A2","Radial Axis action timeout"},
{ "A3","Theta overtravel"},
{ "A4","Theta Axis reference detect"},
{ "A5","Z-Axis reference detect"},
{ "A6","Function timeout"},
{ "A7","Loss of Retrace on Rotate"},
{ "A8","Cassette Interlock error"},
{ "A9","Overcurrent shutdown"},
{ "P0","Bad Checksum Theta Parameters"},
{ "P1","Bad Checksum Z Parameters"},
{ "P2","Bad Checksum Radial Parameters"},
{ "F0","Flipper current limit activated"},
{ "F1","Flipper device error"},
{ "F2","Flipper over voltage"},
{ "F3","Flipper over temperature"},
{ "F4","Flipper continuous current limit"},
{ "F5","No Flipper is installed"},
};
IsRotationAxisUnreferencedTrig = new R_TRIG();
IsExtensionAxisUnreferencedTrig = new R_TRIG();
IsZAxisUnreferencedTrig = new R_TRIG();
return base.Initialize();
}
private bool OnTimer()
{
try
{
_connection.MonitorTimeout();
_connection.MonitorConnection(SC.GetValue<int>("TMRobot.ReconnectCount"), out bool retried);
if (retried)
{
lock (_lockerHandlerList)
{
_lstHandler.Clear();
}
}
if (!_connection.IsConnected || _connection.IsCommunicationError)
{
return true;
}
if (_connection.IsBusy)
return true;
HandlerBase handler = null;
lock (_lockerHandlerList)
{
if (_isPowerUp)
{
if(SC.GetValue<bool>("TMRobot.AllCommandsHaveResponse"))
_lstHandler.AddFirst(new SetCommandResponseHandler(this));
_isPowerUp = false;
}
if (_lstHandler.Count == 0)
{
_lstHandler.AddLast(new QueryOperationalStatusHandler(this));
_lstHandler.AddLast(new QueryAllAxisStatusHandler(this));
_lstHandler.AddLast(new QueryThetaAxisStatusHandler(this));
_lstHandler.AddLast(new QueryZAxisStatusHandler(this));
_lstHandler.AddLast(new QueryRadialAxisStatusHandler(this));
_lstHandler.AddLast(new QueryPositionHandler(this));
}
if (_lstHandler.Count > 0)
{
handler = _lstHandler.First.Value;
_lstHandler.RemoveFirst();
}
}
if (handler != null)
{
handler.SendText = ((HAtmHandler)handler).Package();
_connection.Execute(handler);
}
if (_waferMoveHandler != null)
{
var pick = _waferMoveHandler as PickHandler;
if (pick != null && WaferOnBlade1 && WaferManager.Instance.CheckHasWafer(pick.Target, pick.Slot))
{
WaferManager.Instance.WaferMoved(pick.Target, pick.Slot, ModuleHelper.Converter(Name), (int)Hand.Blade1);
CmdBladeTarget = $"{pick.Target}.Retract";
}
var place = _waferMoveHandler as PlaceHandler;
if (place != null && !WaferOnBlade1 && WaferManager.Instance.CheckHasWafer(ModuleHelper.Converter(Name), (int)Hand.Blade1))
{
WaferManager.Instance.WaferMoved(ModuleHelper.Converter(Name), (int)Hand.Blade1, place.Target, place.Slot);
CmdBladeTarget = $"{place.Target}.Retract";
}
}
if (_waferMoveHandler != null && !Moving)
{
_lastTarget = ((HAtmHandler)_waferMoveHandler).Target;
((HAtmHandler)_waferMoveHandler).Update();
_waferMoveHandler = null;
_motionTimer.Stop();
}
if (_homeHandler != null)
{
_zAxisHomeTrig.CLK = ZReqPos == 0;
if(_zAxisHomeTrig.Q)//means ZAXis is homed
{
ChangeRobotBladeTarget();
}
if (!Moving)
{
_lastTarget = ((HAtmHandler)_homeHandler).Target;
_isHomed = true;
_homeHandler = null;
_motionTimer.Stop();
}
}
}
catch (Exception ex)
{
LOG.Write(ex);
}
return true;
}
private void ChangeRobotBladeTarget()
{
//CmdBladeTarget = $"{ModuleHelper.Converter(RobotDevice.Name)}.Retract";
int cassette = 180;
int cooling = 110;
int pm = 55;
if(Math.Abs(RotateReqPos - cassette) < 10)
{
CmdBladeTarget = $"{ModuleName.Cassette}.{ModuleHelper.Converter(Name)}.Retract";
return;
}
if (Math.Abs(RotateReqPos - cooling) < 10)
{
CmdBladeTarget = $"{ModuleName.Cooling}.{ModuleHelper.Converter(Name)}.Retract";
return;
}
if (Math.Abs(RotateReqPos - pm) < 10)
{
CmdBladeTarget = $"{ModuleName.PM}.{ModuleHelper.Converter(Name)}.Retract";
return;
}
if (Math.Abs(RotateReqPos) < 10)
{
CmdBladeTarget = $"{ModuleHelper.Converter(Name)}.{ModuleHelper.Converter(Name)}.Retract";
return;
}
CmdBladeTarget = $"{ModuleHelper.Converter(Name)}.Retract";
}
public override void Monitor()
{
}
public override void Reset()
{
_trigError.RST = true;
_trigWarningMessage.RST = true;
IsRotationAxisUnreferencedTrig.RST = true;
IsExtensionAxisUnreferencedTrig.RST = true;
IsZAxisUnreferencedTrig.RST = true;
_connection.Reset();
_exceuteErr = false;
lock (_lockerHandlerList)
{
_lstHandler.AddFirst(new ResetHandler(this));
}
_motionTimer.Stop();
_zAxisHomeTrig.RST = true;
_isHomed = false;
base.Reset();
}
public void SetErrorCode(int errorCode)
{
_errorCode = errorCode;
}
public void SetError(string reason)
{
_trigWarningMessage.CLK = true;
if (_trigWarningMessage.Q)
{
EV.PostWarningLog(Module, $"{Module} error, {reason}");
lock (_lockerHandlerList)
{
_lstHandler.AddFirst(new QueryErrorHandler(this));
}
}
_exceuteErr = true;
}
public override void OnDataChanged(string package)
{
}
public override bool Home(out string reason)
{
reason = string.Empty;
var handler = new HomeHandler(this);
//if (_lstHandler.Count > 0 && Moving && !_isFirstHome)
//{
// reason = "Robot busy, please wait or abort.";
// EV.PostMessage(Name, EventEnum.DefaultWarning, string.Format("{0} {1} {2}", this.Name, handler.Name.ToString(), reason));
// return false;
//}
SetBusy();
_exceuteErr = false;
_targetThetaAxisAddressPosition = 0;
_targetZAxisAddressPosition = 0;
ThetaAxisAddressPosition = -1;
ZAxisAddressPosition = -1;
lock (_lockerHandlerList)
{
_lstHandler.AddFirst(handler);
if(SC.GetValue<bool>("TMRobot.AllCommandsHaveResponse"))
_lstHandler.AddFirst(new SetCommandResponseHandler(this));
}
_homeHandler = handler;
_isHomed = false;
//_isFirstHome = false;
_enableLog = SC.GetValue<bool>($"{Module}.EnableLogMessage");
IsThetaBusy = true;
IsZBusy = true;
IsRadialBusy = true;
_motionTimer.Start(0);
_zAxisHomeTrig.RST = true;
return true;
}
public bool Pick(ModuleName target, int slot, out string reason)
{
reason = string.Empty;
var handler = new PickHandler(this, target, slot);
if (_lstHandler.Count > 0 && Moving)
{
reason = "Robot busy, please wait or abort.";
EV.PostMessage(Name, EventEnum.DefaultWarning, string.Format("{0} {1} {2}", this.Name, handler.Name.ToString(), reason));
return false;
}
SetBusy();
_targetThetaAxisAddressPosition = RobotConvertor.Chamber2ThetaAxisPosition(target);
_targetZAxisAddressPosition = RobotConvertor.ChamberSlot2ZAxisPosition(target, slot);
ThetaAxisAddressPosition = -1;
ZAxisAddressPosition = -1;
lock (_lockerHandlerList)
{
_lstHandler.AddFirst(handler);
}
_waferMoveHandler = handler;
IsThetaBusy = true;
IsZBusy = true;
IsRadialBusy = true;
_motionTimer.Start(0);
if(_isSimulator)
WaferPresentOnBlade1 = false;
return true;
}
public bool Place(ModuleName target, int slot, out string reason)
{
reason = string.Empty;
var handler = new PlaceHandler(this, target, slot);
if (_lstHandler.Count > 0 && Moving)
{
reason = "Robot busy, please wait or abort.";
EV.PostMessage(Name, EventEnum.DefaultWarning, string.Format("{0} {1} {2}", this.Name, handler.Name.ToString(), reason));
return false;
}
SetBusy();
_targetThetaAxisAddressPosition = RobotConvertor.Chamber2ThetaAxisPosition(target);
_targetZAxisAddressPosition = RobotConvertor.ChamberSlot2ZAxisPosition(target, slot);
ThetaAxisAddressPosition = -1;
ZAxisAddressPosition = -1;
lock (_lockerHandlerList)
{
_lstHandler.AddFirst(handler);
}
_waferMoveHandler = handler;
IsThetaBusy = true;
IsZBusy = true;
IsRadialBusy = true;
_motionTimer.Start(0);
if (_isSimulator)
WaferPresentOnBlade1 = true;
return true;
}
public bool GotoExtend(ModuleName target, int slot, bool isPick, bool isUp, out string reason)
{
reason = string.Empty;
var handler = new GotoHandler(this, target, slot, isPick, isUp);
if (_lstHandler.Count > 0 && Moving)
{
reason = "Robot busy, please wait or abort.";
EV.PostMessage(Name, EventEnum.DefaultWarning, string.Format("{0} {1} {2}", this.Name, handler.Name.ToString(), reason));
return false;
}
SetBusy();
_targetThetaAxisAddressPosition = RobotConvertor.Chamber2ThetaAxisPosition(target);
_targetZAxisAddressPosition = RobotConvertor.ChamberSlot2ZAxisPosition(target, slot);
ThetaAxisAddressPosition = -1;
ZAxisAddressPosition = -1;
lock (_lockerHandlerList)
{
_lstHandler.AddFirst(handler);
}
_waferMoveHandler = handler;
IsThetaBusy = true;
IsZBusy = true;
IsRadialBusy = true;
_motionTimer.Start(0);
return true;
}
public bool ZAxisMove(ModuleName target, int slot, bool isUp, out string reason)
{
reason = string.Empty;
var handler = new ZAxisMoveHandler(this, target, slot, isUp);
if (_lstHandler.Count > 0 && Moving)
{
reason = "Robot busy, please wait or abort.";
EV.PostMessage(Name, EventEnum.DefaultWarning, string.Format("{0} {1} {2}", this.Name, handler.Name.ToString(), reason));
return false;
}
_targetZAxisAddressPosition = RobotConvertor.ChamberSlot2ZAxisPosition(target, slot);
ZAxisAddressPosition = -1;
lock (_lockerHandlerList)
{
_lstHandler.AddFirst(handler);
}
IsZBusy = true;
_motionTimer.Start(0);
return true;
}
public bool PlaceRetract(ModuleName target, int slot, out string reason)
{
reason = string.Empty;
var handler = new PlaceRetractHandler(this, target, slot);
if (_lstHandler.Count > 0 && Moving)
{
reason = "Robot busy, please wait or abort.";
EV.PostMessage(Name, EventEnum.DefaultWarning, string.Format("{0} {1} {2}", this.Name, handler.Name.ToString(), reason));
return false;
}
SetBusy();
_targetThetaAxisAddressPosition = RobotConvertor.Chamber2ThetaAxisPosition(target);
_targetZAxisAddressPosition = RobotConvertor.ChamberSlot2ZAxisPosition(target, slot);
ThetaAxisAddressPosition = -1;
ZAxisAddressPosition = -1;
lock (_lockerHandlerList)
{
_lstHandler.AddFirst(handler);
}
_waferMoveHandler = handler;
IsThetaBusy = true;
IsZBusy = true;
IsRadialBusy = true;
_motionTimer.Start(0);
return true;
}
public bool PickRetract(ModuleName target, int slot, bool isNeedWaferMove, out string reason)
{
reason = string.Empty;
var handler = new PickRetractHandler(this, target, slot, isNeedWaferMove);
if (_lstHandler.Count > 0 && Moving)
{
reason = "Robot busy, please wait or abort.";
EV.PostMessage(Name, EventEnum.DefaultWarning, string.Format("{0} {1} {2}", this.Name, handler.Name.ToString(), reason));
return false;
}
SetBusy();
_targetThetaAxisAddressPosition = RobotConvertor.Chamber2ThetaAxisPosition(target);
_targetZAxisAddressPosition = RobotConvertor.ChamberSlot2ZAxisPosition(target, slot);
ThetaAxisAddressPosition = -1;
ZAxisAddressPosition = -1;
lock (_lockerHandlerList)
{
_lstHandler.AddFirst(handler);
}
_waferMoveHandler = handler;
IsThetaBusy = true;
IsZBusy = true;
IsRadialBusy = true;
_motionTimer.Start(0);
return true;
}
public void Abort()
{
lock (_lockerHandlerList)
{
_lstHandler.AddFirst(new AbortHandler(this));
}
_waferMoveHandler = null;
_homeHandler = null;
_motionTimer.Stop();
_zAxisHomeTrig.RST = true;
}
public void QueryAllAxisStatus()
{
lock (_lockerHandlerList)
{
_lstHandler.AddFirst(new QueryAllAxisStatusHandler(this));
}
}
public void QueryError()
{
lock (_lockerHandlerList)
{
_lstHandler.AddFirst(new QueryErrorHandler(this));
}
}
public void SetSpeed()
{
lock (_lockerHandlerList)
{
_lstHandler.AddFirst(new SetThetaSpeedHandler(this, SC.GetValue<int>("TMRobot.Speed"), SC.GetValue<int>("TMRobot.Speed")));
_lstHandler.AddFirst(new SetReachSpeedHandler(this, SC.GetValue<int>("TMRobot.Speed"), SC.GetValue<int>("TMRobot.Speed")));
}
}
public void QueryOperationalStatus()
{
lock (_lockerHandlerList)
{
_lstHandler.AddFirst(new QueryOperationalStatusHandler(this));
}
}
public bool VacuumOn(out string reason)
{
reason = string.Empty;
var handler = new VacuumOnHandler(this);
//if (_lstHandler.Count > 0)
//{
// reason = "Robot busy, please wait or abort.";
// EV.PostMessage(Name, EventEnum.DefaultWarning, string.Format("{0} {1} {2}", this.Name, handler.Name.ToString(), reason));
// return false;
//}
lock (_lockerHandlerList)
{
_lstHandler.AddFirst(handler);
}
return true;
}
public bool VacuumOff(out string reason)
{
reason = string.Empty;
var handler = new VacuumOffHandler(this);
//if (_lstHandler.Count > 0)
//{
// reason = "Robot busy, please wait or abort.";
// EV.PostMessage(Name, EventEnum.DefaultWarning, string.Format("{0} {1} {2}", this.Name, handler.Name.ToString(), reason));
// return false;
//}
lock (_lockerHandlerList)
{
_lstHandler.AddFirst(handler);
}
return true;
}
public bool WaferMap(ModuleName target, out string reason)
{
reason = string.Empty;
var handler = new WaferMapHandler(this, target);
if (_lstHandler.Count > 0 && Moving)
{
reason = "Robot busy, please wait or abort.";
EV.PostMessage(Name, EventEnum.DefaultWarning, string.Format("{0} {1} {2}", this.Name, handler.Name.ToString(), reason));
return false;
}
SetBusy();
_targetThetaAxisAddressPosition = RobotConvertor.Chamber2ThetaAxisPosition(target);
ThetaAxisAddressPosition = -1;
ZAxisAddressPosition = -1;
lock (_lockerHandlerList)
{
_lstHandler.AddFirst(handler);
}
IsThetaBusy = true;
IsZBusy = true;
IsRadialBusy = true;
_motionTimer.Start(0);
return true;
}
public bool GetWaferMap(ModuleName target, out string reason)
{
reason = string.Empty;
var handler = new QueryWaferMapHandler(this, target);
SlotMap = string.Empty;
lock (_lockerHandlerList)
{
_lstHandler.AddFirst(handler);
}
return true;
}
private void SetBusy()
{
//IsBusy || IsThetaBusy || IsZBusy || IsRadialBusy
IsBusy = true;
IsThetaBusy = true;
IsZBusy = true;
IsRadialBusy = true;
}
}
}