272 lines
6.1 KiB
C#
272 lines
6.1 KiB
C#
|
using System;
|
|||
|
using System.Collections.Generic;
|
|||
|
using System.Diagnostics;
|
|||
|
using Aitex.Core.RT.Event;
|
|||
|
using MECF.Framework.Common.Equipment;
|
|||
|
using MECF.Framework.Common.SubstrateTrackings;
|
|||
|
|
|||
|
namespace Aitex.Core.RT.Routine
|
|||
|
{
|
|||
|
public class ModuleRoutine : SeqenecRoutine
|
|||
|
{
|
|||
|
#region Variables
|
|||
|
|
|||
|
public delegate RoutineState RoutineFunc<T>(T arg);
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 用于统计Routine耗时的计时器。
|
|||
|
/// </summary>
|
|||
|
protected readonly Stopwatch SwStatisticElapse;
|
|||
|
|
|||
|
protected string _stepName;
|
|||
|
|
|||
|
protected TimeSpan _stepSpan = new TimeSpan(0, 0, 0, 0);
|
|||
|
|
|||
|
protected DateTime _stepStartTime;
|
|||
|
|
|||
|
private static object locker = new object();
|
|||
|
|
|||
|
#endregion
|
|||
|
|
|||
|
#region Constuctors
|
|||
|
|
|||
|
public ModuleRoutine(string module)
|
|||
|
{
|
|||
|
Module = module;
|
|||
|
SwStatisticElapse = new Stopwatch();
|
|||
|
}
|
|||
|
|
|||
|
#endregion
|
|||
|
|
|||
|
#region Properties
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 返回当前Routine所述的模组
|
|||
|
/// </summary>
|
|||
|
public string Module { get; protected set; }
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 返回当前Routine的名称
|
|||
|
/// </summary>
|
|||
|
public string Name { get; protected set; }
|
|||
|
|
|||
|
public string StepName => _stepName;
|
|||
|
|
|||
|
public TimeSpan StepLeftTime
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
if (_stepSpan.TotalMilliseconds < 1.0)
|
|||
|
{
|
|||
|
return _stepSpan;
|
|||
|
}
|
|||
|
return _stepSpan - (DateTime.Now - _stepStartTime);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
#endregion
|
|||
|
|
|||
|
#region Methods
|
|||
|
|
|||
|
|
|||
|
public virtual Result Monitor()
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
MonitorBody();
|
|||
|
}
|
|||
|
catch (RoutineBreakException)
|
|||
|
{
|
|||
|
return Result.RUN;
|
|||
|
}
|
|||
|
catch (RoutineFaildException)
|
|||
|
{
|
|||
|
return Result.FAIL;
|
|||
|
}
|
|||
|
|
|||
|
SwStatisticElapse.Stop();
|
|||
|
Notify($"Finished ! Elapsed time: {(int)(SwStatisticElapse.ElapsedMilliseconds / 1000)} s");
|
|||
|
return Result.DONE;
|
|||
|
}
|
|||
|
|
|||
|
public virtual Result Start(params object[] args)
|
|||
|
{
|
|||
|
Reset();
|
|||
|
SwStatisticElapse.Restart();
|
|||
|
return StartBody(args);
|
|||
|
}
|
|||
|
|
|||
|
public virtual void Abort()
|
|||
|
{
|
|||
|
}
|
|||
|
|
|||
|
protected virtual Result StartBody(params object[] args)
|
|||
|
{
|
|||
|
return Result.RUN;
|
|||
|
}
|
|||
|
|
|||
|
protected virtual void MonitorBody()
|
|||
|
{
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
protected void Notify(string message)
|
|||
|
{
|
|||
|
EV.PostInfoLog(Module, Name + ", " + message);
|
|||
|
}
|
|||
|
|
|||
|
protected void Stop(string failReason)
|
|||
|
{
|
|||
|
EV.PostAlarmLog(Module, Name + " failed, " + failReason);
|
|||
|
}
|
|||
|
|
|||
|
public void Abort(string failReason)
|
|||
|
{
|
|||
|
EV.PostAlarmLog(Module, Name + " " + failReason);
|
|||
|
}
|
|||
|
|
|||
|
public void TimeDelay(int id, string stepName, double time)
|
|||
|
{
|
|||
|
Tuple<bool, Result> tuple = Delay(id, delegate
|
|||
|
{
|
|||
|
Notify($"Delay {time} seconds");
|
|||
|
_stepSpan = new TimeSpan(0, 0, 0, (int)time);
|
|||
|
_stepStartTime = DateTime.Now;
|
|||
|
_stepName = stepName;
|
|||
|
return true;
|
|||
|
}, time * 1000.0);
|
|||
|
if (tuple.Item1 && tuple.Item2 == Result.RUN)
|
|||
|
{
|
|||
|
throw new RoutineBreakException();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public void TimeDelay(int id, double time)
|
|||
|
{
|
|||
|
Tuple<bool, Result> tuple = Delay(id, delegate
|
|||
|
{
|
|||
|
Notify($"Delay {time} seconds");
|
|||
|
_stepSpan = new TimeSpan(0, 0, 0, (int)time);
|
|||
|
_stepStartTime = DateTime.Now;
|
|||
|
return true;
|
|||
|
}, time * 1000.0);
|
|||
|
if (tuple.Item1 && tuple.Item2 == Result.RUN)
|
|||
|
{
|
|||
|
throw new RoutineBreakException();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
protected void ExecuteRoutine(int id, List<(IRoutine routine, object[] args)> routines)
|
|||
|
{
|
|||
|
Tuple<bool, Result> tuple = ExecuteAndWait(id, routines);
|
|||
|
if (tuple.Item1)
|
|||
|
{
|
|||
|
if (tuple.Item2 == Result.FAIL)
|
|||
|
{
|
|||
|
throw new RoutineFaildException();
|
|||
|
}
|
|||
|
if (tuple.Item2 == Result.RUN)
|
|||
|
{
|
|||
|
throw new RoutineBreakException();
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
protected void ExecuteRoutine(int id, List<IRoutine> routines)
|
|||
|
{
|
|||
|
Tuple<bool, Result> tuple = ExecuteAndWait(id, routines);
|
|||
|
if (tuple.Item1)
|
|||
|
{
|
|||
|
if (tuple.Item2 == Result.FAIL)
|
|||
|
{
|
|||
|
throw new RoutineFaildException();
|
|||
|
}
|
|||
|
if (tuple.Item2 == Result.RUN)
|
|||
|
{
|
|||
|
throw new RoutineBreakException();
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
protected void ExecuteRoutine(int id, IRoutine routine, params object[] args)
|
|||
|
{
|
|||
|
Tuple<bool, Result> tuple = ExecuteAndWait(id, routine, args);
|
|||
|
if (tuple.Item1)
|
|||
|
{
|
|||
|
if (tuple.Item2 == Result.FAIL)
|
|||
|
{
|
|||
|
throw new RoutineFaildException();
|
|||
|
}
|
|||
|
if (tuple.Item2 == Result.RUN)
|
|||
|
{
|
|||
|
throw new RoutineBreakException();
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
protected void PerformStep<T, T1>(T step, RoutineFunc<T1> func, T1 param1)
|
|||
|
{
|
|||
|
int num = Convert.ToInt32(step);
|
|||
|
RoutineState routineState = func(param1);
|
|||
|
}
|
|||
|
|
|||
|
public void Loop(int id, int count)
|
|||
|
{
|
|||
|
Tuple<bool, Result> tuple = Loop(id, delegate
|
|||
|
{
|
|||
|
Notify($"Start loop {base.LoopCounter + 1}/{count}");
|
|||
|
return true;
|
|||
|
}, count);
|
|||
|
if (tuple.Item1 && tuple.Item2 == Result.FAIL)
|
|||
|
{
|
|||
|
throw new RoutineFaildException();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public void EndLoop(int id)
|
|||
|
{
|
|||
|
Tuple<bool, Result> tuple = EndLoop(id, delegate
|
|||
|
{
|
|||
|
Notify("Loop finished");
|
|||
|
return true;
|
|||
|
});
|
|||
|
if (tuple.Item1)
|
|||
|
{
|
|||
|
throw new RoutineBreakException();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 转移产品。
|
|||
|
/// </summary>
|
|||
|
/// <param name="id"></param>
|
|||
|
/// <param name="moduleFrom"></param>
|
|||
|
/// <param name="slotFrom"></param>
|
|||
|
/// <param name="moduleTo"></param>
|
|||
|
/// <param name="slotTo"></param>
|
|||
|
/// <exception cref="RoutineFaildException"></exception>
|
|||
|
protected virtual void Transfer(int id, ModuleName moduleFrom, int slotFrom, ModuleName moduleTo, int slotTo)
|
|||
|
{
|
|||
|
var ret = Execute(id, () =>
|
|||
|
{
|
|||
|
Notify($"Transfer {moduleFrom}.{slotFrom} -> {moduleTo}.{slotTo}");
|
|||
|
// 产品到达抓取位置后,Slot0 转移到 Slot1
|
|||
|
WaferManager.Instance.WaferMoved(moduleFrom, slotFrom,
|
|||
|
moduleTo, slotTo);
|
|||
|
return true;
|
|||
|
});
|
|||
|
|
|||
|
if (ret.Item1)
|
|||
|
{
|
|||
|
if (ret.Item2 == Result.FAIL)
|
|||
|
{
|
|||
|
throw new RoutineFaildException();
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
#endregion
|
|||
|
}
|
|||
|
}
|