Browse Source

EFEM Driver and simulator functions.

sangwq 1 year ago
parent
commit
c9282deeeb

+ 5 - 4
Venus/Venus_Core/DeviceName.cs

@@ -44,6 +44,7 @@ namespace Venus_Core
         StateTrack,
         StateTrack,
         //WriteCarrierId,
         //WriteCarrierId,
         Grip,
         Grip,
+        EmsStop,
 
 
     }
     }
 
 
@@ -55,7 +56,6 @@ namespace Venus_Core
             { EfemOperation.Home,           "INIT" },
             { EfemOperation.Home,           "INIT" },
             { EfemOperation.Orgsh,          "ORGSH" },
             { EfemOperation.Orgsh,          "ORGSH" },
             { EfemOperation.ClearError,     "ERROR"},
             { EfemOperation.ClearError,     "ERROR"},
-            //{ EfemOperation.HomeLP,       "INIT" },
             { EfemOperation.Map,            "WAFSH" },
             { EfemOperation.Map,            "WAFSH" },
             { EfemOperation.GetWaferInfo,   "MAPDT" },
             { EfemOperation.GetWaferInfo,   "MAPDT" },
             { EfemOperation.Pick,           "LOAD" },
             { EfemOperation.Pick,           "LOAD" },
@@ -69,14 +69,15 @@ namespace Venus_Core
             { EfemOperation.Goto,           "GOTO" },
             { EfemOperation.Goto,           "GOTO" },
             { EfemOperation.Load,           "OPEN" },
             { EfemOperation.Load,           "OPEN" },
             { EfemOperation.Unload,         "CLOSE" },
             { EfemOperation.Unload,         "CLOSE" },
-            { EfemOperation.CarrierId,  "CSTID" },
+            { EfemOperation.CarrierId,      "CSTID" },
             { EfemOperation.Dock,           "DOCK" },
             { EfemOperation.Dock,           "DOCK" },
             { EfemOperation.Undock,         "UNDOCK" },
             { EfemOperation.Undock,         "UNDOCK" },
             { EfemOperation.Clamp,          "LOCK" },
             { EfemOperation.Clamp,          "LOCK" },
             { EfemOperation.Unclamp,        "UNLOCK" },
             { EfemOperation.Unclamp,        "UNLOCK" },
-            { EfemOperation.SetThickness,        "THICKNESS" },
-            { EfemOperation.StateTrack,        "STATE" },
+            { EfemOperation.SetThickness,   "THICKNESS" },
+            { EfemOperation.StateTrack,     "STATE" },
             { EfemOperation.Grip,           "CLAMP" },
             { EfemOperation.Grip,           "CLAMP" },
+            { EfemOperation.EmsStop,        "EMS"},          
 
 
         };
         };
 
 

+ 3 - 0
Venus/Venus_RT/Devices/EFEM/EfemBase.cs

@@ -86,6 +86,9 @@ namespace Venus_RT.Devices.EFEM
         public virtual bool IsHomed { get; }
         public virtual bool IsHomed { get; }
         public abstract bool HomeAll();
         public abstract bool HomeAll();
         public abstract bool Home(ModuleName mod);
         public abstract bool Home(ModuleName mod);
+        public abstract bool OriginalSearch();
+        public abstract bool CheckWaferPresence();
+        public abstract string GetWaferPresence();
         public abstract bool Halt();
         public abstract bool Halt();
         public abstract bool ClearError();
         public abstract bool ClearError();
         public abstract bool PickExtend(ModuleName chamber, int slot, Hand hand);
         public abstract bool PickExtend(ModuleName chamber, int slot, Hand hand);

+ 1 - 2
Venus/Venus_RT/Devices/EFEM/EfemMessage.cs

@@ -35,9 +35,8 @@ namespace Venus_RT.Devices.YASKAWA
         {
         {
             string sPara = ToParamString();
             string sPara = ToParamString();
             string sOP = EfemConstant.OperationString[Operation];
             string sOP = EfemConstant.OperationString[Operation];
-            string context = $"{Head}:{sOP}{sPara}";
+            string context = $"{Head}:{sOP}{sPara}{EOF}\r";
 
 
-            context += EOF;
             return context;
             return context;
         }
         }
 
 

+ 162 - 7
Venus/Venus_RT/Devices/EFEM/JetEfem.cs

@@ -8,6 +8,7 @@ using Venus_Core;
 using Venus_RT.Modules;
 using Venus_RT.Modules;
 using MECF.Framework.Common.CommonData;
 using MECF.Framework.Common.CommonData;
 using MECF.Framework.Common.Equipment;
 using MECF.Framework.Common.Equipment;
+using MECF.Framework.Common.SubstrateTrackings;
 using Aitex.Sorter.Common;
 using Aitex.Sorter.Common;
 using Aitex.Core.Common;
 using Aitex.Core.Common;
 using Aitex.Core.RT.SCCore;
 using Aitex.Core.RT.SCCore;
@@ -18,10 +19,12 @@ using Venus_RT.Devices.YASKAWA;
 
 
 namespace Venus_RT.Devices.EFEM
 namespace Venus_RT.Devices.EFEM
 {
 {
-    class JetEfem :EfemBase
+    class JetEfem : EfemBase
     {
     {
         private RState _status;
         private RState _status;
         private bool _IsHomed;
         private bool _IsHomed;
+        private string _waferPresence;
+        private bool _bIsUnloadClamp;
         private RobotMoveInfo _robotMoveInfo = new RobotMoveInfo();
         private RobotMoveInfo _robotMoveInfo = new RobotMoveInfo();
         private readonly Loadport[] _LPMs = new Loadport[2];
         private readonly Loadport[] _LPMs = new Loadport[2];
         private readonly SignalTower _signalT = new SignalTower();
         private readonly SignalTower _signalT = new SignalTower();
@@ -53,11 +56,31 @@ namespace Venus_RT.Devices.EFEM
             _status = RState.Init;
             _status = RState.Init;
             _IsHomed = false;
             _IsHomed = false;
 
 
+            _LPMs[0] = new Loadport(ModuleName.LP1, this);
+            _LPMs[1] = new Loadport(ModuleName.LP2, this);
+
+            CarrierManager.Instance.SubscribeLocation(ModuleName.LP1.ToString(), 1);
+            CarrierManager.Instance.SubscribeLocation(ModuleName.LP2.ToString(), 1);
+
+            Action<ModuleName, int> _subscribeLoc = (ModuleName module, int waferCount) => {
+                if (ModuleHelper.IsInstalled(module))
+                {
+                    WaferManager.Instance.SubscribeLocation(module, waferCount);
+                }
+            };
+
+            _subscribeLoc(ModuleName.EfemRobot, 2);
+            _subscribeLoc(ModuleName.Aligner1, 1);
+            _subscribeLoc(ModuleName.Aligner2, 1);
+            _subscribeLoc(ModuleName.Cooling1, 1);
+            _subscribeLoc(ModuleName.Cooling2, 1);
+            _subscribeLoc(ModuleName.LP1, SC.GetValue<int>("EFEM.LoadPort.SlotNumber"));
+            _subscribeLoc(ModuleName.LP2, SC.GetValue<int>("EFEM.LoadPort.SlotNumber"));
+
         }
         }
 
 
         public override void Monitor()
         public override void Monitor()
         {
         {
-
         }
         }
         public override void Terminate()
         public override void Terminate()
         {
         {
@@ -85,6 +108,7 @@ namespace Venus_RT.Devices.EFEM
         {
         {
             _currentMsg = new EfemMessage
             _currentMsg = new EfemMessage
             {
             {
+                Port = ModuleName.EFEM,
                 Operation = EfemOperation.Home,
                 Operation = EfemOperation.Home,
                 Head = EfemMessage.MsgHead.MOV,
                 Head = EfemMessage.MsgHead.MOV,
                 Parameters = new List<string> { Constant.ModuleString[ModuleName.EFEM] }
                 Parameters = new List<string> { Constant.ModuleString[ModuleName.EFEM] }
@@ -99,6 +123,7 @@ namespace Venus_RT.Devices.EFEM
             {
             {
                 _backroundMsg = new EfemMessage
                 _backroundMsg = new EfemMessage
                 {
                 {
+                    Port = mod,
                     Operation = EfemOperation.Home,
                     Operation = EfemOperation.Home,
                     Head = EfemMessage.MsgHead.MOV,
                     Head = EfemMessage.MsgHead.MOV,
                     Parameters = new List<string> { Constant.ModuleString[mod] }
                     Parameters = new List<string> { Constant.ModuleString[mod] }
@@ -120,9 +145,58 @@ namespace Venus_RT.Devices.EFEM
             }
             }
             
             
         }
         }
+
+        public override bool OriginalSearch()
+        {
+            if (!CheckEfemStatus())
+                return false;
+
+            _currentMsg = new EfemMessage
+            {
+                Operation = EfemOperation.Orgsh,
+                Head = EfemMessage.MsgHead.MOV,
+                Parameters = new List<string>
+                {
+                    Constant.ModuleString[ModuleName.EFEM] 
+                }
+            };
+
+            _status = RState.Running;
+            return _socket.Write(_currentMsg.ToString());
+        }
+
+        public override bool CheckWaferPresence()
+        {
+            if (!CheckEfemStatus())
+                return false;
+
+            _currentMsg = new EfemMessage
+            {
+                Operation = EfemOperation.StateTrack,
+                Head = EfemMessage.MsgHead.GET,
+                Parameters = new List<string> { "TRACK" }
+            };
+
+            _waferPresence = string.Empty;
+            _status = RState.Running;
+            return _socket.Write(_currentMsg.ToString());
+        }
+
+        public override string GetWaferPresence()
+        {
+            return _waferPresence;
+        }
+
         public override bool Halt()
         public override bool Halt()
         {
         {
-            return true;
+            _currentMsg = new EfemMessage
+            {
+                Operation = EfemOperation.EmsStop,
+                Head = EfemMessage.MsgHead.MOV,
+            };
+
+            _status = RState.Running;
+            return _socket.Write(_currentMsg.ToString());
         }
         }
 
 
         public override bool ClearError()
         public override bool ClearError()
@@ -467,6 +541,7 @@ namespace Venus_RT.Devices.EFEM
                 Parameters = new List<string> { Constant.ModuleString[mod] }
                 Parameters = new List<string> { Constant.ModuleString[mod] }
             };
             };
 
 
+            _bIsUnloadClamp = isUnloadClamp;
             return _socket.Write(_backroundMsg.ToString());
             return _socket.Write(_backroundMsg.ToString());
         }
         }
         public override bool Unclamp(ModuleName mod)
         public override bool Unclamp(ModuleName mod)
@@ -517,8 +592,7 @@ namespace Venus_RT.Devices.EFEM
                         // 收到INF之后发送ACK确认
                         // 收到INF之后发送ACK确认
                         string strACK = rec_msg.RawString.Replace("INF", "ACK");
                         string strACK = rec_msg.RawString.Replace("INF", "ACK");
 
 
-                        _socket.Write(strACK);
-
+                        SendBack(strACK);
                         EfemMessage ack_msg = strACK.ToMessage();
                         EfemMessage ack_msg = strACK.ToMessage();
                         ack_msg.Direct = MsgDirection.To;
                         ack_msg.Direct = MsgDirection.To;
                         _revMsg = rec_msg;
                         _revMsg = rec_msg;
@@ -547,7 +621,8 @@ namespace Venus_RT.Devices.EFEM
 
 
         private void OnErrorHappen(ErrorEventArgs args)
         private void OnErrorHappen(ErrorEventArgs args)
         {
         {
-
+            _status = RState.Failed;
+            Singleton<RouteManager>.Instance.EFEM.PostMsg(EfemEntity.MSG.Error);
         }
         }
 
 
         private void OnErrorOccurred(EfemMessage message)
         private void OnErrorOccurred(EfemMessage message)
@@ -566,6 +641,7 @@ namespace Venus_RT.Devices.EFEM
                     break;
                     break;
             }
             }
 
 
+            _status = RState.Failed;
             LOG.Write(eEvent.ERR_EFEM_COMMON_FAILED, ModuleName.EFEM, $"{description}, [{message.Data[0]}], [{message.Factor}]");
             LOG.Write(eEvent.ERR_EFEM_COMMON_FAILED, ModuleName.EFEM, $"{description}, [{message.Data[0]}], [{message.Factor}]");
         }
         }
 
 
@@ -669,7 +745,7 @@ namespace Venus_RT.Devices.EFEM
 
 
         private void OnCommandUpdated(EfemMessage message)
         private void OnCommandUpdated(EfemMessage message)
         {
         {
-            if(_currentMsg.Operation != message.Operation)
+            if(message.Operation != EfemOperation.ClearError && message.Operation != EfemOperation.Ready && _currentMsg.Operation != message.Operation && _backroundMsg.Operation != message.Operation)
             {
             {
                 return;
                 return;
             }
             }
@@ -677,13 +753,92 @@ namespace Venus_RT.Devices.EFEM
             switch(message.Operation)
             switch(message.Operation)
             {
             {
                 case EfemOperation.ClearError:
                 case EfemOperation.ClearError:
+                case EfemOperation.Align:
+                case EfemOperation.Map:
                 case EfemOperation.Pick:
                 case EfemOperation.Pick:
                 case EfemOperation.Place:
                 case EfemOperation.Place:
                 case EfemOperation.Extend:
                 case EfemOperation.Extend:
                 case EfemOperation.Goto:
                 case EfemOperation.Goto:
+                case EfemOperation.Orgsh:
+                case EfemOperation.EmsStop:
                     _status = RState.End;
                     _status = RState.End;
                     break;
                     break;
+                case EfemOperation.StateTrack:
+                    {
+                        _waferPresence = message.Data.Count >= 1 ? message.Data.First() : string.Empty;
+                        _status = RState.End;
+                    }
+                    break;
+                case EfemOperation.Home:
+                    {
+                        if(_currentMsg.Port == ModuleName.EFEM)
+                        {
+                            _LPMs[0].OnHomed();
+                            _LPMs[1].OnHomed();
+                        }
+                        else if(ModuleHelper.IsLoadPort(_currentMsg.Port))
+                        {
+                            _LPMs[_currentMsg.Port - ModuleName.LP1].OnHomed();
+                        }
+
+                        _status = RState.End;
+                    }
+                    break;
+                case EfemOperation.Load:
+                    {
+                        _LPMs[message.Port - ModuleName.LP1].OnLoaded();
+                    }
+                    break;
+                case EfemOperation.Unload:
+                    {
+                        _LPMs[message.Port - ModuleName.LP1].OnUnloaded();
+                    }
+                    break;
+                case EfemOperation.CarrierId:
+                    {
+                        if(message.Head == EfemMessage.MsgHead.GET)
+                        {
+                            _LPMs[message.Port - ModuleName.LP1].OnCarrierIDRead(message.Data.First());
+                        }
+                        else
+                        {
+                            _LPMs[message.Port - ModuleName.LP1].OnCarrierIDWrite(message.Data.First());
+                        }
+                    }
+                    break;
+                case EfemOperation.Clamp:
+                    {
+                        _LPMs[message.Port - ModuleName.LP1].OnClamped(_bIsUnloadClamp);
+                    }
+                    break;
+                case EfemOperation.Unclamp:
+                    {
+                        _LPMs[message.Port - ModuleName.LP1].OnUnclamped();
+                    }
+                    break;
+                case EfemOperation.Grip:
+                    {
+                        if (_currentMsg.Parameters[1] == "ARM2")
+                        {
+                            GripStateBlade1 = _currentMsg.Parameters[0];
+                        }
+                        else
+                        {
+                            GripStateBlade2 = _currentMsg.Parameters[0];
+                        }
+                    }
+                    break;
+                case EfemOperation.Ready:
+                    {
+                        Singleton<RouteManager>.Instance.EFEM.PostMsg(EfemEntity.MSG.CommReady);
+                    }
+                    break; 
             }
             }
         }
         }
+
+        async void SendBack(string data)
+        {
+            await Task.Run(()=> _socket.Write(data + '\r'));
+        }
     }
     }
 }
 }

+ 10 - 10
Venus/Venus_RT/Devices/EFEM/Loadport.cs

@@ -626,12 +626,12 @@ namespace Venus_RT.Devices.EFEM
 
 
                             if (st == WaferStatus.Normal)
                             if (st == WaferStatus.Normal)
                             {
                             {
-                                EV.PostInfoLog(this.Module.ToString(), $"Found Wafer on Slot {index + 1} {WaferSize}");
+                                //EV.PostInfoLog(this.Module.ToString(), $"Found Wafer on Slot {index + 1} {WaferSize}");
                             }
                             }
                             else
                             else
                             {
                             {
                                 resultNormal = false;
                                 resultNormal = false;
-                                EV.PostAlarmLog(this.Module.ToString(), $"Found {st} Wafer on Slot {index + 1} {WaferSize}");
+                                //EV.PostAlarmLog(this.Module.ToString(), $"Found {st} Wafer on Slot {index + 1} {WaferSize}");
                             }
                             }
                         }
                         }
                     }
                     }
@@ -641,12 +641,12 @@ namespace Venus_RT.Devices.EFEM
                     dvidMap[DVIDName.PortID] = Module == ModuleName.LP1 ? "1" : "2";
                     dvidMap[DVIDName.PortID] = Module == ModuleName.LP1 ? "1" : "2";
                     if (resultNormal)
                     if (resultNormal)
                     {
                     {
-                        EV.Notify(Module == ModuleName.LP1 ? Port1MappingComplete : Port2MappingComplete, dvidMap);
+                        //EV.Notify(Module == ModuleName.LP1 ? Port1MappingComplete : Port2MappingComplete, dvidMap);
                     }
                     }
                     else
                     else
                     {
                     {
                         //EV.Notify(Module == ModuleName.LP1 ? Port1MappingFailed : Port2MappingFailed, dvidMap);
                         //EV.Notify(Module == ModuleName.LP1 ? Port1MappingFailed : Port2MappingFailed, dvidMap);
-                        EV.PostAlarmLog(Module == ModuleName.LP1 ? "Port1" : "Port2", " MappingFailed");
+                        //EV.PostAlarmLog(Module == ModuleName.LP1 ? "Port1" : "Port2", " MappingFailed");
                     }
                     }
 
 
                     this.IsMapped = true;
                     this.IsMapped = true;
@@ -684,7 +684,7 @@ namespace Venus_RT.Devices.EFEM
                         {
                         {
                             this.HasCassette = false;
                             this.HasCassette = false;
                             this.IsMapped = false;
                             this.IsMapped = false;
-                            EV.PostInfoLog(mod.ToString(), "Cassette removed");
+                            //EV.PostInfoLog(mod.ToString(), "Cassette removed");
                             OP.DoOperation("System.CassetteLeave");     //For unload light control off afer job done
                             OP.DoOperation("System.CassetteLeave");     //For unload light control off afer job done
                             CarrierManager.Instance.DeleteCarrier(Module.ToString());
                             CarrierManager.Instance.DeleteCarrier(Module.ToString());
                             WaferManager.Instance.DeleteWafer(this.Module, 0, 25);
                             WaferManager.Instance.DeleteWafer(this.Module, 0, 25);
@@ -704,9 +704,9 @@ namespace Venus_RT.Devices.EFEM
                             CarrierManager.Instance.CreateCarrier(Module.ToString());
                             CarrierManager.Instance.CreateCarrier(Module.ToString());
                             EV.PostInfoLog(mod.ToString(), $"Cassette {WaferSize} arrived");
                             EV.PostInfoLog(mod.ToString(), $"Cassette {WaferSize} arrived");
 
 
-                            var dvid1 = new SerializableDictionary<string, string>();
-                            dvid1["PortID"] = mod == ModuleName.LP1 ? "1" : "2";
-                            EV.Notify(mod == ModuleName.LP1 ? Port1CassetteArrive : Port2CassetteArrive, dvid1);
+                            //var dvid1 = new SerializableDictionary<string, string>();
+                            //dvid1["PortID"] = mod == ModuleName.LP1 ? "1" : "2";
+                            //EV.Notify(mod == ModuleName.LP1 ? Port1CassetteArrive : Port2CassetteArrive, dvid1);
                             JobDone = false;
                             JobDone = false;
                             _waferThicknessType = "";
                             _waferThicknessType = "";
                         }
                         }
@@ -715,9 +715,9 @@ namespace Venus_RT.Devices.EFEM
                     this.Protrusion = !baData1[9];
                     this.Protrusion = !baData1[9];
                     if (Protrusion)
                     if (Protrusion)
                     {
                     {
-                        EV.PostAlarmLog(Module.ToString(), "发现 wafer 突出");
+                        //EV.PostAlarmLog(Module.ToString(), "发现 wafer 突出");
 
 
-                        EV.Notify(AlarmWaferProtrude);
+                        //EV.Notify(AlarmWaferProtrude);
                         Singleton<RouteManager>.Instance.EFEM.PostMsg(EfemEntity.MSG.Error);
                         Singleton<RouteManager>.Instance.EFEM.PostMsg(EfemEntity.MSG.Error);
                     }
                     }
 
 

+ 83 - 67
Venus/Venus_RT/Modules/EFEM/EfemEntity.cs

@@ -111,20 +111,22 @@ namespace Venus_RT.Modules
         private readonly EfemPickRoutine _pickRoutine;
         private readonly EfemPickRoutine _pickRoutine;
         private readonly EfemPlaceRoutine _placeRoutine;
         private readonly EfemPlaceRoutine _placeRoutine;
         private readonly EfemSwapRoutine _swapRoutine;
         private readonly EfemSwapRoutine _swapRoutine;
+        private readonly EfemHomeRoutine _homeRoutine;
 
 
         // Constructor
         // Constructor
         //
         //
         public EfemEntity()
         public EfemEntity()
         {
         {
-            _smallWafer = SC.GetValue<int>($"System.SmallWafer");
-            _midWafer = SC.GetValue<int>($"System.MidWafer");
-            _bigWafer = SC.GetValue<int>($"System.BigWafer");
+            //_smallWafer = SC.GetValue<int>($"System.SmallWafer");
+            //_midWafer = SC.GetValue<int>($"System.MidWafer");
+            //_bigWafer = SC.GetValue<int>($"System.BigWafer");
             _efemType = (EfemType)SC.GetValue<int>($"EFEM.EfemType");
             _efemType = (EfemType)SC.GetValue<int>($"EFEM.EfemType");
 
 
             _efem = new JetEfem();
             _efem = new JetEfem();
 
 
             Name = ModuleName.EFEM.ToString();
             Name = ModuleName.EFEM.ToString();
 
 
+            _homeRoutine    = new EfemHomeRoutine(_efem);
             _pickRoutine    = new EfemPickRoutine(_efem);
             _pickRoutine    = new EfemPickRoutine(_efem);
             _placeRoutine   = new EfemPlaceRoutine(_efem);
             _placeRoutine   = new EfemPlaceRoutine(_efem);
             _swapRoutine    = new EfemSwapRoutine(_efem);
             _swapRoutine    = new EfemSwapRoutine(_efem);
@@ -150,18 +152,18 @@ namespace Venus_RT.Modules
             _lpms[0].Initialize();
             _lpms[0].Initialize();
             _lpms[1].Initialize();
             _lpms[1].Initialize();
 
 
-            OP.Subscribe($"{ModuleName.EFEM}.{EfemOperation.Home}",         (cmd, args) => { PostMsg(MSG.HomeAll); return true; });
-            OP.Subscribe($"{ModuleName.EFEM}.{EfemOperation.ClearError}",        (cmd, args) => { PostMsg(MSG.Recover); return true; });
-            OP.Subscribe($"{ModuleName.EFEM}.{EfemOperation.TurnOffBuzzer}", (cmd, args) => { PostMsg(MSG.TurnOffBuzzer); return true; });
+            OP.Subscribe($"{ModuleName.EFEM}.{EfemOperation.Home}",             (cmd, args) => { PostMsg(MSG.HomeAll); return true; });
+            OP.Subscribe($"{ModuleName.EFEM}.{EfemOperation.ClearError}",       (cmd, args) => { PostMsg(MSG.Recover); return true; });
+            OP.Subscribe($"{ModuleName.EFEM}.{EfemOperation.TurnOffBuzzer}",    (cmd, args) => { PostMsg(MSG.TurnOffBuzzer); return true; });
             //OP.Subscribe($"{ModuleName.EFEM}.{EfemOperation.SwitchOnBuzzerAndRed}", (cmd, args) => { PostMsg(MSG.SwitchOnBuzzerAndRed); return true; });
             //OP.Subscribe($"{ModuleName.EFEM}.{EfemOperation.SwitchOnBuzzerAndRed}", (cmd, args) => { PostMsg(MSG.SwitchOnBuzzerAndRed); return true; });
-            OP.Subscribe($"{ModuleName.EFEM}.Online",                       (cmd, args) => { PostMsg(MSG.Online); return true; });
-            OP.Subscribe($"{ModuleName.EfemRobot}.{EfemOperation.Pick}",    (cmd, args) => { PostMsg(MSG.Pick, args[0], args[1], args[3], args[2]); return true; });
-            OP.Subscribe($"{ModuleName.EfemRobot}.{EfemOperation.Place}",   (cmd, args) => { PostMsg(MSG.Place, args[0], args[1], args[3], args[2]); return true; });
-            OP.Subscribe($"{ModuleName.EfemRobot}.{EfemOperation.Extend}",  (cmd, args) => { PostMsg(MSG.Extend, args[0], args[1], args[2]); return true; });
-            OP.Subscribe($"{ModuleName.EfemRobot}.{EfemOperation.Retract}", (cmd, args) => { PostMsg(MSG.Retract, args[0], args[1]); return true; });
-            OP.Subscribe($"{ModuleName.EfemRobot}.{EfemOperation.Abort}",   (cmd, args) => { PostMsg(MSG.Abort); return true; });
-            OP.Subscribe($"{ModuleName.EfemRobot}.{EfemOperation.Home}",    (cmd, args) => { PostMsg(MSG.HomeRB); return true; });
-            OP.Subscribe($"{ModuleName.EfemRobot}.{EfemOperation.Grip}", (cmd, args) =>
+            OP.Subscribe($"{ModuleName.EFEM}.Online",                           (cmd, args) => { PostMsg(MSG.Online); return true; });
+            OP.Subscribe($"{ModuleName.EfemRobot}.{EfemOperation.Pick}",        (cmd, args) => { PostMsg(MSG.Pick, args[0], args[1], args[3], args[2]); return true; });
+            OP.Subscribe($"{ModuleName.EfemRobot}.{EfemOperation.Place}",       (cmd, args) => { PostMsg(MSG.Place, args[0], args[1], args[3], args[2]); return true; });
+            OP.Subscribe($"{ModuleName.EfemRobot}.{EfemOperation.Extend}",      (cmd, args) => { PostMsg(MSG.Extend, args[0], args[1], args[2]); return true; });
+            OP.Subscribe($"{ModuleName.EfemRobot}.{EfemOperation.Retract}",     (cmd, args) => { PostMsg(MSG.Retract, args[0], args[1]); return true; });
+            OP.Subscribe($"{ModuleName.EfemRobot}.{EfemOperation.Abort}",       (cmd, args) => { PostMsg(MSG.Abort); return true; });
+            OP.Subscribe($"{ModuleName.EfemRobot}.{EfemOperation.Home}",        (cmd, args) => { PostMsg(MSG.HomeRB); return true; });
+            OP.Subscribe($"{ModuleName.EfemRobot}.{EfemOperation.Grip}",        (cmd, args) =>
             {
             {
                 bool isGrip = ((string)args[0]).ToLower() == "on";
                 bool isGrip = ((string)args[0]).ToLower() == "on";
 
 
@@ -174,23 +176,23 @@ namespace Venus_RT.Modules
 
 
             OP.Subscribe($"{ModuleName.Aligner1}.{EfemOperation.Home}",     (cmd, args) => { PostMsg(MSG.HomeAL, ModuleName.Aligner1); return true; });
             OP.Subscribe($"{ModuleName.Aligner1}.{EfemOperation.Home}",     (cmd, args) => { PostMsg(MSG.HomeAL, ModuleName.Aligner1); return true; });
             OP.Subscribe($"{ModuleName.Aligner2}.{EfemOperation.Home}",     (cmd, args) => { PostMsg(MSG.HomeAL, ModuleName.Aligner2); return true; });
             OP.Subscribe($"{ModuleName.Aligner2}.{EfemOperation.Home}",     (cmd, args) => { PostMsg(MSG.HomeAL, ModuleName.Aligner2); return true; });
-            OP.Subscribe($"{ModuleName.Cooling1}.{EfemOperation.Home}", (cmd, args) => { PostMsg(MSG.HomeAL, ModuleName.Cooling1); return true; });
-            OP.Subscribe($"{ModuleName.Cooling2}.{EfemOperation.Home}", (cmd, args) => { PostMsg(MSG.HomeAL, ModuleName.Cooling2); return true; });
+            OP.Subscribe($"{ModuleName.Cooling1}.{EfemOperation.Home}",     (cmd, args) => { PostMsg(MSG.HomeAL, ModuleName.Cooling1); return true; });
+            OP.Subscribe($"{ModuleName.Cooling2}.{EfemOperation.Home}",     (cmd, args) => { PostMsg(MSG.HomeAL, ModuleName.Cooling2); return true; });
             OP.Subscribe($"{ModuleName.Aligner1}.{EfemOperation.Align}",    (cmd, args) => { PostMsg(MSG.Align, ModuleName.Aligner1, args[0]); return true; });
             OP.Subscribe($"{ModuleName.Aligner1}.{EfemOperation.Align}",    (cmd, args) => { PostMsg(MSG.Align, ModuleName.Aligner1, args[0]); return true; });
             OP.Subscribe($"{ModuleName.Aligner2}.{EfemOperation.Align}",    (cmd, args) => { PostMsg(MSG.Align, ModuleName.Aligner2, args[0]); return true; });
             OP.Subscribe($"{ModuleName.Aligner2}.{EfemOperation.Align}",    (cmd, args) => { PostMsg(MSG.Align, ModuleName.Aligner2, args[0]); return true; });
-            OP.Subscribe($"{ModuleName.Cooling1}.{EfemOperation.Align}", (cmd, args) => { PostMsg(MSG.Align, ModuleName.Cooling1, args[0]); return true; });
-            OP.Subscribe($"{ModuleName.Cooling2}.{EfemOperation.Align}", (cmd, args) => { PostMsg(MSG.Align, ModuleName.Cooling2, args[0]); return true; });
+            OP.Subscribe($"{ModuleName.Cooling1}.{EfemOperation.Align}",    (cmd, args) => { PostMsg(MSG.Align, ModuleName.Cooling1, args[0]); return true; });
+            OP.Subscribe($"{ModuleName.Cooling2}.{EfemOperation.Align}",    (cmd, args) => { PostMsg(MSG.Align, ModuleName.Cooling2, args[0]); return true; });
             OP.Subscribe($"{ModuleName.Aligner1}.{EfemOperation.Lift}",     (cmd, args) => { PostMsg(MSG.Lift, ModuleName.Aligner1); return true; });
             OP.Subscribe($"{ModuleName.Aligner1}.{EfemOperation.Lift}",     (cmd, args) => { PostMsg(MSG.Lift, ModuleName.Aligner1); return true; });
             OP.Subscribe($"{ModuleName.Aligner2}.{EfemOperation.Lift}",     (cmd, args) => { PostMsg(MSG.Lift, ModuleName.Aligner2); return true; });
             OP.Subscribe($"{ModuleName.Aligner2}.{EfemOperation.Lift}",     (cmd, args) => { PostMsg(MSG.Lift, ModuleName.Aligner2); return true; });
-            OP.Subscribe($"{ModuleName.Cooling1}.{EfemOperation.Lift}", (cmd, args) => { PostMsg(MSG.Lift, ModuleName.Cooling1); return true; });
-            OP.Subscribe($"{ModuleName.Cooling2}.{EfemOperation.Lift}", (cmd, args) => { PostMsg(MSG.Lift, ModuleName.Cooling2); return true; });
+            OP.Subscribe($"{ModuleName.Cooling1}.{EfemOperation.Lift}",     (cmd, args) => { PostMsg(MSG.Lift, ModuleName.Cooling1); return true; });
+            OP.Subscribe($"{ModuleName.Cooling2}.{EfemOperation.Lift}",     (cmd, args) => { PostMsg(MSG.Lift, ModuleName.Cooling2); return true; });
 
 
-            DATA.Subscribe($"{Name}.FsmState",     () => ((STATE)fsm.State).ToString());
-            DATA.Subscribe($"{Name}.FsmPrevState", () => ((STATE)fsm.PrevState).ToString());
-            DATA.Subscribe($"{Name}.FsmLastMessage", GetFsmLastMessage);
-            DATA.Subscribe($"{Name}.SmallWafer", () => _smallWafer);
-            DATA.Subscribe($"{Name}.BigWafer", () => _bigWafer);
-            DATA.Subscribe($"{Name}.MidWafer", () => _midWafer);
+            DATA.Subscribe($"{Name}.FsmState",          () => ((STATE)fsm.State).ToString());
+            DATA.Subscribe($"{Name}.FsmPrevState",      () => ((STATE)fsm.PrevState).ToString());
+            DATA.Subscribe($"{Name}.FsmLastMessage",    GetFsmLastMessage);
+            DATA.Subscribe($"{Name}.SmallWafer",        () => _smallWafer);
+            DATA.Subscribe($"{Name}.BigWafer",          () => _bigWafer);
+            DATA.Subscribe($"{Name}.MidWafer",          () => _midWafer);
 
 
             return true;
             return true;
         }
         }
@@ -200,7 +202,7 @@ namespace Venus_RT.Modules
             fsm = new StateMachine<EfemEntity>("EFEM", (int)STATE.Unknown, 50);
             fsm = new StateMachine<EfemEntity>("EFEM", (int)STATE.Unknown, 50);
             fsm.EnableRepeatedMsg(true);
             fsm.EnableRepeatedMsg(true);
 
 
-            AnyStateTransition(FSM_MSG.TIMER,               fnMonitor,          FSM_STATE.SAME);
+            //AnyStateTransition(FSM_MSG.TIMER,               fnMonitor,          FSM_STATE.SAME);
             AnyStateTransition(MSG.TurnOffBuzzer,           fnTurnOffBuzzer,    FSM_STATE.SAME);
             AnyStateTransition(MSG.TurnOffBuzzer,           fnTurnOffBuzzer,    FSM_STATE.SAME);
             AnyStateTransition(MSG.Recover,                 fnRecover,          STATE.Idle);
             AnyStateTransition(MSG.Recover,                 fnRecover,          STATE.Idle);
             AnyStateTransition(MSG.Error,                   fnError,            STATE.Error);
             AnyStateTransition(MSG.Error,                   fnError,            STATE.Error);
@@ -209,12 +211,18 @@ namespace Venus_RT.Modules
             AnyStateTransition(MSG.ToInit,                  fnToInit,           STATE.Init);
             AnyStateTransition(MSG.ToInit,                  fnToInit,           STATE.Init);
 
 
 
 
-            Transition(STATE.Unknown,       MSG.CommReady,          null,               STATE.Init);
+            AnyStateTransition(MSG.CommReady,          fnCommReady,               STATE.Init);
+
+            Transition(STATE.Init, FSM_MSG.TIMER, fnMonitor, STATE.Init);
+            Transition(STATE.Idle, FSM_MSG.TIMER, fnMonitor, STATE.Idle);
+            Transition(STATE.Error, FSM_MSG.TIMER, fnMonitor, STATE.Error);
 
 
             // Home
             // Home
             Transition(STATE.Init,          MSG.HomeAll,            fnHomeAll,          STATE.Initializing);
             Transition(STATE.Init,          MSG.HomeAll,            fnHomeAll,          STATE.Initializing);
             Transition(STATE.Idle,          MSG.HomeAll,            fnHomeAll,          STATE.Initializing);    // 暂时加,出错的时候做 HOME
             Transition(STATE.Idle,          MSG.HomeAll,            fnHomeAll,          STATE.Initializing);    // 暂时加,出错的时候做 HOME
-            Transition(STATE.Initializing,  MSG.ActionDone,         null, STATE.        Orgshing);
+            Transition(STATE.Error,         MSG.HomeAll,            fnHomeAll,          STATE.Initializing);
+            Transition(STATE.Initializing,  FSM_MSG.TIMER,          fnHomingTimeout,    STATE.Idle);
+
             Transition(STATE.Orgshing,      MSG.ActionDone,         fnActionDone,       STATE.Idle);
             Transition(STATE.Orgshing,      MSG.ActionDone,         fnActionDone,       STATE.Idle);
             Transition(STATE.Idle,          MSG.HomeRB,             fnHomeRobot,        STATE.InitingRB);
             Transition(STATE.Idle,          MSG.HomeRB,             fnHomeRobot,        STATE.InitingRB);
             Transition(STATE.InitingRB,     MSG.ActionDone,         null,               STATE.Idle);
             Transition(STATE.InitingRB,     MSG.ActionDone,         null,               STATE.Idle);
@@ -263,13 +271,30 @@ namespace Venus_RT.Modules
             EnumLoop<STATE>.ForEach((item) => { fsm.MapState((int)item, item.ToString()); });
             EnumLoop<STATE>.ForEach((item) => { fsm.MapState((int)item, item.ToString()); });
 
 
             EnumLoop<MSG>.ForEach((item) => { fsm.MapMessage((int)item, item.ToString()); });
             EnumLoop<MSG>.ForEach((item) => { fsm.MapMessage((int)item, item.ToString()); });
+
+            Running = true;
         }
         }
 
 
-        private bool fnHomeAll(object[] param)
+        private bool fnCommReady(object[] param)
         {
         {
-            _efem.HomeAll();
             return true;
             return true;
         }
         }
+        private bool fnHomeAll(object[] param)
+        {
+            return _homeRoutine.Start(ModuleName.EFEM) == RState.Running;
+        }
+
+        private bool fnHomingTimeout(object[] param)
+        {
+            RState ret = _homeRoutine.Monitor();
+            if (ret == RState.Failed || ret == RState.Timeout)
+            {
+                PostMsg(MSG.Error);
+                return false;
+            }
+
+            return ret == RState.End;
+        }
 
 
         private bool fnHomeRobot(object[] param)
         private bool fnHomeRobot(object[] param)
         {
         {
@@ -292,16 +317,6 @@ namespace Venus_RT.Modules
             return true;
             return true;
         }
         }
 
 
-        private bool fnEnterExecute(object[] param)
-        {
-            return false;
-        }
-
-        private bool fnExitExecute(object[] param)
-        {
-            return false;
-        }
-
         private bool fnActionDone(object[] param)
         private bool fnActionDone(object[] param)
         {
         {
             return false;
             return false;
@@ -323,29 +338,8 @@ namespace Venus_RT.Modules
 
 
         private bool fnMonitor(object[] param)
         private bool fnMonitor(object[] param)
         {
         {
-            STATE curSt = (STATE)fsm.State;
-            if (curSt == STATE.Initializing || curSt == STATE.Mapping || curSt == STATE.Picking || curSt == STATE.Placing
-                || curSt == STATE.Orgshing || curSt == STATE.Lifting || curSt == STATE.Extending || curSt == STATE.Retracting
-                || curSt == STATE.InitingAL || curSt == STATE.InitingRB)
-            {
-                int time = SC.GetValue<int>("EFEM.MotionTimeout");
-
-                if (fsm.ElapsedTime > time * 1000)
-                {
-                    EV.PostAlarmLog("EFEM", $"Can not complete motion {curSt} in {time} seconds. ");
-                    PostMsg(MSG.Error);
-                }
-            }
-
-            if (curSt == STATE.Aligning)
-            {
-                if (fsm.ElapsedTime > 10 * 1000)
-                {
-                    EV.PostAlarmLog(ModuleName.Aligner.ToString(), "Align timeout");
-                    PostMsg(MSG.ActionDone, "alignment timeout");
-                }
-            }
-
+            _efem.Monitor();
+            _debugRoutine();
             return true;
             return true;
         }
         }
  
  
@@ -534,9 +528,6 @@ namespace Venus_RT.Modules
                     return false;
                     return false;
             }
             }
 
 
-
-
-
             return true;
             return true;
         }
         }
 
 
@@ -761,6 +752,31 @@ namespace Venus_RT.Modules
         {
         {
             //_efem[module].NoteJobComplete();
             //_efem[module].NoteJobComplete();
         }
         }
+
+        private void _debugRoutine()
+        {
+            int flag = 0;
+            // Test Home routine
+            if (flag == 1)
+            {
+
+                PostMsg(MSG.HomeAll);
+            }
+            else if (flag == 2)
+            {
+            }
+            else if (flag == 3)
+            {
+            }
+            else if (flag == 4)
+            {
+            }
+            else if (flag == 5)
+            {
+            }
+            else if (flag == 6)
+            { }
+        }
     }
     }
 
 
     /// <summary>
     /// <summary>

+ 127 - 8
Venus/Venus_RT/Modules/EFEM/EfemHomeRoutine.cs

@@ -7,6 +7,7 @@ using MECF.Framework.Common.Equipment;
 using MECF.Framework.Common.SubstrateTrackings;
 using MECF.Framework.Common.SubstrateTrackings;
 using Venus_Core;
 using Venus_Core;
 using Aitex.Core.RT.Log;
 using Aitex.Core.RT.Log;
+using Aitex.Core.Common;
 using Aitex.Core.Util;
 using Aitex.Core.Util;
 using MECF.Framework.Common.Schedulers;
 using MECF.Framework.Common.Schedulers;
 using System.Collections.Generic;
 using System.Collections.Generic;
@@ -52,12 +53,12 @@ namespace Venus_RT.Modules.EFEM
         public RState Monitor()
         public RState Monitor()
         {
         {
 
 
-            if(_targetModule == ModuleName.System)
+            if(_targetModule == ModuleName.EFEM)
             {
             {
-                Runner.Run((int)HomeStep.ClearError,            ClearError,             IsStepComplete,     _homeTimeout)
-                    .Run((int)HomeStep.InitRobot,               HomeAll,                IsStepComplete,     _homeTimeout)
-                    .Run((int)HomeStep.HomeAllAxes,             HomeAllAxes,            IsStepComplete,     _homeTimeout)
-                    .Run((int)HomeStep.CheckWaferPresence,      CheckWaferPresence,     IsStepComplete,     _homeTimeout)
+                Runner.Run((int)HomeStep.ClearError,            ClearError,             IsStepComplete,         _homeTimeout)
+                    .Run((int)HomeStep.InitRobot,               HomeAll,                IsStepComplete,         _homeTimeout)
+                    .Run((int)HomeStep.HomeAllAxes,             HomeAllAxes,            IsStepComplete,         _homeTimeout)
+                    .Run((int)HomeStep.CheckWaferPresence,      CheckWaferPresence,     VerifyWaferPresence,    _homeTimeout)
                     .End((int)HomeStep.End,                     NullFun,                _delay_50ms);
                     .End((int)HomeStep.End,                     NullFun,                _delay_50ms);
             }
             }
             else
             else
@@ -80,7 +81,7 @@ namespace Venus_RT.Modules.EFEM
             {
             {
                 return true;
                 return true;
             }
             }
-            else if (_efem.Status != RState.Running)
+            else if (_efem.Status == RState.Failed || _efem.Status == RState.Timeout)
             {
             {
                 LOG.Write(eEvent.ERR_EFEM_ROBOT, Module, $"Efem home failed: {_efem.Status}");
                 LOG.Write(eEvent.ERR_EFEM_ROBOT, Module, $"Efem home failed: {_efem.Status}");
                 return true;
                 return true;
@@ -106,12 +107,130 @@ namespace Venus_RT.Modules.EFEM
 
 
         private bool HomeAllAxes()
         private bool HomeAllAxes()
         {
         {
-            return true;
+            return _efem.OriginalSearch();
         }
         }
 
 
         private bool CheckWaferPresence()
         private bool CheckWaferPresence()
         {
         {
-            return true;
+            return _efem.CheckWaferPresence();
+        }
+
+        private bool VerifyWaferPresence()
+        {
+            if (_efem.Status == RState.End)
+            {
+                var waferPresence = _efem.GetWaferPresence();
+                //000/111 upperArmWafer, lowerArmWafer, alignerWafer1, alignerWafer2,  coolingwafer1,coolingwafer2
+                if (waferPresence.Length != 6)
+                {
+                    LOG.Write(eEvent.ERR_EFEM_ROBOT, Module, $"EFEM Track wafer present return invalid value, {waferPresence}, should be 6 characters");
+                    return true;
+                }
+
+                //upper arm
+                if (waferPresence[0] == '1')
+                {
+                    if (WaferManager.Instance.CheckNoWafer(ModuleName.EfemRobot, 1))
+                    {
+                        WaferManager.Instance.CreateWafer(ModuleName.EfemRobot, 1,  WaferStatus.Normal);
+                    }
+                }
+                else
+                {
+                    if (WaferManager.Instance.CheckHasWafer(ModuleName.EfemRobot, 1))
+                    {
+                        LOG.Write(eEvent.ERR_EFEM_ROBOT, Module, $" {ModuleName.EfemRobot} upper arm has wafer information, while EFEM return empty, manually delete if really no wafer");
+                    }
+                }
+
+                //lower arm
+                if (waferPresence[1] == '1')
+                {
+                    if (WaferManager.Instance.CheckNoWafer(ModuleName.EfemRobot, 0))
+                    {
+                        WaferManager.Instance.CreateWafer(ModuleName.EfemRobot, 0, WaferStatus.Normal);
+                    }
+                }
+                else
+                {
+                    if (WaferManager.Instance.CheckHasWafer(ModuleName.EfemRobot, 0))
+                    {
+                        LOG.Write(eEvent.ERR_EFEM_ROBOT, Module, $" {ModuleName.EfemRobot} lower arm has wafer information, while EFEM return empty, manually delete if really no wafer");
+                    }
+                }
+
+                //aligner1
+                if (waferPresence[2] == '1')
+                {
+                    if (WaferManager.Instance.CheckNoWafer(ModuleName.Aligner1, 0))
+                    {
+                        WaferManager.Instance.CreateWafer(ModuleName.Aligner1, 0, WaferStatus.Normal);
+                    }
+                }
+                else
+                {
+                    if (WaferManager.Instance.CheckHasWafer(ModuleName.Aligner1, 0))
+                    {
+                        LOG.Write(eEvent.ERR_EFEM_ROBOT, Module, $" {ModuleName.Aligner1} has wafer information, while EFEM return empty, manually delete if really no wafer");
+                    }
+                }
+
+                //aligner2
+                if (waferPresence[3] == '1')
+                {
+                    if (WaferManager.Instance.CheckNoWafer(ModuleName.Aligner2, 0))
+                    {
+                        WaferManager.Instance.CreateWafer(ModuleName.Aligner2, 0, WaferStatus.Normal);
+                    }
+                }
+                else
+                {
+                    if (WaferManager.Instance.CheckHasWafer(ModuleName.Aligner2, 0))
+                    {
+                        LOG.Write(eEvent.ERR_EFEM_ROBOT, Module, $" {ModuleName.Aligner2} has wafer information, while EFEM return empty, manually delete if really no wafer");
+                    }
+                }
+
+                //cooling1
+                if (waferPresence[4] == '1')
+                {
+                    if (WaferManager.Instance.CheckNoWafer(ModuleName.Cooling1, 0))
+                    {
+                        WaferManager.Instance.CreateWafer(ModuleName.Cooling1, 0, WaferStatus.Normal);
+                    }
+                }
+                else
+                {
+                    if (WaferManager.Instance.CheckHasWafer(ModuleName.Cooling1, 0))
+                    {
+                        LOG.Write(eEvent.ERR_EFEM_ROBOT, Module, $" {ModuleName.Cooling1} has wafer information, while EFEM return empty, manually delete if really no wafer");
+                    }
+                }
+
+                //cooling2
+                if (waferPresence[5] == '1')
+                {
+                    if (WaferManager.Instance.CheckNoWafer(ModuleName.Cooling2, 0))
+                    {
+                        WaferManager.Instance.CreateWafer(ModuleName.Cooling2, 0, WaferStatus.Normal);
+                    }
+                }
+                else
+                {
+                    if (WaferManager.Instance.CheckHasWafer(ModuleName.Cooling2, 0))
+                    {
+                        LOG.Write(eEvent.ERR_EFEM_ROBOT, Module, $" {ModuleName.Cooling2} has wafer information, while EFEM return empty, manually delete if really no wafer");
+                    }
+                }
+                return true;
+            }
+            else if (_efem.Status != RState.Running)
+            {
+                LOG.Write(eEvent.ERR_EFEM_ROBOT, Module, $"Efem StateTrack failed: {_efem.Status}");
+                return true;
+            }
+            else
+                return false;
         }
         }
 
 
     }
     }

+ 77 - 0
Venus/Venus_RT/Modules/RouteManager.cs

@@ -76,6 +76,46 @@ namespace Venus_RT.Modules
 
 
         public string Name { get; set; }
         public string Name { get; set; }
 
 
+        public bool IsAutoMode
+        {
+            get
+            {
+                return fsm.State == (int)RtState.AutoRunning || fsm.State == (int)RtState.AutoIdle;
+            }
+        }
+
+        public bool IsInit
+        {
+            get { return fsm.State == (int)RtState.Init; }
+        }
+
+        public bool IsIdle
+        {
+            get { return fsm.State == (int)RtState.Idle || fsm.State == (int)RtState.AutoIdle; }
+        }
+        public bool IsAlarm
+        {
+            get { return fsm.State == (int)RtState.Error; }
+        }
+
+        public bool IsEntityError
+        {
+            get
+            {
+                return (EFEM?.IsError ?? false)
+                       || (PMA?.IsError ?? false)
+                       || (PMB?.IsError ?? false);
+            }
+        }
+
+        public bool IsRunning
+        {
+            get
+            {
+                return !IsInit && !IsAlarm && !IsIdle;
+            }
+        }
+
         private TMCycle _TMCycle;
         private TMCycle _TMCycle;
 
 
         public RouteManager()
         public RouteManager()
@@ -103,6 +143,9 @@ namespace Venus_RT.Modules
             if (ModuleHelper.IsInstalled(ModuleName.LLB))
             if (ModuleHelper.IsInstalled(ModuleName.LLB))
                 LLB = new LLEntity(ModuleName.LLB);
                 LLB = new LLEntity(ModuleName.LLB);
 
 
+            if (ModuleHelper.IsInstalled(ModuleName.EFEM))
+                EFEM = new EfemEntity();
+
             fsm = new StateMachine<RouteManager>(Name, (int)RtState.Init, 200);
             fsm = new StateMachine<RouteManager>(Name, (int)RtState.Init, 200);
 
 
             SubscribeOperation();
             SubscribeOperation();
@@ -128,6 +171,38 @@ namespace Venus_RT.Modules
 
 
             return true;
             return true;
         }
         }
+
+        void SubscribeDataVariable()
+        {
+            DATA.Subscribe("Rt.Status", () => ((RtState)fsm.State).ToString());
+
+            DATA.Subscribe(ModuleName.System.ToString(), "AlarmEvent", EV.GetAlarmEvent);
+
+            DATA.Subscribe("System.IsAutoMode", () => IsAutoMode);
+            DATA.Subscribe("System.IsIdle", () => IsIdle || IsInit);
+            DATA.Subscribe("System.IsAlarm", () => IsAlarm || IsEntityError);
+            DATA.Subscribe("System.IsBusy", () => IsRunning);
+            DATA.Subscribe("System.IsWaitUnload", () => /*_isWaitUnload && */IsAutoMode);
+            //DATA.Subscribe("System.IsConnectedWithHost", () => Singleton<FaManager>.Instance.IsConnected);
+
+            DATA.Subscribe("EquipmentMode", () => IsAutoMode ? 0 : 1, SubscriptionAttribute.FLAG.IgnoreSaveDB);
+
+            DATA.Subscribe("EquipmentStatus", () =>
+            {
+                //"0 = Uninit
+                //1 = Idle
+                //2 = Running
+                //3 = Error
+                //4 = Pause
+                //"
+                if (IsInit) return 0;
+                if (IsIdle) return 1;
+                if (IsAlarm) return 3;
+
+                return 2;
+            }, SubscriptionAttribute.FLAG.IgnoreSaveDB);
+        }
+
         void SubscribeOperation()
         void SubscribeOperation()
         {
         {
             OP.Subscribe("CreateWafer", InvokeCreateWafer);
             OP.Subscribe("CreateWafer", InvokeCreateWafer);
@@ -262,6 +337,8 @@ namespace Venus_RT.Modules
             LLA?.Initialize();
             LLA?.Initialize();
             LLB?.Initialize();
             LLB?.Initialize();
 
 
+            EFEM?.Initialize();
+
             _TMCycle = new TMCycle();
             _TMCycle = new TMCycle();
 
 
             BuildTransitionTable();
             BuildTransitionTable();

+ 7 - 3
Venus/Venus_Simulator/Devices/EfemSimulator.cs

@@ -142,11 +142,12 @@ namespace Venus_Simulator.Devices
                 strINF += "/1111111111111110001111111;";
                 strINF += "/1111111111111110001111111;";
                 break;
                 break;
             case EfemOperation.Home:
             case EfemOperation.Home:
-                //string s1 = "EVT:SIGSTAT/P1/00000381/00000000;\rEVT:SIGSTAT/P2/00000381/00000000;\rEVT:SIGSTAT/System/0000FFF7/00000004;\r";
-                //strINF = s1 + strACK.Replace(ACK, "INF");
+                string s1 = "EVT:SIGSTAT/P1/00000381/00000000;\rEVT:SIGSTAT/P2/00000381/00000000;\rEVT:SIGSTAT/System/0000FFF7/00000004;\r";
+                strINF = s1 + strACK.Replace(ACK, "INF");
                 SendSystemData();
                 SendSystemData();
                 SendLP1Data();
                 SendLP1Data();
                 SendLP2Data();
                 SendLP2Data();
+                OnWriteMessage(strACK.Replace(ACK, "INF"));
                     return;
                     return;
             case EfemOperation.Map:
             case EfemOperation.Map:
                 Match m2 = Regex.Match(strACK, SFOUP);
                 Match m2 = Regex.Match(strACK, SFOUP);
@@ -157,6 +158,9 @@ namespace Venus_Simulator.Devices
                     strINF = s2 + strACK.Replace(ACK, "INF");
                     strINF = s2 + strACK.Replace(ACK, "INF");
                 }
                 }
                 break;
                 break;
+            case EfemOperation.StateTrack:
+                    strINF = "INF:STATE/TRACK/000000;";
+                    break;
             case EfemOperation.Align:
             case EfemOperation.Align:
             case EfemOperation.Pick:
             case EfemOperation.Pick:
             case EfemOperation.Place:
             case EfemOperation.Place:
@@ -398,7 +402,7 @@ namespace Venus_Simulator.Devices
             //15 Cassette Door Door Closed  
             //15 Cassette Door Door Closed  
             data1 |= (!_isDoorOpen ? 0x00008000u : 0x0);
             data1 |= (!_isDoorOpen ? 0x00008000u : 0x0);
 
 
-            return data1;
+            return 65535;
         }
         }
     }
     }
 }
 }