using MECF.Framework.Common.Equipment; using MECF.Framework.Simulator.Core.SubstrateTrackings; using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Timers; namespace MECF.Framework.Simulator.Core.Robots.Sunway { public class SunwayRobotSimulator : RobotSimulator { public enum OperateEnum { Null, RSR, INPUT, STAT, RQ, RSRWafer, RSRTray } protected Random _rd = new Random(); public bool IsError { get; set; } public string ErrorCode { get; set; } public bool StateChecked { get; set; } public int StateCode { get; set; } public bool EventChecked { get; set; } public string EventCode { get; set; } private static string msgDone = "_RDY"; private static string msgError = "_ERR"; private static string msgRSRCassA = "MAP 1 2 3 0 1 2 3 0 1 2 3 0 1 2 3 0 1 2 3 0 1 2 3 0 ?"; private static string msgRSRCassB = "MAP 1 2 3 0 1 2 3 0"; private static string msgRSR = "1"; private string lastMsg = ""; private System.Timers.Timer timer; OperateEnum operateEnum = OperateEnum.Null; public string CassetteResult { get; set; } Dictionary ModuleAssociateStationDic; public SunwayRobotSimulator(int port) : base(port, 0, "\r\n", ' ', 5) { AddCommandHandler("HOME", HandleHome); AddCommandHandler("RQ", HandleRQLoad); AddCommandHandler("GOTO", HandleHome); AddCommandHandler("MAP", HandleMap); AddCommandHandler("RSR", HandleRSR); AddCommandHandler("PICK", HandleHome); AddCommandHandler("PLACE", HandleHome); AddCommandHandler("VAC", HandleHome); AddCommandHandler("SET", HandleHome); AddCommandHandler("SVON", HandleHome); AddCommandHandler("ERR", HandleErr); AddCommandHandler("OUTP", HandleHome); AddCommandHandler("MOVR", HandleHome); AddCommandHandler("RETH", HandleHome); AddCommandHandler("INPUT", HandleInput); AddCommandHandler("OUPT", HandleHome); ErrorCode = "0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000"; ModuleAssociateStationDic = new Dictionary() { {1,$"{ModuleName.PM1 }"}, {2,$"{ModuleName.PM2}" }, {3,$"{ModuleName.Buffer}1"}, {4,$"{ModuleName.Buffer}2"}, {5,$"{ModuleName.Buffer}3"}, {6,$"{ModuleName.LoadLock}"}, {7,$"{ModuleName.UnLoad}"}, {8,$"{ModuleName.Aligner}"}, {9,$"{ModuleName.CassAL}"}, {10,$"{ModuleName.CassAR}"}, {12,$"{ModuleName.CassBL}"}, }; timer = new System.Timers.Timer(); timer.Enabled = false; timer.AutoReset = false; timer.Elapsed += new ElapsedEventHandler(timer_Elapsed); } internal void HandleErr(string msg) { lastMsg = msg; if (IsError) OnWriteMessage(string.IsNullOrEmpty(ErrorCode) ? @"FFFF, FFFF, FFFF, FFFF, FFFF, FFFF, FFFF, FFFF" : ErrorCode); else OnWriteMessage("0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000"); } internal void HandleStat(string msg) { lastMsg = msg; OnWriteMessage(StateCode.ToString()); } internal void HandleHome(string msg) { lastMsg = msg; operateEnum = OperateEnum.Null; HandleMove(RobotStateEnum.Homing, new string[] { "" }); } internal void HandleRQLoad(string msg) { lastMsg = msg; operateEnum = OperateEnum.Null; OnWriteMessage($"LOAD A OFF/r/n_RDY"); } internal void HandleGetSp(string msg) { // GETSP B 11 1 lastMsg = msg; operateEnum = OperateEnum.Null; HandleGetSp(RobotStateEnum.Picking, msg.Split(' ')); } internal void HandleInput(string msg) { lastMsg = msg; operateEnum = OperateEnum.INPUT; HandleInput(RobotStateEnum.Input, new string[] { "" }); } internal void HandleMap(string msg) { lastMsg = msg; HandleMap(RobotStateEnum.MAP, new string[] { "" }); } internal void HandleRSR(string msg) { int cassette = int.Parse(msg.Replace("RSR", "").Trim()); if (ModuleAssociateStationDic[cassette] == ModuleName.CassAL.ToString() || ModuleAssociateStationDic[cassette] == ModuleName.CassAR.ToString()) { operateEnum = OperateEnum.RSRWafer; } else { operateEnum = OperateEnum.RSRTray; } HandleRSR(RobotStateEnum.RSR, new string[] { "" }); } internal void HandleSTAT(string msg) { operateEnum = OperateEnum.STAT; HandleSTAT(RobotStateEnum.STAT, new string[] { "" }); } internal void SetResult() { msgRSRCassA = CassetteResult; } private bool HandleRSR(RobotStateEnum action, string[] cmdComponents) { if (robotStateArgs.State != RobotStateEnum.Idle && (action == RobotStateEnum.Homing && robotStateArgs.State != RobotStateEnum.Errored)) // allow homes when in error, but not other moves { HandleError("Already moving"); return false; } double delay = 1; timer.Interval = delay * 1000; timer.Enabled = true; return true; } private bool HandleSTAT(RobotStateEnum action, string[] cmdComponents) { if (robotStateArgs.State != RobotStateEnum.Idle && (action == RobotStateEnum.Homing && robotStateArgs.State != RobotStateEnum.Errored)) // allow homes when in error, but not other moves { HandleError("Already moving"); return false; } double delay = 1; timer.Interval = delay * 1000; timer.Enabled = true; return true; } internal void HandleUnknown(string msg) { OnWriteMessage(msgError); } private bool HandleMove(RobotStateEnum action, string[] cmdComponents) { if (robotStateArgs.State != RobotStateEnum.Idle && (action == RobotStateEnum.Homing && robotStateArgs.State != RobotStateEnum.Errored)) // allow homes when in error, but not other moves { HandleError("Already moving"); return false; } ErrorCode = "0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000"; double delay = 1; timer.Interval = delay * 1000; timer.Enabled = true; return true; } private bool HandleGetSp(RobotStateEnum action, string[] args) { if (IsError && args[3] == "1") { ErrorCode = "0000, 0000, 0000, 0001, 0000, 0000, 0001, 0001"; OnWriteMessage(msgError); return true; } OnWriteMessage(msgDone); return true; } private bool HandleInput(RobotStateEnum action, string[] cmdComponents) { if (robotStateArgs.State != RobotStateEnum.Idle && (action == RobotStateEnum.Homing && robotStateArgs.State != RobotStateEnum.Errored)) // allow homes when in error, but not other moves { HandleError("Already moving"); return false; } double delay = 1; timer.Interval = delay * 1000; timer.Enabled = true; return true; } private bool HandleMap(RobotStateEnum action, string[] cmdComponents) { if (robotStateArgs.State != RobotStateEnum.Idle && (action == RobotStateEnum.Homing && robotStateArgs.State != RobotStateEnum.Errored) ) // allow homes when in error, but not other moves { HandleError("Already moving"); return false; } double delay = 1; timer.Interval = delay * 1000; timer.Enabled = true; return true; } private void HandleError(string msg) { OnWriteMessage(msgError); } private void timer_Elapsed(object sender, ElapsedEventArgs e) { SetRobotState(RobotStateEnum.Idle); timer.Enabled = false; this.CassetteResult = msgRSRCassA; if (operateEnum == OperateEnum.STAT) { OnWriteMessage("19568"); } else if (operateEnum == OperateEnum.RSRWafer) { OnWriteMessage(msgRSRCassA); } else if (operateEnum == OperateEnum.RSRTray) { OnWriteMessage(msgRSRCassB); } else if (operateEnum == OperateEnum.INPUT) { OnWriteMessage("1"); } else { OnWriteMessage(msgDone); } } } }