Sic.Framework-Nanjing-Baishi/MECF.Framework.RT.Equipment.../HardwareUnits/Robots/GuanAng/GAPlcRobot.cs

1884 lines
66 KiB
C#
Raw Normal View History

2023-04-13 11:51:03 +08:00
using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Linq;
using System.Text;
using Aitex.Core.Common.DeviceData;
using Aitex.Core.RT.Device;
using Aitex.Core.RT.Device.Unit;
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 MECF.Framework.Common.Communications;
using MECF.Framework.Common.Device.Bases;
using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Common;
using Newtonsoft.Json;
using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Robots.RobotBase;
using MECF.Framework.Common.Equipment;
using MECF.Framework.Common.SubstrateTrackings;
using System.Threading;
using Aitex.Core.Common;
using Aitex.Core.RT.DataCenter;
using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Robot;
using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.LoadPorts.LoadPortBase;
using System.Xml;
using Aitex.Core.RT.IOCore;
using Aitex.Core.RT.Routine;
using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Robots;
using MECF.Framework.Common.CommonData;
using EventType = Aitex.Core.RT.Event.EventType;
namespace Aitex.Core.RT.Device.Unit
{
public class GAPlcRobot:RobotBaseDevice
{
public GAPlcRobot(string module,XmlElement node,string ioModule =""): base(node.GetAttribute("module"), node.GetAttribute("id"))
{
base.Module = node.GetAttribute("module");//string.IsNullOrEmpty(node.GetAttribute("module")) ? module : node.GetAttribute("module");
base.Name = node.GetAttribute("id");
ioModule = node.GetAttribute("ioModule");
_aiCurrentXPos_L = ParseAiNode("AI_CurrentXPos_L", node, ioModule);
_aiCurrentXPos_H = ParseAiNode("AI_CurrentXPos_H", node, ioModule);
_aiCurrentYPos_L = ParseAiNode("AI_CurrentYPos_L", node, ioModule);
_aiCurrentYPos_H = ParseAiNode("AI_CurrentYPos_H", node, ioModule);
_aiCurrentZPos_L = ParseAiNode("AI_CurrentZPos_L", node, ioModule);
_aiCurrentZPos_H = ParseAiNode("AI_CurrentZPos_H", node, ioModule);
_aiZAxisPitch_L = ParseAiNode("AI_ZAxisPitch_L", node, ioModule);
_aiZAxisPitch_H = ParseAiNode("AI_ZAxisPitch_H", node, ioModule);
_aiZAxisFirstPos_L = ParseAiNode("AI_ZAxisFirstPos_L", node, ioModule);
_aiZAxisFirstPos_H = ParseAiNode("AI_ZAxisFirstPos_H", node, ioModule);
_aiZAxisPlacePos_L = ParseAiNode("AI_ZAxisPlacePos_L", node, ioModule);
_aiZAxisPlacePos_H = ParseAiNode("AI_ZAxisPlacePos_H", node, ioModule);
_aiXAxisMoveDistance_L = ParseAiNode("AI_XAxisMoveDistance_L", node, ioModule);
_aiXAxisMoveDistance_H = ParseAiNode("AI_XAxisMoveDistance_H", node, ioModule);
_aiYAxisMoveDistance_L = ParseAiNode("AI_YAxisMoveDistance_L", node, ioModule);
_aiYAxisMoveDistance_H = ParseAiNode("AI_YAxisMoveDistance_H", node, ioModule);
_aiZAxisMoveSpeed_L = ParseAiNode("AI_ZAxisMoveSpeed_L", node, ioModule);
_aiZAxisMoveSpeed_H = ParseAiNode("AI_ZAxisMoveSpeed_H", node, ioModule);
_aiXAxisMoveSpeed_L = ParseAiNode("AI_XAxisMoveSpeed_L", node, ioModule);
_aiXAxisMoveSpeed_H = ParseAiNode("AI_XAxisMoveSpeed_H", node, ioModule);
_aiYAxisMoveSpeed_L = ParseAiNode("AI_YAxisMoveSpeed_L", node, ioModule);
_aiYAxisMoveSpeed_H = ParseAiNode("AI_YAxisMoveSpeed_H", node, ioModule);
_aiTargetPos = ParseAiNode("AI_TargetPos", node, ioModule);
_aoZAxisPitch_L = ParseAoNode("AO_ZAxisPitch_L", node, ioModule);
_aoZAxisPitch_H = ParseAoNode("AO_ZAxisPitch_H", node, ioModule);
_aoZAxisFirstPos_L = ParseAoNode("AO_ZAxisFirstPos_L", node, ioModule);
_aoZAxisFirstPos_H = ParseAoNode("AO_ZAxisFirstPos_H", node, ioModule);
_aoZAxisPlacePos_L = ParseAoNode("AO_ZAxisPlacePos_L", node, ioModule);
_aoZAxisPlacePos_H = ParseAoNode("AO_ZAxisPlacePos_H", node, ioModule);
_aoXAxisMoveDistance_L = ParseAoNode("AO_XAxisMoveDistance_L", node, ioModule);
_aoXAxisMoveDistance_H = ParseAoNode("AO_XAxisMoveDistance_H", node, ioModule);
_aoYAxisMoveDistance_L = ParseAoNode("AO_YAxisMoveDistance_L", node, ioModule);
_aoYAxisMoveDistance_H = ParseAoNode("AO_YAxisMoveDistance_H", node, ioModule);
_aoZAxisMoveSpeed_L = ParseAoNode("AO_ZAxisMoveSpeed_L", node, ioModule);
_aoZAxisMoveSpeed_H = ParseAoNode("AO_ZAxisMoveSpeed_H", node, ioModule);
_aoXAxisMoveSpeed_L = ParseAoNode("AO_XAxisMoveSpeed_L", node, ioModule);
_aoXAxisMoveSpeed_H = ParseAoNode("AO_XAxisMoveSpeed_H", node, ioModule);
_aoYAxisMoveSpeed_L = ParseAoNode("AO_YAxisMoveSpeed_L", node, ioModule);
_aoYAxisMoveSpeed_H = ParseAoNode("AO_YAxisMoveSpeed_H", node, ioModule);
_aoTargetPos = ParseAoNode("AO_TargetPos", node, ioModule);
_aoXMoveFwdDistance_L = ParseAoNode("AO_XMoveFwdDistance_L", node, ioModule);
_aoXMoveFwdDistance_H = ParseAoNode("AO_XMoveFwdDistance_H", node, ioModule);
_aoYMoveFwdDistance_L = ParseAoNode("AO_YMoveFwdDistance_L", node, ioModule);
_aoYMoveFwdDistance_H = ParseAoNode("AO_YMoveFwdDistance_H", node, ioModule);
_aoZMoveFwdDistance_L = ParseAoNode("AO_ZMoveFwdDistance_L", node, ioModule);
_aoZMoveFwdDistance_H = ParseAoNode("AO_ZMoveFwdDistance_H", node, ioModule);
_aoXMoveRevDistance_L = ParseAoNode("AO_XMoveRevDistance_L", node, ioModule);
_aoXMoveRevDistance_H = ParseAoNode("AO_XMoveRevDistance_H", node, ioModule);
_aoYMoveRevDistance_L = ParseAoNode("AO_YMoveRevDistance_L", node, ioModule);
_aoYMoveRevDistance_H = ParseAoNode("AO_YMoveRevDistance_H", node, ioModule);
_aoZMoveRevDistance_L = ParseAoNode("AO_ZMoveRevDistance_L", node, ioModule);
_aoZMoveRevDistance_H = ParseAoNode("AO_ZMoveRevDistance_H", node, ioModule);
_diReset_Ack = ParseDiNode("DI_Reset_Ack", node, ioModule);
_diHome_Ack = ParseDiNode("DI_Home_Ack", node, ioModule);
_diSave_Ack = ParseDiNode("DI_Save_Ack", node, ioModule);
_diPick_Ack = ParseDiNode("DI_Pick_Ack", node, ioModule);
_diPlace_Ack = ParseDiNode("DI_Place_Ack", node, ioModule);
_diX_Fwd_Ack = ParseDiNode("DI_X_Fwd_Ack", node, ioModule);
_diX_Rev_Ack = ParseDiNode("DI_X_Rev_Ack", node, ioModule);
_diY_Fwd_Ack = ParseDiNode("DI_Y_Fwd_Ack", node, ioModule);
_diY_Rev_Ack = ParseDiNode("DI_Y_Rev_Ack", node, ioModule);
_diZ_Fwd_Ack = ParseDiNode("DI_Z_Fwd_Ack", node, ioModule);
_diZ_Rev_Ack = ParseDiNode("DI_Z_Rev_Ack", node, ioModule);
_diPlugError = ParseDiNode("DI_PlugError", node, ioModule);
_diZMotionError = ParseDiNode("DI_ZMotionError", node, ioModule);
_diXMotionError = ParseDiNode("DI_XMotionError", node, ioModule);
_diYMotionError = ParseDiNode("DI_YMotionError", node, ioModule);
_diZMotionOutLimit = ParseDiNode("DI_ZMotionOutLimit", node, ioModule);
_diXMotionOutLimit = ParseDiNode("DI_XMotionOutLimit", node, ioModule);
_diYMotionOutLimit = ParseDiNode("DI_YMotionOutLimit", node, ioModule);
_diPLCReady = ParseDiNode("DI_PLCReady", node, ioModule);
_diMotionIdle = ParseDiNode("DI_MotionIdle", node, ioModule);
_doResetCmd = ParseDoNode("DO_ResetCmd", node, ioModule);
_doHomeCmd = ParseDoNode("DO_HomeCmd", node, ioModule);
_doSaveCmd = ParseDoNode("DO_SaveCmd", node, ioModule);
_doPickCmd = ParseDoNode("DO_PickCmd", node, ioModule);
_doPlaceCmd = ParseDoNode("DO_PlaceCmd", node, ioModule);
_doX_FwdCmd = ParseDoNode("DO_X_FwdCmd", node, ioModule);
_doX_RevCmd = ParseDoNode("DO_X_RevCmd", node, ioModule);
_doY_FwdCmd = ParseDoNode("DO_Y_FwdCmd", node, ioModule);
_doY_RevCmd = ParseDoNode("DO_Y_RevCmd", node, ioModule);
_doZ_FwdCmd = ParseDoNode("DO_Z_FwdCmd", node, ioModule);
_doZ_RevCmd = ParseDoNode("DO_Z_RevCmd", node, ioModule);
EV.Subscribe(new EventItem("Alarm", AlarmRobotError, $"Robot occurred error.", EventLevel.Alarm, EventType.EventUI_Notify));
DATA.Subscribe($"{Name}.PLCReady", () => _diPLCReady.Value);
DATA.Subscribe($"{Name}.MotionIdle", () => _diMotionIdle.Value);
DATA.Subscribe($"{Name}.SlotPitch", () => _slotPitch);
DATA.Subscribe($"{Name}.FirstZPosition", () => _zFirstPosition);
DATA.Subscribe($"{Name}.PlaceWaferZPosition", () => _zPutWaferPosition);
DATA.Subscribe($"{Name}.XMoveDistance", () => _xMoveDistance);
DATA.Subscribe($"{Name}.YMoveDistance", () => _yMoveDistance);
DATA.Subscribe($"{Name}.ZMoveSpeed", () => _zMoveSpeed);
DATA.Subscribe($"{Name}.YMoveSpeed", () => _yMoveSpeed);
DATA.Subscribe($"{Name}.XMoveSpeed", () => _xMoveSpeed);
DATA.Subscribe($"{Name}.CurrentXPosition", () => _currentXPosition);
DATA.Subscribe($"{Name}.CurrentYPosition", () => _currentYPosition);
DATA.Subscribe($"{Name}.CurrentZPosition", () => _currentZPosition);
_trigErrorOccurred = new R_TRIG();
_thread = new PeriodicJob(10, OnTimer, $"{Module}.{Name} MonitorHandler", true);
}
private string AlarmRobotError = "RobotOccurredError";
private AIAccessor _aiZAxisPitch_L;
private AIAccessor _aiZAxisPitch_H;
private AIAccessor _aiZAxisFirstPos_L;
private AIAccessor _aiZAxisFirstPos_H;
private AIAccessor _aiZAxisPlacePos_L;
private AIAccessor _aiZAxisPlacePos_H;
private AIAccessor _aiXAxisMoveDistance_L;
private AIAccessor _aiXAxisMoveDistance_H;
private AIAccessor _aiYAxisMoveDistance_L;
private AIAccessor _aiYAxisMoveDistance_H;
private AIAccessor _aiZAxisMoveSpeed_L;
private AIAccessor _aiZAxisMoveSpeed_H;
private AIAccessor _aiXAxisMoveSpeed_L;
private AIAccessor _aiXAxisMoveSpeed_H;
private AIAccessor _aiYAxisMoveSpeed_L;
private AIAccessor _aiYAxisMoveSpeed_H;
private AIAccessor _aiTargetPos;
private AIAccessor _aiCurrentXPos_L;
private AIAccessor _aiCurrentXPos_H;
private AIAccessor _aiCurrentYPos_L;
private AIAccessor _aiCurrentYPos_H;
private AIAccessor _aiCurrentZPos_L;
private AIAccessor _aiCurrentZPos_H;
private AOAccessor _aoZAxisPitch_L;
private AOAccessor _aoZAxisPitch_H;
private AOAccessor _aoZAxisFirstPos_L;
private AOAccessor _aoZAxisFirstPos_H;
private AOAccessor _aoZAxisPlacePos_L;
private AOAccessor _aoZAxisPlacePos_H;
private AOAccessor _aoXAxisMoveDistance_L;
private AOAccessor _aoXAxisMoveDistance_H;
private AOAccessor _aoYAxisMoveDistance_L;
private AOAccessor _aoYAxisMoveDistance_H;
private AOAccessor _aoZAxisMoveSpeed_L;
private AOAccessor _aoZAxisMoveSpeed_H;
private AOAccessor _aoXAxisMoveSpeed_L;
private AOAccessor _aoXAxisMoveSpeed_H;
private AOAccessor _aoYAxisMoveSpeed_L;
private AOAccessor _aoYAxisMoveSpeed_H;
private AOAccessor _aoTargetPos;
private AOAccessor _aoXMoveFwdDistance_L;
private AOAccessor _aoXMoveFwdDistance_H;
private AOAccessor _aoYMoveFwdDistance_L;
private AOAccessor _aoYMoveFwdDistance_H;
private AOAccessor _aoZMoveFwdDistance_L;
private AOAccessor _aoZMoveFwdDistance_H;
private AOAccessor _aoXMoveRevDistance_L;
private AOAccessor _aoXMoveRevDistance_H;
private AOAccessor _aoYMoveRevDistance_L;
private AOAccessor _aoYMoveRevDistance_H;
private AOAccessor _aoZMoveRevDistance_L;
private AOAccessor _aoZMoveRevDistance_H;
private DIAccessor _diReset_Ack;
private DIAccessor _diHome_Ack;
private DIAccessor _diSave_Ack;
private DIAccessor _diPick_Ack;
private DIAccessor _diPlace_Ack;
private DIAccessor _diX_Fwd_Ack;
private DIAccessor _diX_Rev_Ack;
private DIAccessor _diY_Fwd_Ack;
private DIAccessor _diY_Rev_Ack;
private DIAccessor _diZ_Fwd_Ack;
private DIAccessor _diZ_Rev_Ack;
private DIAccessor _diPlugError;
private DIAccessor _diZMotionError;
private DIAccessor _diXMotionError;
private DIAccessor _diYMotionError;
private DIAccessor _diZMotionOutLimit;
private DIAccessor _diXMotionOutLimit;
private DIAccessor _diYMotionOutLimit;
private DIAccessor _diPLCReady;
private DIAccessor _diMotionIdle;
private DOAccessor _doResetCmd;
private DOAccessor _doHomeCmd;
private DOAccessor _doSaveCmd;
private DOAccessor _doPickCmd;
private DOAccessor _doPlaceCmd;
private DOAccessor _doX_FwdCmd;
private DOAccessor _doX_RevCmd;
private DOAccessor _doY_FwdCmd;
private DOAccessor _doY_RevCmd;
private DOAccessor _doZ_FwdCmd;
private DOAccessor _doZ_RevCmd;
private PeriodicJob _thread;
private R_TRIG _trigErrorOccurred;
private int _currentXPosition
{
get
{
return TwoShortConvInt(_aiCurrentXPos_L.Value, _aiCurrentXPos_H.Value);
}
}
private int _currentYPosition
{
get
{
return TwoShortConvInt(_aiCurrentYPos_L.Value, _aiCurrentYPos_H.Value);
}
}
private int _currentZPosition
{
get
{
return TwoShortConvInt(_aiCurrentZPos_L.Value, _aiCurrentZPos_H.Value);
}
}
private int _slotPitch
{
get
{
return TwoShortConvInt(_aiZAxisPitch_L.Value, _aiZAxisPitch_H.Value);
}
}
private int _zFirstPosition
{
get
{
return TwoShortConvInt(_aiZAxisFirstPos_L .Value, _aiZAxisFirstPos_H.Value);
}
}
private int _zPutWaferPosition
{
get
{
return TwoShortConvInt(_aiZAxisPlacePos_L.Value, _aiZAxisPlacePos_H.Value);
}
}
private int _xMoveDistance
{
get
{
return TwoShortConvInt(_aiXAxisMoveDistance_L.Value, _aiXAxisMoveDistance_H.Value);
}
}
private int _yMoveDistance
{
get
{
return TwoShortConvInt(_aiYAxisMoveDistance_L.Value, _aiYAxisMoveDistance_H.Value);
}
}
private int _zMoveSpeed
{
get
{
return TwoShortConvInt(_aiZAxisMoveSpeed_L.Value, _aiZAxisMoveSpeed_H.Value);
}
}
private int _yMoveSpeed
{
get
{
return TwoShortConvInt(_aiYAxisMoveSpeed_L.Value, _aiYAxisMoveSpeed_H.Value);
}
}
private int _xMoveSpeed
{
get
{
return TwoShortConvInt(_aiXAxisMoveSpeed_L.Value, _aiXAxisMoveSpeed_H.Value);
}
}
private bool OnTimer()
{
_trigErrorOccurred.CLK =
_diPlugError.Value || _diZMotionError.Value
|| _diXMotionError.Value || _diYMotionError.Value || _diZMotionOutLimit.Value
|| _diXMotionOutLimit.Value || _diYMotionOutLimit.Value;
if(_trigErrorOccurred.Q)
{
EV.Notify(AlarmRobotError);
if (_diPlugError.Value)
{
EV.PostAlarmLog("Robot", $"Robot occurred error: _diPlugError.");
}
if (_diZMotionError.Value)
{
EV.PostAlarmLog("Robot", $"Robot occurred error: _diZMotionError.");
}
if (_diXMotionError.Value)
{
EV.PostAlarmLog("Robot", $"Robot occurred error: _diXMotionError.");
}
if (_diYMotionError.Value)
{
EV.PostAlarmLog("Robot", $"Robot occurred error: _diYMotionError.");
}
if (_diZMotionOutLimit.Value)
{
EV.PostAlarmLog("Robot", $"Robot occurred error: _diZMotionOutLimit.");
}
if (_diYMotionOutLimit.Value)
{
EV.PostAlarmLog("Robot", $"Robot occurred error: _diYMotionOutLimit.");
}
if (_diXMotionOutLimit.Value)
{
EV.PostAlarmLog("Robot", $"Robot occurred error: _diXMotionOutLimit.");
}
OnError("Robot Error");
}
return true;
}
#region Override Robot base function
private enum RobotStepEnum
{
ActionStep1,
ActionStep2,
ActionStep3,
ActionStep4,
ActionStep5,
ActionStep6,
ActionStep7,
ActionStep8,
ActionStep9,
ActionStep10,
ActionStep11,
ActionStep12,
ActionStep13,
ActionStep14,
ActionStep15,
ActionStep16,
}
private DateTime _dtActionStart;
protected override bool fClear(object[] param)
{
return true;
}
protected override bool fStartReadData(object[] param)
{
return true;
}
protected override bool fStartSetParameters(object[] param)
{
try
{
_aoZAxisPitch_L.Value = _aiZAxisPitch_L.Value;
_aoZAxisPitch_H.Value = _aiZAxisPitch_H.Value;
_aoZAxisFirstPos_L.Value = _aiZAxisFirstPos_L.Value;
_aoZAxisFirstPos_H.Value = _aiZAxisFirstPos_H.Value;
_aoZAxisPlacePos_L.Value = _aiZAxisPlacePos_L.Value;
_aoZAxisPlacePos_H.Value = _aiZAxisPlacePos_H.Value;
_aoXAxisMoveDistance_L.Value = _aiXAxisMoveDistance_L.Value;
_aoXAxisMoveDistance_H.Value = _aiXAxisMoveDistance_H.Value;
_aoYAxisMoveDistance_L.Value = _aiYAxisMoveDistance_L.Value;
_aoYAxisMoveDistance_H.Value = _aiYAxisMoveDistance_H.Value;
_aoZAxisMoveSpeed_L.Value = _aiZAxisMoveSpeed_L.Value;
_aoZAxisMoveSpeed_H.Value = _aiZAxisMoveSpeed_H.Value;
_aoXAxisMoveSpeed_L.Value = _aiXAxisMoveSpeed_L.Value;
_aoXAxisMoveSpeed_H.Value = _aiXAxisMoveSpeed_H.Value;
_aoYAxisMoveSpeed_L.Value = _aiYAxisMoveSpeed_L.Value;
_aoYAxisMoveSpeed_H.Value = _aiYAxisMoveSpeed_H.Value;
string setcommand = param[0].ToString();
int setvalue = Convert.ToInt32(param[1].ToString());
short lowbit=0, highbit=0;
IntConvTwoShort(setvalue, ref lowbit, ref highbit);
_dtActionStart = DateTime.Now;
ResetRoutine();
switch (setcommand)
{
case "SlotPitch":
_aoZAxisPitch_L.Value = lowbit;
_aoZAxisPitch_H.Value = highbit;
break;
case "FirstZPosition":
_aoZAxisFirstPos_L.Value = lowbit;
_aoZAxisFirstPos_H.Value = highbit;
break;
case "PlaceWaferZPosition":
_aoZAxisPlacePos_L.Value = lowbit;
_aoZAxisPlacePos_H.Value = highbit;
break;
case "XMoveDistance":
_aoXAxisMoveDistance_L.Value = lowbit;
_aoXAxisMoveDistance_H.Value = highbit;
break;
case "YMoveDistance":
_aoYAxisMoveDistance_L.Value = lowbit;
_aoYAxisMoveDistance_H.Value = highbit;
break;
case "ZMoveSpeed":
_aoZAxisMoveSpeed_L.Value = lowbit;
_aoZAxisMoveSpeed_H.Value = highbit;
break;
case "XMoveSpeed":
_aoXAxisMoveSpeed_L.Value = lowbit;
_aoXAxisMoveSpeed_H.Value = highbit;
break;
case "YMoveSpeed":
_aoYAxisMoveSpeed_L.Value = lowbit;
_aoYAxisMoveSpeed_H.Value = highbit;
break;
default:
return false;
}
}
catch(Exception ex)
{
LOG.Write(ex);
}
return true;
}
protected override bool fMonitorSetParamter(object[] param)
{
IsBusy = false;
if (DateTime.Now - _dtActionStart > TimeSpan.FromSeconds(RobotCommandTimeout))
{
OnError("Command execution timeout");
return true;
}
try
{
SetDoState((int)RobotStepEnum.ActionStep2, _doSaveCmd, true, Notify);
WaitDiState((int)RobotStepEnum.ActionStep3, RobotCommandTimeout, _diSave_Ack, true, Notify, Stop);
SetDoState((int)RobotStepEnum.ActionStep4, _doSaveCmd, false, Notify);
WaitDiState((int)RobotStepEnum.ActionStep5, RobotCommandTimeout, _diSave_Ack, false, Notify, Stop);
}
catch (RoutineBreakException)
{
return false;
}
catch (RoutineFaildException)
{
EV.PostAlarmLog("Alarm", "Pick wafer failed.");
OnError("PickFailed");
}
return true;
}
protected override bool fStartTransferWafer(object[] param)
{
return true;
}
protected override bool fStartUnGrip(object[] param)
{
return false;
}
protected override bool fStartGrip(object[] param)
{
return false;
}
protected override bool fStartGoTo(object[] param)
{
return false;
}
protected override bool fStartMapWafer(object[] param)
{
return false;
}
protected override bool fStartSwapWafer(object[] param)
{
return false;
}
protected override bool fStartPlaceWafer(object[] param)
{
if(!_diPLCReady.Value)
{
EV.PostAlarmLog("Robot", "PLC ready signal is OFF.");
return false;
}
if(!_diMotionIdle.Value)
{
EV.PostAlarmLog("Robot", "Motion idle signal is OFF.");
return false;
}
_dtActionStart = DateTime.Now;
ResetRoutine();
try
{
//RobotArmEnum arm = (RobotArmEnum)param[0];
ModuleName tempmodule = (ModuleName)Enum.Parse(typeof(ModuleName), param[1].ToString());
int slotindex = int.Parse(param[2].ToString());
if (ModuleHelper.IsLoadPort(tempmodule))
{
_aoTargetPos.Value = (short)(slotindex + 1);
}
else
_aoTargetPos.Value = 26;
Blade1Target = tempmodule;
Blade2Target = tempmodule;
CmdTarget = tempmodule;
MoveInfo = new RobotMoveInfo()
{
Action = RobotAction.Picking,
ArmTarget = CmdRobotArm == RobotArmEnum.Lower ? RobotArm.ArmA : RobotArm.ArmB,
BladeTarget = BuildBladeTarget(),
};
}
catch (Exception ex)
{
LOG.Write(ex);
return false;
}
return true;
}
protected override bool fMonitorPlace(object[] param)
{
IsBusy = false;
if (DateTime.Now - _dtActionStart > TimeSpan.FromSeconds(RobotCommandTimeout))
{
OnError("Command execution timeout");
return true;
}
try
{
WaitAiValue((int)RobotStepEnum.ActionStep1, RobotCommandTimeout, _aiTargetPos, _aoTargetPos.Value, Notify, Stop);
SetDoState((int)RobotStepEnum.ActionStep2, _doPlaceCmd, true, Notify);
WaitDiState((int)RobotStepEnum.ActionStep3, RobotCommandTimeout, _diPlace_Ack, true, Notify, Stop);
SetDoState((int)RobotStepEnum.ActionStep4, _doPlaceCmd, false, Notify);
WaitDiState((int)RobotStepEnum.ActionStep5, RobotCommandTimeout, _diPlace_Ack, false, Notify, Stop);
}
catch (RoutineBreakException)
{
return false;
}
catch (RoutineFaildException)
{
EV.PostAlarmLog("Alarm", "Pick wafer failed.");
OnError("PickFailed");
return true;
}
Blade1Target = ModuleName.System;
Blade2Target = ModuleName.System;
CmdTarget = ModuleName.System;
MoveInfo = new RobotMoveInfo()
{
Action = RobotAction.Picking,
ArmTarget = CmdRobotArm == RobotArmEnum.Lower ? RobotArm.ArmA : RobotArm.ArmB,
BladeTarget = BuildBladeTarget(),
};
ModuleName sourcemodule;
if (!Enum.TryParse(CurrentParamter[1].ToString(), out sourcemodule)) return false;
int SourceslotIndex;
if (!int.TryParse(CurrentParamter[2].ToString(), out SourceslotIndex)) return false;
WaferManager.Instance.WaferMoved(RobotModuleName, 0,sourcemodule, SourceslotIndex);
return true;
}
protected override bool fMonitorPick(object[] param)
{
IsBusy = false;
if (DateTime.Now - _dtActionStart > TimeSpan.FromSeconds(RobotCommandTimeout))
{
OnError("Command execution timeout");
return true;
}
try
{
WaitAiValue((int)RobotStepEnum.ActionStep1, RobotCommandTimeout, _aiTargetPos, _aoTargetPos.Value, Notify, Stop);
SetDoState((int)RobotStepEnum.ActionStep2, _doPickCmd, true, Notify);
WaitDiState((int)RobotStepEnum.ActionStep3, RobotCommandTimeout, _diPick_Ack, true, Notify, Stop);
SetDoState((int)RobotStepEnum.ActionStep4, _doPickCmd, false, Notify);
WaitDiState((int)RobotStepEnum.ActionStep5, RobotCommandTimeout, _diPick_Ack, false, Notify, Stop);
}
catch (RoutineBreakException)
{
return false;
}
catch (RoutineFaildException)
{
EV.PostAlarmLog("Alarm","Pick wafer failed.");
OnError("PickFailed");
return true;
}
Blade1Target = ModuleName.System;
Blade2Target = ModuleName.System;
CmdTarget = ModuleName.System;
MoveInfo = new RobotMoveInfo()
{
Action = RobotAction.Picking,
ArmTarget = CmdRobotArm == RobotArmEnum.Lower ? RobotArm.ArmA : RobotArm.ArmB,
BladeTarget = BuildBladeTarget(),
};
ModuleName sourcemodule;
if (!Enum.TryParse(CurrentParamter[1].ToString(), out sourcemodule)) return false;
int SourceslotIndex;
if (!int.TryParse(CurrentParamter[2].ToString(), out SourceslotIndex)) return false;
WaferManager.Instance.WaferMoved(sourcemodule, SourceslotIndex, RobotModuleName, 0);
return true;
}
protected override bool fStartPickWafer(object[] param)
{
if (!_diPLCReady.Value)
{
EV.PostAlarmLog("Robot", "PLC ready signal is OFF.");
return false;
}
if (!_diMotionIdle.Value)
{
EV.PostAlarmLog("Robot", "Motion idle signal is OFF.");
return false;
}
_dtActionStart = DateTime.Now;
ResetRoutine();
try
{
ModuleName tempmodule = (ModuleName)Enum.Parse(typeof(ModuleName), param[1].ToString());
int slotindex = int.Parse(param[2].ToString());
if (ModuleHelper.IsLoadPort(tempmodule))
{
_aoTargetPos.Value = (short)(slotindex + 1);
}
else
_aoTargetPos.Value = 26;
Blade1Target = tempmodule;
Blade2Target = tempmodule;
CmdTarget = tempmodule;
MoveInfo = new RobotMoveInfo()
{
Action = RobotAction.Picking,
ArmTarget = CmdRobotArm == RobotArmEnum.Lower ? RobotArm.ArmA : RobotArm.ArmB,
BladeTarget = BuildBladeTarget(),
};
}
catch (Exception ex)
{
LOG.Write(ex);
return false;
}
return true;
}
protected override bool fResetToReady(object[] param)
{
return true;
}
protected override bool fReset(object[] param)
{
_dtActionStart = DateTime.Now;
ResetRoutine();
return true;
}
protected override bool fMonitorReset(object[] param)
{
IsBusy = false;
if (DateTime.Now - _dtActionStart > TimeSpan.FromSeconds(RobotCommandTimeout))
{
OnError("Command execution timeout");
return true;
}
try
{
SetDoState((int)RobotStepEnum.ActionStep1, _doPickCmd, false, Notify);
SetDoState((int)RobotStepEnum.ActionStep2, _doPlaceCmd, false, Notify);
SetDoState((int)RobotStepEnum.ActionStep3, _doHomeCmd, false, Notify);
SetDoState((int)RobotStepEnum.ActionStep4, _doSaveCmd, false, Notify);
SetDoState((int)RobotStepEnum.ActionStep5, _doX_FwdCmd, false, Notify);
SetDoState((int)RobotStepEnum.ActionStep6, _doX_RevCmd, false, Notify);
SetDoState((int)RobotStepEnum.ActionStep7, _doY_FwdCmd, false, Notify);
SetDoState((int)RobotStepEnum.ActionStep8, _doY_RevCmd, false, Notify);
SetDoState((int)RobotStepEnum.ActionStep9, _doZ_FwdCmd, false, Notify);
SetDoState((int)RobotStepEnum.ActionStep10, _doZ_RevCmd, false, Notify);
SetDoState((int)RobotStepEnum.ActionStep11, _doResetCmd, true, Notify);
WaitDiState((int)RobotStepEnum.ActionStep12, RobotCommandTimeout, _diReset_Ack, true, Notify, Stop);
SetDoState((int)RobotStepEnum.ActionStep13, _doResetCmd, false, Notify);
WaitDiState((int)RobotStepEnum.ActionStep14, RobotCommandTimeout, _diReset_Ack, false, Notify, Stop);
}
catch (RoutineBreakException)
{
return false;
}
catch (RoutineFaildException)
{
EV.PostAlarmLog("Alarm", "Pick wafer failed.");
OnError("PickFailed");
return true;
}
return true;
}
protected override bool fStartInit(object[] param)
{
_dtActionStart = DateTime.Now;
ResetRoutine();
return true;
}
protected override bool fMonitorInit(object[] param)
{
IsBusy = false;
if (DateTime.Now - _dtActionStart > TimeSpan.FromSeconds(RobotCommandTimeout))
{
OnError("Command execution timeout");
return true;
}
try
{
SetDoState((int)RobotStepEnum.ActionStep1, _doPickCmd, false, Notify);
SetDoState((int)RobotStepEnum.ActionStep2, _doPlaceCmd, false, Notify);
SetDoState((int)RobotStepEnum.ActionStep3, _doResetCmd, false, Notify);
SetDoState((int)RobotStepEnum.ActionStep4, _doSaveCmd, false, Notify);
SetDoState((int)RobotStepEnum.ActionStep5, _doX_FwdCmd, false, Notify);
SetDoState((int)RobotStepEnum.ActionStep6, _doX_RevCmd, false, Notify);
SetDoState((int)RobotStepEnum.ActionStep7, _doY_FwdCmd, false, Notify);
SetDoState((int)RobotStepEnum.ActionStep8, _doY_RevCmd, false, Notify);
SetDoState((int)RobotStepEnum.ActionStep9, _doZ_FwdCmd, false, Notify);
SetDoState((int)RobotStepEnum.ActionStep10, _doZ_RevCmd, false, Notify);
SetDoState((int)RobotStepEnum.ActionStep11, _doHomeCmd, true, Notify);
WaitDiState((int)RobotStepEnum.ActionStep12, RobotCommandTimeout, _diHome_Ack, true, Notify, Stop);
SetDoState((int)RobotStepEnum.ActionStep13, _doHomeCmd, false, Notify);
WaitDiState((int)RobotStepEnum.ActionStep14, RobotCommandTimeout, _diHome_Ack, false, Notify, Stop);
}
catch (RoutineBreakException)
{
return false;
}
catch (RoutineFaildException)
{
EV.PostAlarmLog("Alarm", "Pick wafer failed.");
OnError("PickFailed");
return true;
}
Blade1Target = ModuleName.System;
Blade2Target = ModuleName.System;
CmdTarget = ModuleName.System;
MoveInfo = new RobotMoveInfo()
{
Action = RobotAction.Picking,
ArmTarget = CmdRobotArm == RobotArmEnum.Lower ? RobotArm.ArmA : RobotArm.ArmB,
BladeTarget = BuildBladeTarget(),
};
return true;
}
protected override bool fStartExecuteCommand(object[] param)
{
CurrentExecuteCmd = param[0].ToString();
if (string.IsNullOrEmpty(CurrentExecuteCmd))
return false;
_dtActionStart = DateTime.Now;
ResetRoutine();
return true;
}
public string CurrentExecuteCmd { get; private set; }
protected override bool fMonitorExecuting(object[] param)
{
string command = CurrentParamter[0].ToString();
Int32 pnum = Convert.ToInt32(CurrentParamter[1]);
short high16bit = (short)(pnum >> 16);
short low16bit = (short)(pnum & ushort.MaxValue);
try
{
switch (command)
{
case "XMoveFwd":
SetAoValue((int)RobotStepEnum.ActionStep1, _aoXMoveFwdDistance_H, high16bit, Notify);
SetAoValue((int)RobotStepEnum.ActionStep2, _aoXMoveFwdDistance_L, low16bit, Notify);
SetDoState((int)RobotStepEnum.ActionStep3, _doX_FwdCmd, true, Notify);
WaitDiState((int)RobotStepEnum.ActionStep4, RobotCommandTimeout, _diX_Fwd_Ack, true, Notify,Stop);
SetDoState((int)RobotStepEnum.ActionStep5, _doX_FwdCmd, false, Notify);
WaitDiState((int)RobotStepEnum.ActionStep6, RobotCommandTimeout, _diX_Fwd_Ack, false, Notify, Stop);
SetAoValue((int)RobotStepEnum.ActionStep7, _aoXMoveFwdDistance_H, 0, Notify);
SetAoValue((int)RobotStepEnum.ActionStep8, _aoXMoveFwdDistance_L, 0, Notify);
break;
case "XMoveRev":
high16bit = (short)((-1*pnum) >> 16);
low16bit = (short)((-1 * pnum) & ushort.MaxValue);
SetAoValue((int)RobotStepEnum.ActionStep1, _aoXMoveRevDistance_H, high16bit, Notify);
SetAoValue((int)RobotStepEnum.ActionStep2, _aoXMoveRevDistance_L, low16bit, Notify);
SetDoState((int)RobotStepEnum.ActionStep3, _doX_RevCmd, true, Notify);
WaitDiState((int)RobotStepEnum.ActionStep4, RobotCommandTimeout, _diX_Rev_Ack, true, Notify, Stop);
SetDoState((int)RobotStepEnum.ActionStep5, _doX_RevCmd, false, Notify);
WaitDiState((int)RobotStepEnum.ActionStep6, RobotCommandTimeout, _diX_Rev_Ack, false, Notify, Stop);
SetAoValue((int)RobotStepEnum.ActionStep7, _aoXMoveRevDistance_H, 0, Notify);
SetAoValue((int)RobotStepEnum.ActionStep8, _aoXMoveRevDistance_L, 0, Notify);
break;
case "YMoveFwd":
SetAoValue((int)RobotStepEnum.ActionStep1, _aoYMoveFwdDistance_H, high16bit, Notify);
SetAoValue((int)RobotStepEnum.ActionStep2, _aoYMoveFwdDistance_L, low16bit, Notify);
SetDoState((int)RobotStepEnum.ActionStep3, _doY_FwdCmd, true, Notify);
WaitDiState((int)RobotStepEnum.ActionStep4, RobotCommandTimeout, _diY_Fwd_Ack, true, Notify, Stop);
SetDoState((int)RobotStepEnum.ActionStep5, _doY_FwdCmd, false, Notify);
WaitDiState((int)RobotStepEnum.ActionStep6, RobotCommandTimeout, _diY_Fwd_Ack, false, Notify, Stop);
SetAoValue((int)RobotStepEnum.ActionStep7, _aoYMoveFwdDistance_H, 0, Notify);
SetAoValue((int)RobotStepEnum.ActionStep8, _aoYMoveFwdDistance_L, 0, Notify);
break;
case "YMoveRev":
high16bit = (short)((-1 * pnum) >> 16);
low16bit = (short)((-1 * pnum) & ushort.MaxValue);
SetAoValue((int)RobotStepEnum.ActionStep1, _aoYMoveRevDistance_H, high16bit, Notify);
SetAoValue((int)RobotStepEnum.ActionStep2, _aoYMoveRevDistance_L, low16bit, Notify);
SetDoState((int)RobotStepEnum.ActionStep3, _doY_RevCmd, true, Notify);
WaitDiState((int)RobotStepEnum.ActionStep4, RobotCommandTimeout, _diY_Rev_Ack, true, Notify, Stop);
SetDoState((int)RobotStepEnum.ActionStep5, _doY_RevCmd, false, Notify);
WaitDiState((int)RobotStepEnum.ActionStep6, RobotCommandTimeout, _diY_Rev_Ack, false, Notify, Stop);
SetAoValue((int)RobotStepEnum.ActionStep7, _aoYMoveRevDistance_H, 0, Notify);
SetAoValue((int)RobotStepEnum.ActionStep8, _aoYMoveRevDistance_L, 0, Notify);
break;
case "ZMoveFwd":
SetAoValue((int)RobotStepEnum.ActionStep1, _aoZMoveFwdDistance_H, high16bit, Notify);
SetAoValue((int)RobotStepEnum.ActionStep2, _aoZMoveFwdDistance_L, low16bit, Notify);
SetDoState((int)RobotStepEnum.ActionStep3, _doZ_FwdCmd, true, Notify);
WaitDiState((int)RobotStepEnum.ActionStep4, RobotCommandTimeout, _diZ_Fwd_Ack, true, Notify, Stop);
SetDoState((int)RobotStepEnum.ActionStep5, _doZ_FwdCmd, false, Notify);
WaitDiState((int)RobotStepEnum.ActionStep6, RobotCommandTimeout, _diZ_Fwd_Ack, false, Notify, Stop);
SetAoValue((int)RobotStepEnum.ActionStep7, _aoZMoveFwdDistance_H, 0, Notify);
SetAoValue((int)RobotStepEnum.ActionStep8, _aoZMoveFwdDistance_L, 0, Notify);
break;
case "ZMoveRev":
high16bit = (short)((-1 * pnum) >> 16);
low16bit = (short)((-1 * pnum) & ushort.MaxValue);
SetAoValue((int)RobotStepEnum.ActionStep1, _aoZMoveRevDistance_H, high16bit, Notify);
SetAoValue((int)RobotStepEnum.ActionStep2, _aoZMoveRevDistance_L, low16bit, Notify);
SetDoState((int)RobotStepEnum.ActionStep3, _doZ_RevCmd, true, Notify);
WaitDiState((int)RobotStepEnum.ActionStep4, RobotCommandTimeout, _diZ_Rev_Ack, true, Notify, Stop);
SetDoState((int)RobotStepEnum.ActionStep5, _doZ_RevCmd, false, Notify);
WaitDiState((int)RobotStepEnum.ActionStep6, RobotCommandTimeout, _diZ_Rev_Ack, false, Notify, Stop);
SetAoValue((int)RobotStepEnum.ActionStep7, _aoZMoveRevDistance_H, 0, Notify);
SetAoValue((int)RobotStepEnum.ActionStep8, _aoZMoveRevDistance_L, 0, Notify);
break;
default:
break;
}
}
catch (RoutineBreakException)
{
return false;
}
catch (RoutineFaildException)
{
EV.PostAlarmLog("Alarm", $"Execute command:{command} failed.");
OnError($"Execute {command} failed");
return true;
}
return true;
}
protected override bool fError(object[] param)
{
return true;
}
protected override bool fStartExtendForPick(object[] param)
{
return true;
}
protected override bool fStartExtendForPlace(object[] param)
{
return true;
}
protected override bool fStartRetractFromPick(object[] param)
{
return true;
}
protected override bool fStartRetractFromPlace(object[] param)
{
return true;
}
public override RobotArmWaferStateEnum GetWaferState(RobotArmEnum arm)
{
if (WaferManager.Instance.CheckHasWafer(RobotModuleName, 0))
return RobotArmWaferStateEnum.Present;
return RobotArmWaferStateEnum.Absent;
}
private string BuildBladeTarget()
{
return (CmdRobotArm == RobotArmEnum.Upper ? "ArmB" : "ArmA") + "." + CmdTarget;
}
private static int TwoShortConvInt(short low16bit, short high16bit)
{
return (high16bit << 16) + low16bit + (low16bit<0 ? UInt16.MaxValue+1 :0);
}
private static void IntConvTwoShort(int num,ref short low16bit,ref short high16bit)
{
high16bit = (short)(num >> 16);
low16bit = (short)(num & ushort.MaxValue);
}
#endregion
public DOAccessor ParseDoNode(string name, XmlElement node, string ioModule = "")
{
if (!string.IsNullOrEmpty(node.GetAttribute(name).Trim()))
return IO.DO[string.IsNullOrEmpty(ioModule) ? node.GetAttribute(name).Trim() : $"{ioModule}.{node.GetAttribute(name).Trim()}"];
return null;
}
public DIAccessor ParseDiNode(string name, XmlElement node, string ioModule = "")
{
if (!string.IsNullOrEmpty(node.GetAttribute(name).Trim()))
return IO.DI[string.IsNullOrEmpty(ioModule) ? node.GetAttribute(name).Trim() : $"{ioModule}.{node.GetAttribute(name).Trim()}"];
return null;
}
public AOAccessor ParseAoNode(string name, XmlElement node, string ioModule = "")
{
if (!string.IsNullOrEmpty(node.GetAttribute(name).Trim()))
return IO.AO[string.IsNullOrEmpty(ioModule) ? node.GetAttribute(name).Trim() : $"{ioModule}.{node.GetAttribute(name).Trim()}"];
return null;
}
public AIAccessor ParseAiNode(string name, XmlElement node, string ioModule = "")
{
if (!string.IsNullOrEmpty(node.GetAttribute(name).Trim()))
return IO.AI[string.IsNullOrEmpty(ioModule) ? node.GetAttribute(name).Trim() : $"{ioModule}.{node.GetAttribute(name).Trim()}"];
return null;
}
public SCConfigItem ParseScNode(string name, XmlElement node, string ioModule = "", string defaultScPath = "")
{
SCConfigItem result = null;
if (!string.IsNullOrEmpty(node.GetAttribute(name).Trim()))
result = SC.GetConfigItem(node.GetAttribute(name));
if (result == null && !string.IsNullOrEmpty(defaultScPath) && SC.ContainsItem(defaultScPath))
result = SC.GetConfigItem(defaultScPath);
return result;
}
public static T ParseDeviceNode<T>(string name, XmlElement node) where T : class, IDevice
{
if (!string.IsNullOrEmpty(node.GetAttribute(name).Trim()))
return DEVICE.GetDevice<T>(node.GetAttribute(name));
LOG.Write(string.Format("{0},未定义{1}", node.InnerXml, name));
return null;
}
public static T ParseDeviceNode<T>(string module, string name, XmlElement node) where T : class, IDevice
{
string device_id = node.GetAttribute(name);
if (!string.IsNullOrEmpty(device_id) && !string.IsNullOrEmpty(device_id.Trim()))
{
return DEVICE.GetDevice<T>($"{module}.{device_id}");
}
LOG.Write(string.Format("{0},undefined {1}", node.InnerXml, name));
return null;
}
public enum CarrierMode
{
Foup,
Fosb,
OpenCassette,
}
private void SetAoValue(int id, AOAccessor ao, short value, Action<string> notify)
{
var ret = Execute(id, () =>
{
notify($"{RobotModuleName} set {ao.Name} to {value}.");
ao.Value = value;
return true;
});
if (ret.Item1)
{
if (ret.Item2 == Result.FAIL)
{
throw new RoutineFaildException();
}
}
}
private void WaitAiValue(int id, int time, AIAccessor ai, short value, Action<string> notify, Action<string> error)
{
var ret = ExecuteAndWait(id, () =>
{
notify($"Wait {RobotModuleName} {ai.Name} to be {value}");
return true;
}, () =>
{
if (ai.Value == value)
return true;
return false;
}, time * 1000);
if (ret.Item1)
{
if (ret.Item2 == Result.FAIL)
{
throw new RoutineFaildException();
}
else if (ret.Item2 == Result.TIMEOUT) //timeout
{
//EV.Notify(RobotModuleName);
error($"Wait {RobotModuleName} {ai.Name} to be {value} timeout after {time} seconds");
throw new RoutineFaildException();
}
else
{
throw new RoutineBreakException();
}
}
}
private void WaitDiState(int id, int time, DIAccessor di, bool state, Action<string> notify, Action<string> error)
{
var ret = ExecuteAndWait(id, () =>
{
notify($"Wait {RobotModuleName} {di.Name} to be {state}");
return true;
}, () =>
{
if (di.Value == state)
return true;
return false;
}, time * 1000);
if (ret.Item1)
{
if (ret.Item2 == Result.FAIL)
{
throw new RoutineFaildException();
}
else if (ret.Item2 == Result.TIMEOUT) //timeout
{
//EV.Notify();
error($"Wait {RobotModuleName} {di.Name} to be {state} timeout after {time} seconds");
throw new RoutineFaildException();
}
else
{
throw new RoutineBreakException();
}
}
}
private void SetDoState(int id, DOAccessor _do, bool state, Action<string> notify)
{
var ret = Execute(id, () =>
{
notify($"{RobotModuleName} start set {_do.Name} to {state}.");
//if (_do.Value == state)
//{
// _do.Value = !state;
// Thread.Sleep(500);
//}
return _do.SetValue(state, out _);
});
if (ret.Item1)
{
if (ret.Item2 == Result.FAIL)
{
throw new RoutineFaildException();
}
}
}
protected void Notify(string message)
{
EV.PostMessage(Name, EventEnum.GeneralInfo, string.Format("{0}:{1}", Name, message));
}
protected void Stop(string failReason)
{
OnError(string.Format("Failed {0}, {1} ", Name, failReason));
}
#region Routine Executor
//timer, 计算routine时间
protected DeviceTimer counter = new DeviceTimer();
protected DeviceTimer delayTimer = new DeviceTimer();
private enum STATE
{
IDLE,
WAIT,
}
public int TokenId
{
get { return _id; }
}
private int _id; //step index
/// <summary>
/// already done steps
/// </summary>
private Stack<int> _steps = new Stack<int>();
private STATE state; //step state //idel,wait,
//loop control
private int loop = 0;
private int loopCount = 0;
private int loopID = 0;
private DeviceTimer timer = new DeviceTimer();
public int LoopCounter { get { return loop; } }
public int LoopTotalTime { get { return loopCount; } }
// public int Timeout { get { return (int)(timer.GetTotalTime() / 1000); } }
//状态持续时间,单位为秒
public int Elapsed { get { return (int)(timer.GetElapseTime() / 1000); } }
protected RoutineResult RoutineToken = new RoutineResult() { Result = RoutineState.Running };
public void ResetRoutine()
{
_id = 0;
_steps.Clear();
loop = 0;
loopCount = 0;
state = STATE.IDLE;
counter.Start(60 * 60 * 100); //默认1小时
RoutineToken.Result = RoutineState.Running;
}
protected void PerformRoutineStep(int id, Func<RoutineState> execution, RoutineResult result)
{
if (!Acitve(id))
return;
result.Result = execution();
}
#region interface
public void StopLoop()
{
loop = loopCount;
}
public Tuple<bool, Result> Loop<T>(T id, Func<bool> func, int count)
{
int idx = Convert.ToInt32(id);
bool bActive = Acitve(idx);
if (bActive)
{
if (!func())
{
return Tuple.Create(bActive, Result.FAIL); //执行错误
}
loopID = idx;
loopCount = count;
next();
return Tuple.Create(true, Result.RUN);
}
return Tuple.Create(false, Result.RUN);
}
public Tuple<bool, Result> EndLoop<T>(T id, Func<bool> func)
{
int idx = Convert.ToInt32(id);
bool bActive = Acitve(idx);
if (bActive)
{
if (++loop >= loopCount) //Loop 结束
{
if (!func())
{
return Tuple.Create(bActive, Result.FAIL); //执行错误
}
loop = 0;
loopCount = 0; // Loop 结束时当前loop和loop总数都清零
next();
return Tuple.Create(true, Result.RUN);
}
//继续下一LOOP
next(loopID);
return Tuple.Create(true, Result.RUN);
}
return Tuple.Create(false, Result.RUN);
}
public Tuple<bool, Result> ExecuteAndWait<T>(T id, IRoutine routine)
{
int idx = Convert.ToInt32(id);
bool bActive = Acitve(idx);
if (bActive)
{
if (state == STATE.IDLE)
{
Result startRet = routine.Start();
if (startRet == Result.FAIL)
{
return Tuple.Create(true, Result.FAIL); //执行错误
}
else if (startRet == Result.DONE)
{
next();
return Tuple.Create(true, Result.DONE);
}
state = STATE.WAIT;
}
Result ret = routine.Monitor();
if (ret == Result.DONE)
{
next();
return Tuple.Create(true, Result.DONE);
}
else if (ret == Result.FAIL || ret == Result.TIMEOUT)
{
return Tuple.Create(true, Result.FAIL);
}
else
{
return Tuple.Create(true, Result.RUN);
}
}
return Tuple.Create(false, Result.RUN);
}
public Tuple<bool, Result> ExecuteAndWait<T>(T id, List<IRoutine> routines)
{
int idx = Convert.ToInt32(id);
bool bActive = Acitve(idx);
if (bActive)
{
if (state == STATE.IDLE)
{
foreach (var item in routines)
{
if (item.Start() == Result.FAIL)
return Tuple.Create(true, Result.FAIL);
}
state = STATE.WAIT;
}
//wait all sub failed or completedboo
bool bFail = false;
bool bDone = true;
foreach (var item in routines)
{
Result ret = item.Monitor();
bDone &= (ret == Result.FAIL || ret == Result.DONE);
bFail |= ret == Result.FAIL;
}
if (bDone)
{
next();
if (bFail)
return Tuple.Create(true, Result.FAIL);
return Tuple.Create(true, Result.DONE);
}
return Tuple.Create(true, Result.RUN);
}
return Tuple.Create(false, Result.RUN);
}
public Tuple<bool, Result> Check<T>(T id, Func<bool> func) //顺序执行
{
return Check(Check(Convert.ToInt32(id), func));
}
public Tuple<bool, Result> Execute<T>(T id, Func<bool> func) //顺序执行
{
return Check(execute(Convert.ToInt32(id), func));
}
public Tuple<bool, Result> Wait<T>(T id, Func<bool> func, double timeout = int.MaxValue) //Wait condition
{
return Check(wait(Convert.ToInt32(id), func, timeout));
}
public Tuple<bool, Result> Wait<T>(T id, Func<bool?> func, double timeout = int.MaxValue) //Wait condition
{
return Check(wait(Convert.ToInt32(id), func, timeout));
}
public Tuple<bool, Result> ExecuteAndWait<T>(T id, Func<bool> execute, Func<bool?> check, double timeout = int.MaxValue)
{
int idx = Convert.ToInt32(id);
bool bActive = Acitve(idx);
bool? bExecute = false;
if (bActive)
{
if (state == STATE.IDLE)
{
if (!execute())
{
return Tuple.Create(bActive, Result.FAIL); //执行错误
}
timer.Start(timeout);
state = STATE.WAIT;
}
bExecute = check();
if (bExecute == null)
{
return Tuple.Create(bActive, Result.FAIL); //Termianate
}
else
{
if (bExecute.Value) //检查Success, next
{
next();
return Tuple.Create(true, Result.RUN);
}
}
if (timer.IsTimeout())
return Tuple.Create(true, Result.TIMEOUT);
return Tuple.Create(true, Result.RUN);
}
return Tuple.Create(false, Result.RUN);
}
public Tuple<bool, Result> ExecuteAndWait<T>(T id, Func<bool> execute, Func<bool?> check, Func<double> time)
{
int idx = Convert.ToInt32(id);
bool bActive = Acitve(idx);
bool? bExecute = false;
double timeout = 0;
if (bActive)
{
if (state == STATE.IDLE)
{
timeout = time();
if (!execute())
{
return Tuple.Create(true, Result.FAIL); //执行错误
}
timer.Start(timeout);
state = STATE.WAIT;
}
bExecute = check();
if (bExecute == null)
{
return Tuple.Create(true, Result.FAIL); //Termianate
}
if (bExecute.Value) //检查Success, next
{
next();
return Tuple.Create(true, Result.RUN);
}
if (timer.IsTimeout())
return Tuple.Create(true, Result.TIMEOUT);
return Tuple.Create(true, Result.RUN);
}
return Tuple.Create(false, Result.RUN);
}
public Tuple<bool, Result> Wait<T>(T id, IRoutine rt)
{
int idx = Convert.ToInt32(id);
bool bActive = Acitve(idx);
if (bActive)
{
if (state == STATE.IDLE)
{
rt.Start();
state = STATE.WAIT;
}
Result ret = rt.Monitor();
return Tuple.Create(true, ret);
}
return Tuple.Create(false, Result.RUN);
}
//Monitor
public Tuple<bool, Result> Monitor<T>(T id, Func<bool> func, Func<bool> check, double time)
{
int idx = Convert.ToInt32(id);
bool bActive = Acitve(idx);
bool bCheck = false;
if (bActive)
{
if (state == STATE.IDLE)
{
if ((func != null) && !func())
{
return Tuple.Create(true, Result.FAIL);
}
timer.Start(time);
state = STATE.WAIT;
}
bCheck = check();
if (!bCheck)
{
return Tuple.Create(true, Result.FAIL); //Termianate
}
if (timer.IsTimeout())
{
next();
}
return Tuple.Create(true, Result.RUN);
}
return Tuple.Create(false, Result.RUN);
}
//Delay
public Tuple<bool, Result> Delay<T>(T id, Func<bool> func, double time)
{
int idx = Convert.ToInt32(id);
bool bActive = Acitve(idx);
if (bActive)
{
if (state == STATE.IDLE)
{
if ((func != null) && !func())
{
return Tuple.Create(true, Result.FAIL);
}
timer.Start(time);
state = STATE.WAIT;
}
if (timer.IsTimeout())
{
next();
}
return Tuple.Create(true, Result.RUN);
}
return Tuple.Create(false, Result.RUN);
}
//先delay 再运行
public Tuple<bool, Result> DelayCheck<T>(T id, Func<bool> func, double time)
{
int idx = Convert.ToInt32(id);
bool bActive = Acitve(idx);
if (bActive)
{
if (state == STATE.IDLE)
{
timer.Start(time);
state = STATE.WAIT;
}
if (timer.IsTimeout())
{
if (func != null && !func())
{
return Tuple.Create(true, Result.FAIL);
}
next();
}
return Tuple.Create(true, Result.RUN);
}
return Tuple.Create(false, Result.RUN);
}
#endregion
private Tuple<bool, bool> execute(int id, Func<bool> func) //顺序执行
{
bool bActive = Acitve(id);
bool bExecute = false;
if (bActive)
{
bExecute = func();
if (bExecute)
{
next();
}
}
return Tuple.Create(bActive, bExecute);
}
private Tuple<bool, bool> Check(int id, Func<bool> func) //check
{
bool bActive = Acitve(id);
bool bExecute = false;
if (bActive)
{
bExecute = func();
next();
}
return Tuple.Create(bActive, bExecute);
}
/// <summary>
/// </summary>
/// <param name="id"></param>
/// <param name="func"></param>
/// <param name="timeout"></param>
/// <returns>
/// item1 Active
/// item2 execute
/// item3 Timeout
///</returns>
private Tuple<bool, bool, bool> wait(int id, Func<bool> func, double timeout = int.MaxValue) //Wait condition
{
bool bActive = Acitve(id);
bool bExecute = false;
bool bTimeout = false;
if (bActive)
{
if (state == STATE.IDLE)
{
timer.Start(timeout);
state = STATE.WAIT;
}
bExecute = func();
if (bExecute)
{
next();
}
bTimeout = timer.IsTimeout();
}
return Tuple.Create(bActive, bExecute, bTimeout);
}
private Tuple<bool, bool?, bool> wait(int id, Func<bool?> func, double timeout = int.MaxValue) //Wait condition && Check error
{
bool bActive = Acitve(id);
bool? bExecute = false;
bool bTimeout = false;
if (bActive)
{
if (state == STATE.IDLE)
{
timer.Start(timeout);
state = STATE.WAIT;
}
bExecute = func();
if (bExecute.HasValue && bExecute.Value)
{
next();
}
bTimeout = timer.IsTimeout();
}
return Tuple.Create(bActive, bExecute, bTimeout);
}
/// <summary>
/// </summary>
/// <param name="value"></param>
/// <returns>
/// item1 true, return item2
/// </returns>
private Tuple<bool, Result> Check(Tuple<bool, bool> value)
{
if (value.Item1)
{
if (!value.Item2)
{
return Tuple.Create(true, Result.FAIL);
}
return Tuple.Create(true, Result.RUN);
}
return Tuple.Create(false, Result.RUN);
}
private Tuple<bool, Result> Check(Tuple<bool, bool, bool> value)
{
if (value.Item1) // 当前执行
{
if (CheckTimeout(value)) //timeout
{
return Tuple.Create(true, Result.TIMEOUT);
}
return Tuple.Create(true, Result.RUN);
}
return Tuple.Create(false, Result.RUN);
}
private Tuple<bool, Result> Check(Tuple<bool, bool?, bool> value)
{
if (value.Item1) // 当前执行
{
if (value.Item2 == null)
{
return Tuple.Create(true, Result.FAIL);
}
else
{
if (value.Item2 == false && value.Item3 == true) //timeout
{
return Tuple.Create(true, Result.TIMEOUT);
}
return Tuple.Create(true, Result.RUN);
}
}
return Tuple.Create(false, Result.RUN);
}
private bool CheckTimeout(Tuple<bool, bool, bool> value)
{
return value.Item1 == true && value.Item2 == false && value.Item3 == true;
}
private bool Acitve(int id) //
{
if (_steps.Contains(id))
return false;
this._id = id;
return true;
}
private void next()
{
_steps.Push(this._id);
state = STATE.IDLE;
}
private void next(int step) //loop
{
while (_steps.Pop() != step) ;
state = STATE.IDLE;
}
public void Delay(int id, double delaySeconds)
{
Tuple<bool, Result> ret = Delay(id, () =>
{
return true;
}, delaySeconds * 1000);
if (ret.Item1)
{
if (ret.Item2 == Result.RUN)
{
throw (new RoutineBreakException());
}
}
}
public bool IsActived(int id)
{
return _steps.Contains(id);
}
#endregion
}
}