From 6fc65c5cf54432d1044fbe9799aca76f7273798c Mon Sep 17 00:00:00 2001
From: LAPTOP-SNT8I5JK\Boounion <Chenluhua@qq.com>
Date: 星期五, 23 五月 2025 18:02:27 +0800
Subject: [PATCH] Merge branch 'clh'

---
 Document/ESWIN_EAS_Bonder_Inline_Mapping_Address_v1.1.5(5).xlsx |    0 
 SourceCode/Bond/Servo/CPagePortProperty.cpp                     |  274 ++++++
 SourceCode/Bond/Servo/Servo.vcxproj                             |    9 
 SourceCode/Bond/Servo/resource.h                                |    0 
 SourceCode/Bond/Servo/CPagePortProperty.h                       |    5 
 SourceCode/Bond/Servo/CVacuumBake.cpp                           |    5 
 Document/ESWIN_EAS_Bonder_Inline_Mapping_Address_v1.1.6.xlsx    |    0 
 SourceCode/Bond/Servo/CGlass.h                                  |    7 
 SourceCode/Bond/Servo/CEFEM.h                                   |    2 
 SourceCode/Bond/Servo/CMaster.h                                 |    2 
 Document/simulator/SEComSimulator.Conf                          |   53 +
 SourceCode/Bond/Servo/CBakeCooling.cpp                          |    8 
 SourceCode/Bond/x64/Debug/Res/msgbox_tip.ico                    |    0 
 SourceCode/Bond/Servo/MsgDlg.h                                  |   72 +
 SourceCode/Bond/Servo/CBakeCooling.h                            |    1 
 SourceCode/Bond/Servo/CEquipment.cpp                            |  104 +
 SourceCode/Bond/Servo/CPortStatusReport.h                       |   42 
 SourceCode/Bond/Servo/Servo.rc                                  |    0 
 SourceCode/Bond/Servo/CMaster.cpp                               |   31 
 SourceCode/Bond/Servo/CBonder.h                                 |    1 
 SourceCode/Bond/Servo/CPageGraph2.cpp                           |   16 
 SourceCode/Bond/x64/Debug/Servo.ini                             |    4 
 SourceCode/Bond/Servo/CLoadPort.h                               |   26 
 SourceCode/Bond/Servo/CPagePortStatus.h                         |   38 
 SourceCode/Bond/Servo/JobSlotGrid.h                             |   37 
 SourceCode/Bond/Servo/CLoadPort.cpp                             |  604 ++++++++++++
 SourceCode/Bond/Servo/CMeasurement.h                            |    2 
 SourceCode/Bond/Servo/CVacuumBake.h                             |    2 
 SourceCode/Bond/Servo/CPortStatusReport.cpp                     |  212 ++++
 SourceCode/Bond/Servo/JobSlotGrid.cpp                           |  170 +++
 SourceCode/Bond/x64/Debug/Master.dat                            |    0 
 SourceCode/Bond/Servo/CMeasurement.cpp                          |    8 
 SourceCode/Bond/Servo/Servo.vcxproj.filters                     |    9 
 SourceCode/Bond/x64/Debug/EqsGraph.ini                          |   51 +
 SourceCode/Bond/x64/Debug/Res/msgbox_warning.ico                |    0 
 SourceCode/Bond/Servo/CPagePortStatus.cpp                       |  148 +++
 SourceCode/Bond/Servo/MsgDlg.cpp                                |  303 ++++++
 SourceCode/Bond/x64/Debug/Res/msgbox_question.ico               |    0 
 SourceCode/Bond/Servo/CVcrEventReport.h                         |    4 
 SourceCode/Bond/x64/Debug/Res/msgbox_error.ico                  |    0 
 SourceCode/Bond/Servo/CEFEM.cpp                                 |   95 -
 SourceCode/Bond/Servo/CVcrEventReport.cpp                       |   26 
 SourceCode/Bond/Servo/CEquipment.h                              |   25 
 SourceCode/Bond/Servo/ServoCommo.h                              |   37 
 SourceCode/Bond/x64/Debug/Res/msgbox_succeed.ico                |    0 
 SourceCode/Bond/Servo/CBonder.cpp                               |    5 
 SourceCode/Bond/Servo/Common.h                                  |  163 ++-
 47 files changed, 2,396 insertions(+), 205 deletions(-)

diff --git "a/Document/ESWIN_EAS_Bonder_Inline_Mapping_Address_v1.1.5\0505\051.xlsx" "b/Document/ESWIN_EAS_Bonder_Inline_Mapping_Address_v1.1.5\0505\051.xlsx"
index 0e5b4b9..8b3d58f 100644
--- "a/Document/ESWIN_EAS_Bonder_Inline_Mapping_Address_v1.1.5\0505\051.xlsx"
+++ "b/Document/ESWIN_EAS_Bonder_Inline_Mapping_Address_v1.1.5\0505\051.xlsx"
Binary files differ
diff --git a/Document/ESWIN_EAS_Bonder_Inline_Mapping_Address_v1.1.6.xlsx b/Document/ESWIN_EAS_Bonder_Inline_Mapping_Address_v1.1.6.xlsx
new file mode 100644
index 0000000..85b872f
--- /dev/null
+++ b/Document/ESWIN_EAS_Bonder_Inline_Mapping_Address_v1.1.6.xlsx
Binary files differ
diff --git a/Document/simulator/SEComSimulator.Conf b/Document/simulator/SEComSimulator.Conf
new file mode 100644
index 0000000..a2608bb
--- /dev/null
+++ b/Document/simulator/SEComSimulator.Conf
@@ -0,0 +1,53 @@
+锘�<?xml version="1.0" encoding="utf-8"?>
+<SEComSimulatorConfiguration>
+  <LASTSELECT>
+    <LASTSEComID>A</LASTSEComID>
+  </LASTSELECT>
+  <SEComID>
+    <A>
+      <DRVINFO>
+        <DEVICEID>1</DEVICEID>
+        <IDENTITY>Host</IDENTITY>
+      </DRVINFO>
+      <LOGINFO>
+        <DIR>D:\Chenluhua\dazi\a</DIR>
+        <SECSIMODE>D</SECSIMODE>
+        <SECSIIMODE>D</SECSIIMODE>
+        <XMLMODE />
+        <DRIVERMODE>N</DRIVERMODE>
+        <DRIVERLEVEL>5</DRIVERLEVEL>
+        <BACKUP>2</BACKUP>
+      </LOGINFO>
+      <SECSMODE MODE="HSMS">
+        <HSMS>
+          <HSMSMODE>Active</HSMSMODE>
+          <REMOTEIP>127.0.0.1</REMOTEIP>
+          <REMOTEPORT>7000</REMOTEPORT>
+          <LOCALPORT>
+          </LOCALPORT>
+        </HSMS>
+        <SECS1>
+          <MASTER>True</MASTER>
+          <COMPORT>COM1</COMPORT>
+          <AUTOBAUD>False</AUTOBAUD>
+          <BAUDRATE>9600</BAUDRATE>
+          <INTERLEAVE>False</INTERLEAVE>
+          <RETRYCOUNT>3</RETRYCOUNT>
+        </SECS1>
+      </SECSMODE>
+      <TIMEOUT>
+        <T1>0.5</T1>
+        <T2>10</T2>
+        <T3>45</T3>
+        <T4>45</T4>
+        <T5>10</T5>
+        <T6>5</T6>
+        <T7>10</T7>
+        <T8>10</T8>
+      </TIMEOUT>
+      <EXT>
+        <LINKTEST>120</LINKTEST>
+      </EXT>
+    </A>
+  </SEComID>
+</SEComSimulatorConfiguration>
\ No newline at end of file
diff --git a/SourceCode/Bond/Servo/CBakeCooling.cpp b/SourceCode/Bond/Servo/CBakeCooling.cpp
index 5e374ab..96367ba 100644
--- a/SourceCode/Bond/Servo/CBakeCooling.cpp
+++ b/SourceCode/Bond/Servo/CBakeCooling.cpp
@@ -35,8 +35,7 @@
 		LOGI("<CBakeCooling>initPins");
 		addPin(SERVO::PinType::INPUT, _T("In1"));
 		addPin(SERVO::PinType::INPUT, _T("In2"));
-		addPin(SERVO::PinType::OUTPUT, _T("Out1"));
-		addPin(SERVO::PinType::OUTPUT, _T("Out2"));
+		addPin(SERVO::PinType::OUTPUT, _T("Out"));
 	}
 
 	void CBakeCooling::onTimer(UINT nTimerid)
@@ -68,4 +67,9 @@
 
 		return (m_glassList.size() < 4);
 	}
+
+	int CBakeCooling::getIndexerOperationModeBaseValue()
+	{
+		return 25000;
+	}
 }
diff --git a/SourceCode/Bond/Servo/CBakeCooling.h b/SourceCode/Bond/Servo/CBakeCooling.h
index 6d85350..bea7a17 100644
--- a/SourceCode/Bond/Servo/CBakeCooling.h
+++ b/SourceCode/Bond/Servo/CBakeCooling.h
@@ -20,6 +20,7 @@
         virtual void getAttributeVector(CAttributeVector& attrubutes);
         virtual int recvIntent(CPin* pPin, CIntent* pIntent);
         virtual BOOL glassWillArrive(CGlass* pGlass);
+        virtual int getIndexerOperationModeBaseValue();
 	};
 }
 
diff --git a/SourceCode/Bond/Servo/CBonder.cpp b/SourceCode/Bond/Servo/CBonder.cpp
index 655c99a..f485a94 100644
--- a/SourceCode/Bond/Servo/CBonder.cpp
+++ b/SourceCode/Bond/Servo/CBonder.cpp
@@ -448,4 +448,9 @@
 
 		return 0;
 	}
+
+	int CBonder::getIndexerOperationModeBaseValue()
+	{
+		return m_nIndex == 0 ? 15000 : 20000;
+	}
 }
diff --git a/SourceCode/Bond/Servo/CBonder.h b/SourceCode/Bond/Servo/CBonder.h
index e05dce4..f24e05b 100644
--- a/SourceCode/Bond/Servo/CBonder.h
+++ b/SourceCode/Bond/Servo/CBonder.h
@@ -23,6 +23,7 @@
         virtual BOOL glassWillArrive(CGlass* pGlass);
         virtual BOOL onPreStoredJob(int port, CJobDataB* pJobDataB);
         virtual int onProcessData(CProcessData* pProcessData);
+        virtual int getIndexerOperationModeBaseValue();
 
     public:
         void setIndex(unsigned int index);
diff --git a/SourceCode/Bond/Servo/CEFEM.cpp b/SourceCode/Bond/Servo/CEFEM.cpp
index b59945d..05e7074 100644
--- a/SourceCode/Bond/Servo/CEFEM.cpp
+++ b/SourceCode/Bond/Servo/CEFEM.cpp
@@ -3,7 +3,7 @@
 #include "Log.h"
 
 
-#define ADD_EQ_CASSETTE_TRANSFER_STATE_STEP(name,ws,index,psd) {				\
+#define ADD_EQ_PORT_STATUS_STEP(name,ws,index,psd) {							\
 	CEqCassetteTransferStateStep* pStep = new CEqCassetteTransferStateStep();	\
 	pStep->setName(name);														\
 	pStep->setWriteSignalDev(ws);												\
@@ -439,12 +439,18 @@
 		}
 
 		{
-			// VCR1 Event Report
-			CEqVcrEventStep* pStep = new CEqVcrEventStep();
+			// VCR Event Report
+			// 机器上报扫码结果,扫码器预计安装在巡边检机器上
+			CEqReadStep* pStep = new CEqReadStep(0x5fef, 15 * 2,
+				[&](void* pFrom, int code, const char* pszData, size_t size) -> int {
+					if (code == ROK && pszData != nullptr && size > 0) {
+						decodeVCREventReport((CStep*)pFrom, pszData, size);
+					}
+					return -1;
+				});
 			pStep->setName(STEP_EQ_VCR1_EVENT_REPORT);
+			pStep->setProp("Port", (void*)1);
 			pStep->setWriteSignalDev(0x4a);
-			pStep->setReturnDev(0x91e);
-			pStep->setVcrEventReportDev(0x5fef);
 			if (addStep(STEP_ID_VCR1_EVENT_REPORT, pStep) != 0) {
 				delete pStep;
 			}
@@ -515,56 +521,6 @@
 				delete pStep;
 			}
 		}
-
-		// CEqCassetteTranserStateStep
-		ADD_EQ_CASSETTE_TRANSFER_STATE_STEP(STEP_EQ_P1_CASSETTE_EMPTY, 0xd8,
-			STEP_ID_PORT1_CASSETTIE_EMPTY, 0x6050);
-		ADD_EQ_CASSETTE_TRANSFER_STATE_STEP(STEP_EQ_P1_CASSETTE_LOAD_EADY, 0xe0,
-			STEP_ID_PORT1_CASSETTIE_LOAD_READY, 0x6050);
-		ADD_EQ_CASSETTE_TRANSFER_STATE_STEP(STEP_EQ_P1_CASSETTE_LOADED, 0xe8,
-			STEP_ID_PORT1_CASSETTIE_LOADED, 0x6050);
-		ADD_EQ_CASSETTE_TRANSFER_STATE_STEP(STEP_EQ_P1_CASSETTE_INUSE, 0xf0,
-			STEP_ID_PORT1_CASSETTIE_INUSE, 0x6050);
-		ADD_EQ_CASSETTE_TRANSFER_STATE_STEP(STEP_EQ_P1_CASSETTE_UNLOAD_EADY, 0xf8,
-			STEP_ID_PORT1_CASSETTIE_UNLOAD_READY, 0x60f50);
-		ADD_EQ_CASSETTE_TRANSFER_STATE_STEP(STEP_EQ_P1_CASSETTE_BLOCKED, 0x100,
-			STEP_ID_PORT1_CASSETTIE_BLOCKED, 0x6050);
-		ADD_EQ_CASSETTE_TRANSFER_STATE_STEP(STEP_EQ_P2_CASSETTE_EMPTY, 0xd9,
-			STEP_ID_PORT2_CASSETTIE_EMPTY, 0x6070);
-		ADD_EQ_CASSETTE_TRANSFER_STATE_STEP(STEP_EQ_P2_CASSETTE_LOAD_EADY, 0xe1,
-			STEP_ID_PORT2_CASSETTIE_LOAD_READY, 0x6070);
-		ADD_EQ_CASSETTE_TRANSFER_STATE_STEP(STEP_EQ_P2_CASSETTE_LOADED, 0xe9,
-			STEP_ID_PORT2_CASSETTIE_LOADED, 0x6070);
-		ADD_EQ_CASSETTE_TRANSFER_STATE_STEP(STEP_EQ_P2_CASSETTE_INUSE, 0xf1,
-			STEP_ID_PORT2_CASSETTIE_INUSE, 0x6070);
-		ADD_EQ_CASSETTE_TRANSFER_STATE_STEP(STEP_EQ_P2_CASSETTE_UNLOAD_EADY, 0xf9,
-			STEP_ID_PORT2_CASSETTIE_UNLOAD_READY, 0x6070);
-		ADD_EQ_CASSETTE_TRANSFER_STATE_STEP(STEP_EQ_P2_CASSETTE_BLOCKED, 0x101,
-			STEP_ID_PORT2_CASSETTIE_BLOCKED, 0x6070);
-		ADD_EQ_CASSETTE_TRANSFER_STATE_STEP(STEP_EQ_P3_CASSETTE_EMPTY, 0xda,
-			STEP_ID_PORT3_CASSETTIE_EMPTY, 0x6090);
-		ADD_EQ_CASSETTE_TRANSFER_STATE_STEP(STEP_EQ_P3_CASSETTE_LOAD_EADY, 0xe2,
-			STEP_ID_PORT3_CASSETTIE_LOAD_READY, 0x6090);
-		ADD_EQ_CASSETTE_TRANSFER_STATE_STEP(STEP_EQ_P3_CASSETTE_LOADED, 0xea,
-			STEP_ID_PORT3_CASSETTIE_INUSE, 0x6090);
-		ADD_EQ_CASSETTE_TRANSFER_STATE_STEP(STEP_EQ_P3_CASSETTE_INUSE, 0xf2,
-			STEP_ID_PORT3_CASSETTIE_INUSE, 0x6090);
-		ADD_EQ_CASSETTE_TRANSFER_STATE_STEP(STEP_EQ_P3_CASSETTE_UNLOAD_EADY, 0xfa,
-			STEP_ID_PORT3_CASSETTIE_UNLOAD_READY, 0x6090);
-		ADD_EQ_CASSETTE_TRANSFER_STATE_STEP(STEP_EQ_P3_CASSETTE_BLOCKED, 0x102,
-			STEP_ID_PORT3_CASSETTIE_BLOCKED, 0x6090);
-		ADD_EQ_CASSETTE_TRANSFER_STATE_STEP(STEP_EQ_P4_CASSETTE_EMPTY, 0xdb,
-			STEP_ID_PORT4_CASSETTIE_EMPTY, 0x60b0);
-		ADD_EQ_CASSETTE_TRANSFER_STATE_STEP(STEP_EQ_P4_CASSETTE_LOAD_EADY, 0xe3,
-			STEP_ID_PORT4_CASSETTIE_LOAD_READY, 0x60b0);
-		ADD_EQ_CASSETTE_TRANSFER_STATE_STEP(STEP_EQ_P4_CASSETTE_LOADED, 0xeb,
-			STEP_ID_PORT4_CASSETTIE_LOADED, 0x60b0);
-		ADD_EQ_CASSETTE_TRANSFER_STATE_STEP(STEP_EQ_P4_CASSETTE_INUSE, 0xf3,
-			STEP_ID_PORT4_CASSETTIE_INUSE, 0x60b0);
-		ADD_EQ_CASSETTE_TRANSFER_STATE_STEP(STEP_EQ_P4_CASSETTE_UNLOAD_EADY, 0xfb,
-			STEP_ID_PORT4_CASSETTIE_UNLOAD_READY, 0x60b0);
-		ADD_EQ_CASSETTE_TRANSFER_STATE_STEP(STEP_EQ_P4_CASSETTE_BLOCKED, 0x103,
-			STEP_ID_PORT4_CASSETTIE_BLOCKED, 0x60b0);
 
 		{
 			// Received Job Report Upstream#1~9
@@ -659,25 +615,17 @@
 				delete pStep;
 			}
 		}
-	}
 
-	int CEFEM::onStepEvent(CStep* pStep, int code)
-	{
-		int nRet = CEquipment::onStepEvent(pStep, code);
-		if (nRet > 0) return nRet;
-
-		if (code == STEP_EVENT_READDATA) {
-			if (isCassetteTransferStateStep(pStep)) {
-				SERVO::CEqCassetteTransferStateStep* pEqCassetteStep = (SERVO::CEqCassetteTransferStateStep*)pStep;
-				int id = pEqCassetteStep->getID();
-				if (id == STEP_ID_PORT1_CASSETTIE_EMPTY) {
-
-				}
+		{
+			// Indexer Operation Mode Change
+			CEqWriteStep* pStep = new CEqWriteStep();
+			pStep->setName(STEP_EFEM_IN_OP_MODE_CHANGE);
+			pStep->setWriteSignalDev(0x070);
+			pStep->setDataDev(0x023);
+			if (addStep(STEP_ID_IN_OP_CMD_REPLY, pStep) != 0) {
+				delete pStep;
 			}
 		}
-
-
-		return 0;
 	}
 
 	void CEFEM::onTimer(UINT nTimerid)
@@ -808,4 +756,9 @@
 
 		return -1;
 	}
+
+	int CEFEM::getIndexerOperationModeBaseValue()
+	{
+		return 10000;
+	}
 }
diff --git a/SourceCode/Bond/Servo/CEFEM.h b/SourceCode/Bond/Servo/CEFEM.h
index 5607ec3..d8a4e1b 100644
--- a/SourceCode/Bond/Servo/CEFEM.h
+++ b/SourceCode/Bond/Servo/CEFEM.h
@@ -20,7 +20,6 @@
         virtual void term();
         virtual void initPins();
         virtual void initSteps();
-        virtual int onStepEvent(CStep* pStep, int code);
         virtual void onTimer(UINT nTimerid);
         virtual void serialize(CArchive& ar);
         virtual void getAttributeVector(CAttributeVector& attrubutes);
@@ -31,6 +30,7 @@
         virtual int onSentOutJob(int port, CJobDataS* pJobDataS);
         virtual int onFetchedOutJob(int port, CJobDataB* pJobDataB);
         virtual int onStoredJob(int port, CJobDataB* pJobDataB);
+        virtual int getIndexerOperationModeBaseValue();
 
     public:
         void setPort(unsigned int index, CLoadPort* pPort);
diff --git a/SourceCode/Bond/Servo/CEquipment.cpp b/SourceCode/Bond/Servo/CEquipment.cpp
index 1d3f312..e4d8c07 100644
--- a/SourceCode/Bond/Servo/CEquipment.cpp
+++ b/SourceCode/Bond/Servo/CEquipment.cpp
@@ -493,30 +493,30 @@
 
 
 		// CEqCassetteTranserStateStep
-		CHECK_READ_STEP_SIGNAL(STEP_ID_PORT1_CASSETTIE_EMPTY, pszData, size);
-		CHECK_READ_STEP_SIGNAL(STEP_ID_PORT1_CASSETTIE_LOAD_READY, pszData, size);
-		CHECK_READ_STEP_SIGNAL(STEP_ID_PORT1_CASSETTIE_LOADED, pszData, size);
-		CHECK_READ_STEP_SIGNAL(STEP_ID_PORT1_CASSETTIE_INUSE, pszData, size);
-		CHECK_READ_STEP_SIGNAL(STEP_ID_PORT1_CASSETTIE_UNLOAD_READY, pszData, size);
-		CHECK_READ_STEP_SIGNAL(STEP_ID_PORT1_CASSETTIE_BLOCKED, pszData, size);
-		CHECK_READ_STEP_SIGNAL(STEP_ID_PORT2_CASSETTIE_EMPTY, pszData, size);
-		CHECK_READ_STEP_SIGNAL(STEP_ID_PORT2_CASSETTIE_LOAD_READY, pszData, size);
-		CHECK_READ_STEP_SIGNAL(STEP_ID_PORT2_CASSETTIE_LOADED, pszData, size);
-		CHECK_READ_STEP_SIGNAL(STEP_ID_PORT2_CASSETTIE_INUSE, pszData, size);
-		CHECK_READ_STEP_SIGNAL(STEP_ID_PORT2_CASSETTIE_UNLOAD_READY, pszData, size);
-		CHECK_READ_STEP_SIGNAL(STEP_ID_PORT2_CASSETTIE_BLOCKED, pszData, size);
-		CHECK_READ_STEP_SIGNAL(STEP_ID_PORT3_CASSETTIE_EMPTY, pszData, size);
-		CHECK_READ_STEP_SIGNAL(STEP_ID_PORT3_CASSETTIE_LOAD_READY, pszData, size);
-		CHECK_READ_STEP_SIGNAL(STEP_ID_PORT3_CASSETTIE_LOADED, pszData, size);
-		CHECK_READ_STEP_SIGNAL(STEP_ID_PORT3_CASSETTIE_INUSE, pszData, size);
-		CHECK_READ_STEP_SIGNAL(STEP_ID_PORT3_CASSETTIE_UNLOAD_READY, pszData, size);
-		CHECK_READ_STEP_SIGNAL(STEP_ID_PORT3_CASSETTIE_BLOCKED, pszData, size);
-		CHECK_READ_STEP_SIGNAL(STEP_ID_PORT4_CASSETTIE_EMPTY, pszData, size);
-		CHECK_READ_STEP_SIGNAL(STEP_ID_PORT4_CASSETTIE_LOAD_READY, pszData, size);
-		CHECK_READ_STEP_SIGNAL(STEP_ID_PORT4_CASSETTIE_LOADED, pszData, size);
-		CHECK_READ_STEP_SIGNAL(STEP_ID_PORT4_CASSETTIE_INUSE, pszData, size);
-		CHECK_READ_STEP_SIGNAL(STEP_ID_PORT4_CASSETTIE_UNLOAD_READY, pszData, size);
-		CHECK_READ_STEP_SIGNAL(STEP_ID_PORT4_CASSETTIE_BLOCKED, pszData, size);
+		CHECK_READ_STEP_SIGNAL(STEP_ID_PORT1_EMPTY, pszData, size);
+		CHECK_READ_STEP_SIGNAL(STEP_ID_PORT1_LOAD_READY, pszData, size);
+		CHECK_READ_STEP_SIGNAL(STEP_ID_PORT1_LOADED, pszData, size);
+		CHECK_READ_STEP_SIGNAL(STEP_ID_PORT1_INUSE, pszData, size);
+		CHECK_READ_STEP_SIGNAL(STEP_ID_PORT1_UNLOAD_READY, pszData, size);
+		CHECK_READ_STEP_SIGNAL(STEP_ID_PORT1_BLOCKED, pszData, size);
+		CHECK_READ_STEP_SIGNAL(STEP_ID_PORT2_EMPTY, pszData, size);
+		CHECK_READ_STEP_SIGNAL(STEP_ID_PORT2_LOAD_READY, pszData, size);
+		CHECK_READ_STEP_SIGNAL(STEP_ID_PORT2_LOADED, pszData, size);
+		CHECK_READ_STEP_SIGNAL(STEP_ID_PORT2_INUSE, pszData, size);
+		CHECK_READ_STEP_SIGNAL(STEP_ID_PORT2_UNLOAD_READY, pszData, size);
+		CHECK_READ_STEP_SIGNAL(STEP_ID_PORT2_BLOCKED, pszData, size);
+		CHECK_READ_STEP_SIGNAL(STEP_ID_PORT3_EMPTY, pszData, size);
+		CHECK_READ_STEP_SIGNAL(STEP_ID_PORT3_LOAD_READY, pszData, size);
+		CHECK_READ_STEP_SIGNAL(STEP_ID_PORT3_LOADED, pszData, size);
+		CHECK_READ_STEP_SIGNAL(STEP_ID_PORT3_INUSE, pszData, size);
+		CHECK_READ_STEP_SIGNAL(STEP_ID_PORT3_UNLOAD_READY, pszData, size);
+		CHECK_READ_STEP_SIGNAL(STEP_ID_PORT3_BLOCKED, pszData, size);
+		CHECK_READ_STEP_SIGNAL(STEP_ID_PORT4_EMPTY, pszData, size);
+		CHECK_READ_STEP_SIGNAL(STEP_ID_PORT4_LOAD_READY, pszData, size);
+		CHECK_READ_STEP_SIGNAL(STEP_ID_PORT4_LOADED, pszData, size);
+		CHECK_READ_STEP_SIGNAL(STEP_ID_PORT4_INUSE, pszData, size);
+		CHECK_READ_STEP_SIGNAL(STEP_ID_PORT4_UNLOAD_READY, pszData, size);
+		CHECK_READ_STEP_SIGNAL(STEP_ID_PORT4_BLOCKED, pszData, size);
 	}
 
 	BOOL CEquipment::isBitOn(const char* pszData, size_t size, int index)
@@ -595,6 +595,7 @@
 				panelNo = (value & 0xffff);
 				LOGI("Cim Message Confirm(msgID = %d, panel no.=%d).", msgId, panelNo);
 			}
+			/*
 			else if (isVcrEventStep(pStep)) {
 				SERVO::CEqVcrEventStep* pEqVcrEventStep = (SERVO::CEqVcrEventStep*)pStep;
 				CVcrEventReport* pVcrEventReport = pEqVcrEventStep->getVcrEventReport();
@@ -607,6 +608,7 @@
 				pEqVcrEventStep->setReturnCode(1);		
 				return 1;
 			}
+			*/
 		}
 
 
@@ -1090,6 +1092,34 @@
 		return 0;
 	}
 
+	int CEquipment::indexerOperationModeChange(IDNEXER_OPERATION_MODE mode, ONWRITED onWritedBlock/* = nullptr*/)
+	{
+		SERVO::CEqWriteStep* pStep = (SERVO::CEqWriteStep*)getStepWithName(STEP_EFEM_IN_OP_MODE_CHANGE);
+		if (pStep == nullptr) {
+			return -1;
+		}
+
+		unsigned short operationMode = (unsigned short)(mode + getIndexerOperationModeBaseValue());
+		LOGI("<CEquipment-%s>准备设置indexerOperationMode<%d>", m_strName.c_str(), (int)mode);
+		if (onWritedBlock != nullptr) {
+			pStep->writeShort(operationMode, onWritedBlock);
+		}
+		else {
+			pStep->writeShort(operationMode, [&, mode](int code) -> int {
+				if (code == WOK) {
+					LOGI("<CEquipment-%s>设置indexerOperationMode成功.", m_strName.c_str());
+				}
+				else {
+					LOGI("<CEquipment-%s>设置indexerOperationMode失败,code:%d", m_strName.c_str(), code);
+				}
+
+				return 0;
+				});
+		}
+
+		return 0;
+	}
+
 	int CEquipment::masterRecipeListRequest(short unitNo)
 	{
 		SERVO::CEqWriteStep* pStep = (SERVO::CEqWriteStep*)getStepWithName(STEP_EQ_MASTER_RECIPE_LIST_REQ);
@@ -1334,6 +1364,27 @@
 		return index;
 	}
 
+	int CEquipment::decodeVCREventReport(CStep* pStep, const char* pszData, size_t size)
+	{
+		CVcrEventReport vcrEventReport;
+		vcrEventReport.unserialize(pszData, size);
+		LOGI("<CEquipment-%s>decodeVCREventReport<Result:%d, GlassId:%s>\n", m_strName.c_str(),
+			vcrEventReport.getVcrResult(),
+			vcrEventReport.getGlassId().c_str());
+
+
+		// 缓存Attribute,用于调试时显示信息
+		unsigned int weight = 201;
+		CAttributeVector attrubutes;
+		vcrEventReport.getAttributeVector(attrubutes, weight);
+		pStep->addAttributeVector(attrubutes);
+
+		// 0426, 先固定返回1(OK)
+		((CReadStep*)pStep)->setReturnCode((short)VCR_Reply_Code::OK);
+
+		return 0;
+	}
+
 	int CEquipment::onPreStoredJob(int port, CJobDataB* pJobDataB)
 	{
 		LOGI("<CEquipment-%s>onPreStoredJob:port:%d|GlassId:%s",
@@ -1364,6 +1415,11 @@
 		return 0;
 	}
 
+	int CEquipment::getIndexerOperationModeBaseValue()
+	{
+		return 0;
+	}
+
 	int CEquipment::addJobDataB(CJobDataB* pJobDataB)
 	{
 		// 添加之前先删除旧的,以免数据重复
diff --git a/SourceCode/Bond/Servo/CEquipment.h b/SourceCode/Bond/Servo/CEquipment.h
index 8b4db97..6357114 100644
--- a/SourceCode/Bond/Servo/CEquipment.h
+++ b/SourceCode/Bond/Servo/CEquipment.h
@@ -32,6 +32,7 @@
 #include "CJobDataC.h"
 #include "CJobDataS.h"
 #include "CProcessData.h"
+#include "CPortStatusReport.h"
 
 
 namespace SERVO {
@@ -74,6 +75,18 @@
 		Local = 2
 	};
 
+	enum IDNEXER_OPERATION_MODE {
+		Normal = 1,
+		Clear_Out = 2,
+		Cold_Run = 2,
+		Start = 10,
+		Stop = 11,
+		Pause = 12,
+		Resume = 13,
+		Abort = 14,
+		Cancel = 15,
+	};
+
 	enum RCMD {
 		Robot_home = 1,
 		Transfer, 
@@ -85,6 +98,13 @@
 		Command_Clear,
 		Batch_get,
 		Batch_put
+	};
+
+	enum VCR_Reply_Code {
+		OK = 1,
+		NG,
+		Job_Data_Request,
+		VCR_Mismatch
 	};
 
 	// Robot cmd param
@@ -159,6 +179,7 @@
 		virtual BOOL onPreStoredJob(int port, CJobDataB* pJobDataB);
 		virtual int onStoredJob(int port, CJobDataB* pJobDataB);
 		virtual int onProcessData(CProcessData* pProcessData);
+		virtual int getIndexerOperationModeBaseValue();
 		void getGlassList(std::list<CGlass*>& list);
 		CGlass* getGlassFromList(const char* pszId);
 		CGlass* getFrontGlass();
@@ -179,6 +200,9 @@
 		int clearCimMessage(short id, short nTouchPanelNo);
 		int setDateTime(short year, short month, short day, short hour, short minute, short second);
 		int setDispatchingMode(DISPATCHING_MODE mode, ONWRITED onWritedBlock = nullptr);
+		int indexerOperationModeChange(IDNEXER_OPERATION_MODE mode, ONWRITED onWritedBlock = nullptr);
+
+
 
 		// 请求主配方列表
 		// unitNo: 0:local; Others:unit No
@@ -217,6 +241,7 @@
 		int decodeSentOutJobReport(CStep* pStep, int port, const char* pszData, size_t size);
 		int decodeFetchedOutJobReport(CStep* pStep, int port, const char* pszData, size_t size);
 		int decodeStoredJobReport(CStep* pStep, int port, const char* pszData, size_t size);
+		int decodeVCREventReport(CStep* pStep, const char* pszData, size_t size);
 		int addJobDataB(CJobDataB* pJobDataB);
 		int removeJobDataB(int nCassetteSequenceNo, int nJobSequenceNo);
 		CJobDataB* getJobDataB(int nCassetteSequenceNo, int nJobSequenceNo);
diff --git a/SourceCode/Bond/Servo/CGlass.h b/SourceCode/Bond/Servo/CGlass.h
index 8ed33c2..be44aaa 100644
--- a/SourceCode/Bond/Servo/CGlass.h
+++ b/SourceCode/Bond/Servo/CGlass.h
@@ -6,15 +6,10 @@
 #include "CJobDataB.h"
 #include "CJobDataC.h"
 #include "CJobDataS.h"
+#include "ServoCommo.h"
 
 
 namespace SERVO {
-	enum MaterialsType {
-		G1 = 0,
-		G2 = 1,
-		G1G2 = 2
-	};
-
 	class CGlass : public CContext
 	{
 	public:
diff --git a/SourceCode/Bond/Servo/CLoadPort.cpp b/SourceCode/Bond/Servo/CLoadPort.cpp
index d3879c3..1c7becf 100644
--- a/SourceCode/Bond/Servo/CLoadPort.cpp
+++ b/SourceCode/Bond/Servo/CLoadPort.cpp
@@ -85,7 +85,13 @@
 			static int writeSignalDev[] = { 0xa0, 0xa1, 0xa2, 0xa3 };
 			static int addr[] = { STEP_ID_PORT1_TYPE_CHANGE, STEP_ID_PORT2_TYPE_CHANGE, STEP_ID_PORT3_TYPE_CHANGE, STEP_ID_PORT4_TYPE_CHANGE };
 
-			CEqReadIntStep* pStep = new CEqReadIntStep(__INT16, dev[m_nIndex]);
+			CEqReadStep* pStep = new CEqReadStep(dev[m_nIndex], sizeof(short),
+				[&](void* pFrom, int code, const char* pszData, size_t size) -> int {
+					if (code == ROK && pszData != nullptr && size > 0) {
+						m_nType = (unsigned int)CToolUnits::toInt16(pszData);
+					}
+					return 0;
+				});
 			pStep->setName(pszName[m_nIndex]);
 			pStep->setWriteSignalDev(writeSignalDev[m_nIndex]);
 			if (addStep(addr[m_nIndex], pStep) != 0) {
@@ -100,7 +106,13 @@
 			static int writeSignalDev[] = { 0xa8, 0xa9, 0xaa, 0xab };
 			static int addr[] = { STEP_ID_PORT1_MODE_CHANGE, STEP_ID_PORT2_MODE_CHANGE, STEP_ID_PORT3_MODE_CHANGE, STEP_ID_PORT4_MODE_CHANGE };
 
-			CEqReadIntStep* pStep = new CEqReadIntStep(__INT16, dev[m_nIndex]);
+			CEqReadStep* pStep = new CEqReadStep(dev[m_nIndex], sizeof(short),
+				[&](void* pFrom, int code, const char* pszData, size_t size) -> int {
+					if (code == ROK && pszData != nullptr && size > 0) {
+						m_nMode = (unsigned int)CToolUnits::toInt16(pszData);
+					}
+					return 0;
+				});
 			pStep->setName(pszName[m_nIndex]);
 			pStep->setWriteSignalDev(writeSignalDev[m_nIndex]);
 			if (addStep(addr[m_nIndex], pStep) != 0) {
@@ -115,7 +127,13 @@
 			static int writeSignalDev[] = { 0xb0, 0xb1, 0xb2, 0xb3 };
 			static int addr[] = { STEP_ID_PORT1_CASSETTE_TYPE_CHANGE, STEP_ID_PORT2_CASSETTE_TYPE_CHANGE, STEP_ID_PORT3_CASSETTE_TYPE_CHANGE, STEP_ID_PORT4_CASSETTE_TYPE_CHANGE };
 
-			CEqReadIntStep* pStep = new CEqReadIntStep(__INT16, dev[m_nIndex]);
+			CEqReadStep* pStep = new CEqReadStep(dev[m_nIndex], sizeof(short),
+				[&](void* pFrom, int code, const char* pszData, size_t size) -> int {
+					if (code == ROK && pszData != nullptr && size > 0) {
+						m_nCassetteType = (unsigned int)CToolUnits::toInt16(pszData);
+					}
+					return 0;
+				});
 			pStep->setName(pszName[m_nIndex]);
 			pStep->setWriteSignalDev(writeSignalDev[m_nIndex]);
 			if (addStep(addr[m_nIndex], pStep) != 0) {
@@ -130,7 +148,13 @@
 			static int writeSignalDev[] = { 0xb8, 0xb9, 0xba, 0xbb };
 			static int addr[] = { STEP_ID_PORT1_TRANSFER_MODE_CHANGE, STEP_ID_PORT2_TRANSFER_MODE_CHANGE, STEP_ID_PORT3_TRANSFER_MODE_CHANGE, STEP_ID_PORT4_TRANSFER_MODE_CHANGE };
 
-			CEqReadIntStep* pStep = new CEqReadIntStep(__INT16, dev[m_nIndex]);
+			CEqReadStep* pStep = new CEqReadStep(dev[m_nIndex], sizeof(short),
+				[&](void* pFrom, int code, const char* pszData, size_t size) -> int {
+					if (code == ROK && pszData != nullptr && size > 0) {
+						m_nTransferMode = (unsigned int)CToolUnits::toInt16(pszData);
+					}
+					return 0;
+				});
 			pStep->setName(pszName[m_nIndex]);
 			pStep->setWriteSignalDev(writeSignalDev[m_nIndex]);
 			if (addStep(addr[m_nIndex], pStep) != 0) {
@@ -145,7 +169,13 @@
 			static int writeSignalDev[] = { 0xc0, 0xc1, 0xc2, 0xc3 };
 			static int addr[] = { STEP_ID_PORT1_ENABLE_MODE_CHANGE, STEP_ID_PORT2_ENABLE_MODE_CHANGE, STEP_ID_PORT3_ENABLE_MODE_CHANGE, STEP_ID_PORT4_ENABLE_MODE_CHANGE };
 
-			CEqReadIntStep* pStep = new CEqReadIntStep(__INT16, dev[m_nIndex]);
+			CEqReadStep* pStep = new CEqReadStep(dev[m_nIndex], sizeof(short),
+				[&](void* pFrom, int code, const char* pszData, size_t size) -> int {
+					if (code == ROK && pszData != nullptr && size > 0) {
+						m_bEnable = (unsigned int)CToolUnits::toInt16(pszData) == 1;
+					}
+					return 0;
+				});
 			pStep->setName(pszName[m_nIndex]);
 			pStep->setWriteSignalDev(writeSignalDev[m_nIndex]);
 			if (addStep(addr[m_nIndex], pStep) != 0) {
@@ -160,11 +190,151 @@
 			static int writeSignalDev[] = { 0xc8, 0xc9, 0xca, 0xcb };
 			static int addr[] = { STEP_ID_PORT1_TYPE_AUTO_CHANGE, STEP_ID_PORT2_TYPE_AUTO_CHANGE, STEP_ID_PORT3_TYPE_AUTO_CHANGE, STEP_ID_PORT4_TYPE_AUTO_CHANGE };
 
-			CEqReadIntStep* pStep = new CEqReadIntStep(__INT16, dev[m_nIndex]);
+			CEqReadStep* pStep = new CEqReadStep(dev[m_nIndex], sizeof(short),
+				[&](void* pFrom, int code, const char* pszData, size_t size) -> int {
+					if (code == ROK && pszData != nullptr && size > 0) {
+						m_bAutoChangeEnable = (unsigned int)CToolUnits::toInt16(pszData) == 1;
+					}
+					return 0;
+				});
 			pStep->setName(pszName[m_nIndex]);
 			pStep->setWriteSignalDev(writeSignalDev[m_nIndex]);
 			if (addStep(addr[m_nIndex], pStep) != 0) {
 				delete pStep;
+			}
+		}
+
+		{
+			// port command
+			// Port Type Change Command
+			static char* pszName[] = { STEP_PORT1_TYPE_CHANGE, STEP_PORT2_TYPE_CHANGE, STEP_PORT3_TYPE_CHANGE, STEP_PORT4_TYPE_CHANGE };
+			static int dev[] = { 0x024, 0x02c, 0x034, 0x03c };
+
+			CEqWriteStep* pStep = new CEqWriteStep();
+			pStep->setName(pszName[m_nIndex]);
+			pStep->setWriteSignalDev(0x100 + m_nIndex);
+			pStep->setDataDev(dev[m_nIndex]);
+			if (addStep(STEP_ID_PROT1_TYPE_CHANGE_REPLY + m_nIndex, pStep) != 0) {
+				delete pStep;
+			}
+		}
+
+		{
+			// port command
+			// Port Mode Change Command
+			static char* pszName[] = { STEP_PORT1_MODE_CHANGE, STEP_PORT2_MODE_CHANGE, STEP_PORT3_MODE_CHANGE, STEP_PORT4_MODE_CHANGE };
+			static int dev[] = { 0x025, 0x02d, 0x035, 0x03d };
+
+			CEqWriteStep* pStep = new CEqWriteStep();
+			pStep->setName(pszName[m_nIndex]);
+			pStep->setWriteSignalDev(0x108 + m_nIndex);
+			pStep->setDataDev(dev[m_nIndex]);
+			if (addStep(STEP_ID_PROT1_MODE_CHANGE_REPLY + m_nIndex, pStep) != 0) {
+				delete pStep;
+			}
+		}
+
+		{
+			// port command
+			// Port Transfer Mode Change Command
+			static char* pszName[] = { STEP_PORT1_TRANSFER_MODE_CHANGE, STEP_PORT2_TRANSFER_MODE_CHANGE, STEP_PORT3_TRANSFER_MODE_CHANGE, STEP_PORT4_TRANSFER_MODE_CHANGE };
+			static int dev[] = { 0x028, 0x030, 0x038, 0x040 };
+
+			CEqWriteStep* pStep = new CEqWriteStep();
+			pStep->setName(pszName[m_nIndex]);
+			pStep->setWriteSignalDev(0x110 + m_nIndex);
+			pStep->setDataDev(dev[m_nIndex]);
+			if (addStep(STEP_ID_PROT1_TRANSFER_MODE_CHANGE_REPLY + m_nIndex, pStep) != 0) {
+				delete pStep;
+			}
+		}
+
+		{
+			// port command
+			// Port Enable Mode Change Command
+			static char* pszName[] = { STEP_PORT1_ENABLE_MODE_CHANGE, STEP_PORT2_ENABLE_MODE_CHANGE, STEP_PORT3_ENABLE_MODE_CHANGE, STEP_PORT4_ENABLE_MODE_CHANGE };
+			static int dev[] = { 0x029, 0x031, 0x039, 0x041 };
+
+			CEqWriteStep* pStep = new CEqWriteStep();
+			pStep->setName(pszName[m_nIndex]);
+			pStep->setWriteSignalDev(0x118 + m_nIndex);
+			pStep->setDataDev(dev[m_nIndex]);
+			if (addStep(STEP_ID_PROT1_ENABLE_MODE_CHANGE_REPLY + m_nIndex, pStep) != 0) {
+				delete pStep;
+			}
+		}
+
+		{
+			// port command
+			// Port Type Auto Change Command
+			static char* pszName[] = { STEP_PORT1_TYPE_AUTO_CHANGE, STEP_PORT2_TYPE_AUTO_CHANGE, STEP_PORT3_TYPE_AUTO_CHANGE, STEP_PORT4_TYPE_AUTO_CHANGE };
+			static int dev[] = { 0x02A, 0x032, 0x03A, 0x042 };
+
+			CEqWriteStep* pStep = new CEqWriteStep();
+			pStep->setName(pszName[m_nIndex]);
+			pStep->setWriteSignalDev(0x120 + m_nIndex);
+			pStep->setDataDev(dev[m_nIndex]);
+			if (addStep(STEP_ID_PROT1_TYPE_AUTO_CHANGE_REPLY + m_nIndex, pStep) != 0) {
+				delete pStep;
+			}
+		}
+
+		{
+			// port command
+			// Port Cassette Type Change Command
+			static char* pszName[] = { STEP_PORT1_CASSETTE_TYPE_CHANGE, STEP_PORT2_CASSETTE_TYPE_CHANGE, STEP_PORT3_CASSETTE_TYPE_CHANGE, STEP_PORT4_CASSETTE_TYPE_CHANGE };
+			static int dev[] = { 0x026, 0x02E, 0x036, 0x03E };
+
+			CEqWriteStep* pStep = new CEqWriteStep();
+			pStep->setName(pszName[m_nIndex]);
+			pStep->setWriteSignalDev(0x128 + m_nIndex);
+			pStep->setDataDev(dev[m_nIndex]);
+			if (addStep(STEP_ID_PROT1_TYPE_AUTO_CHANGE_REPLY + m_nIndex, pStep) != 0) {
+				delete pStep;
+			}
+		}
+
+		{
+			char* pszName[6][4] = { 
+				{STEP_EQ_PORT1_EMPTY, STEP_EQ_PORT2_EMPTY, STEP_EQ_PORT3_EMPTY, STEP_EQ_PORT4_EMPTY},
+				{STEP_EQ_PORT1_LOAD_EADY, STEP_EQ_PORT2_LOAD_EADY, STEP_EQ_PORT3_LOAD_EADY, STEP_EQ_PORT4_LOAD_EADY},
+				{STEP_EQ_PORT1_LOADED, STEP_EQ_PORT2_LOADED, STEP_EQ_PORT3_LOADED, STEP_EQ_PORT4_LOADED},
+				{STEP_EQ_PORT1_INUSE, STEP_EQ_PORT2_INUSE, STEP_EQ_PORT3_INUSE, STEP_EQ_PORT4_INUSE},
+				{STEP_EQ_PORT1_UNLOAD_EADY, STEP_EQ_PORT2_UNLOAD_EADY, STEP_EQ_PORT3_UNLOAD_EADY, STEP_EQ_PORT4_UNLOAD_EADY},
+				{STEP_EQ_PORT1_BLOCKED, STEP_EQ_PORT2_BLOCKED, STEP_EQ_PORT3_BLOCKED, STEP_EQ_PORT4_BLOCKED}
+			};
+			static int dev[] = { 0x6050, 0x6070, 0x6090, 0x60b0 };
+			static int writeSignalDev[6][4] = {
+				{0xd8, 0xd9, 0xda, 0xdb},
+				{0xe0, 0xe1, 0xe2, 0xe3},
+				{0xe8, 0xe9, 0xea, 0xeb},
+				{0xf0, 0xf1, 0xf2, 0xf3},
+				{0xf8, 0xf9, 0xfa, 0xfb},
+				{0x100, 0x101, 0x102, 0x103}
+			};
+			static int addr[6][4] = {
+				{ STEP_ID_PORT1_EMPTY, STEP_ID_PORT2_EMPTY, STEP_ID_PORT3_EMPTY, STEP_ID_PORT4_EMPTY },
+				{ STEP_ID_PORT1_LOAD_READY, STEP_ID_PORT2_LOAD_READY, STEP_ID_PORT3_LOAD_READY, STEP_ID_PORT4_LOAD_READY },
+				{ STEP_ID_PORT1_LOADED, STEP_ID_PORT2_LOADED, STEP_ID_PORT3_LOADED, STEP_ID_PORT4_LOADED },
+				{ STEP_ID_PORT1_INUSE, STEP_ID_PORT2_INUSE, STEP_ID_PORT3_INUSE, STEP_ID_PORT4_INUSE },
+				{ STEP_ID_PORT1_UNLOAD_READY, STEP_ID_PORT2_UNLOAD_READY, STEP_ID_PORT3_UNLOAD_READY, STEP_ID_PORT4_UNLOAD_READY },
+				{ STEP_ID_PORT1_BLOCKED, STEP_ID_PORT2_BLOCKED, STEP_ID_PORT3_BLOCKED, STEP_ID_PORT4_BLOCKED },
+			};
+
+			for (int i = 0; i < 6; i++) {
+				CEqReadStep* pStep = new CEqReadStep(dev[m_nIndex], 32 * 2,
+					[&](void* pFrom, int code, const char* pszData, size_t size) -> int {
+						if (code == ROK && pszData != nullptr && size > 0) {
+							decodePortStatusReport((CStep*)pFrom, pszData, size);
+						}
+						return -1;
+					});
+				pStep->setName(pszName[i][m_nIndex]);
+				pStep->setProp("Port", (void*)(__int64)(m_nIndex + 1));
+				pStep->setWriteSignalDev(writeSignalDev[i][m_nIndex]);
+				if (addStep(addr[i][m_nIndex], pStep) != 0) {
+					delete pStep;
+				}
 			}
 		}
 	}
@@ -294,6 +464,41 @@
 	BOOL CLoadPort::isAutoChange()
 	{
 		return m_bAutoChangeEnable;
+	}
+
+	int CLoadPort::getPortStatus()
+	{
+		return m_portStatusReport.getPortStatus();
+	}
+
+	int CLoadPort::getCassetteSequenceNo()
+	{
+		return m_portStatusReport.getCassetteSequenceNo();
+	}
+
+	std::string& CLoadPort::getCassetteId()
+	{
+		return m_portStatusReport.getCassetteId();
+	}
+
+	int CLoadPort::getLoadingCassetteType()
+	{
+		return m_portStatusReport.getLoadingCassetteType();
+	}
+
+	int CLoadPort::getQTimeFlag()
+	{
+		return m_portStatusReport.getQTimeFlag();
+	}
+
+	int CLoadPort::getCassetteMappingState()
+	{
+		return m_portStatusReport.getCassetteMappingState();
+	}
+
+	int CLoadPort::getCassetteStatus()
+	{
+		return m_portStatusReport.getCassetteStatus();
 	}
 
 	/*
@@ -446,6 +651,156 @@
 		return strDescription;
 	}
 
+	/*
+	 1: Load Ready(Load Request)
+	 2: Loaded
+	 3: In Use (Load Complete)
+	 4: Unload Ready (Unload Request)
+	 5: Empty (Unload Complete)
+	 6: Blocked
+ */
+	std::string& CLoadPort::getPortStatusDescription(int portStatus, std::string& strDescription)
+	{
+		switch (portStatus) {
+		case 1:
+			strDescription = _T("Load Ready(Load Request)");
+			break;
+		case 2:
+			strDescription = _T("Loaded");
+			break;
+		case 3:
+			strDescription = _T("In Use(Load Complete)");
+			break;
+		case 4:
+			strDescription = _T("Unload Ready(Unload Request)");
+			break;
+		case 5:
+			strDescription = _T("Empty(Unload Complete)");
+			break;
+		case 6:
+			strDescription = _T("Blocked");
+			break;
+		default:
+			strDescription = _T("");
+			break;
+		}
+
+		return strDescription;
+	}
+
+	/*
+	 1: G1 Cassette
+	 2: G2 Cassette
+	 3: G1 + G2 Cassette
+	 4: Empty Cassette
+	 *  Include this item only when cassette exists"
+	*/
+	std::string& CLoadPort::getLoadingCassetteTypeDescription(int type, std::string& strDescription)
+	{
+		switch (type) {
+		case 1:
+			strDescription = _T("G1 Cassette)");
+			break;
+		case 2:
+			strDescription = _T("G2 Cassette");
+			break;
+		case 3:
+			strDescription = _T("G1+G2 Cassette)");
+			break;
+		case 4:
+			strDescription = _T("Empty Cassette)");
+			break;
+		default:
+			strDescription = _T("");
+			break;
+		}
+
+		return strDescription;
+	}
+
+	/*
+	 1: Normal Un-loading
+	 2: Q-Time Over & Un-loading
+	*/
+	std::string& CLoadPort::getQTimeFlagDescription(int flag, std::string& strDescription)
+	{
+		switch (flag) {
+		case 1:
+			strDescription = _T("Normal Un-loading");
+			break;
+		case 2:
+			strDescription = _T("Q-Time Over & Un-loading");
+			break;
+		default:
+			strDescription = _T("");
+			break;
+		}
+
+		return strDescription;
+	}
+
+	/*
+	 1: mapping use
+	 2: mapping not use
+	*/
+	std::string& CLoadPort::getCassetteMappingStateDescription(int state, std::string& strDescription)
+	{
+		switch (state) {
+		case 1:
+			strDescription = _T("Mapping use");
+			break;
+		case 2:
+			strDescription = _T("Mapping not use");
+			break;
+		default:
+			strDescription = _T("");
+			break;
+		}
+
+		return strDescription;
+	}
+
+	/*
+	 1: No Cassette Exist
+	 2: Waiting for Cassette Data
+	 3: Waiting for Start Command
+	 4: Waiting for Processing
+	 5: In Processing
+	 6: Process Paused
+	 7: Process Completed
+	*/
+	std::string& CLoadPort::getCassetteStatusDescription(int state, std::string& strDescription)
+	{
+		switch (state) {
+		case 1:
+			strDescription = _T("No Cassette Exist");
+			break;
+		case 2:
+			strDescription = _T("Waiting for Cassette Data");
+			break;
+		case 3:
+			strDescription = _T("Waiting for Start Command");
+			break;
+		case 4:
+			strDescription = _T("Waiting for Processing");
+			break;
+		case 5:
+			strDescription = _T("In Processing");
+			break;
+		case 6:
+			strDescription = _T("Process Paused");
+			break;
+		case 7:
+			strDescription = _T("Process Completed");
+			break;
+		default:
+			strDescription = _T("");
+			break;
+		}
+
+		return strDescription;
+	}
+
 	void CLoadPort::onReceiveLBData(const char* pszData, size_t size)
 	{
 		static int type[] = { STEP_ID_PORT1_TYPE_CHANGE, STEP_ID_PORT2_TYPE_CHANGE,
@@ -467,40 +822,221 @@
 		CHECK_READ_STEP_SIGNAL2(transferMode[m_nIndex], pszData, size);
 		CHECK_READ_STEP_SIGNAL2(enable[m_nIndex], pszData, size);
 		CHECK_READ_STEP_SIGNAL2(autoType[m_nIndex], pszData, size);
+
+
+		static int typeReply[] = { STEP_ID_PROT1_TYPE_CHANGE_REPLY, STEP_ID_PROT2_TYPE_CHANGE_REPLY,
+			STEP_ID_PROT3_TYPE_CHANGE_REPLY, STEP_ID_PROT4_TYPE_CHANGE_REPLY };
+		static int modeReply[] = { STEP_ID_PROT1_MODE_CHANGE_REPLY, STEP_ID_PROT2_MODE_CHANGE_REPLY,
+			STEP_ID_PROT3_MODE_CHANGE_REPLY, STEP_ID_PROT4_MODE_CHANGE_REPLY };
+		static int transferModeReply[] = { STEP_ID_PROT1_TRANSFER_MODE_CHANGE_REPLY, STEP_ID_PROT2_TRANSFER_MODE_CHANGE_REPLY,
+			STEP_ID_PROT3_TRANSFER_MODE_CHANGE_REPLY, STEP_ID_PROT4_TRANSFER_MODE_CHANGE_REPLY };
+		static int enableModeReply[] = { STEP_ID_PROT1_ENABLE_MODE_CHANGE_REPLY, STEP_ID_PROT2_ENABLE_MODE_CHANGE_REPLY,
+			STEP_ID_PROT3_ENABLE_MODE_CHANGE_REPLY, STEP_ID_PROT4_ENABLE_MODE_CHANGE_REPLY };
+		static int typeAutoReply[] = { STEP_ID_PROT1_TYPE_AUTO_CHANGE_REPLY, STEP_ID_PROT2_TYPE_AUTO_CHANGE_REPLY,
+			STEP_ID_PROT3_TYPE_AUTO_CHANGE_REPLY, STEP_ID_PROT4_TYPE_AUTO_CHANGE_REPLY };
+		static int cassetteTypeReply[] = { STEP_ID_PROT1_CASSETTE_TYPE_CHANGE_REPLY, STEP_ID_PROT2_CASSETTE_TYPE_CHANGE_REPLY,
+			STEP_ID_PROT3_CASSETTE_TYPE_CHANGE_REPLY, STEP_ID_PROT4_CASSETTE_TYPE_CHANGE_REPLY };
+
+		CHECK_READ_STEP_SIGNAL2(typeReply[m_nIndex], pszData, size);
+		CHECK_READ_STEP_SIGNAL2(modeReply[m_nIndex], pszData, size);
+		CHECK_READ_STEP_SIGNAL2(transferModeReply[m_nIndex], pszData, size);
+		CHECK_READ_STEP_SIGNAL2(enableModeReply[m_nIndex], pszData, size);
+		CHECK_READ_STEP_SIGNAL2(typeAutoReply[m_nIndex], pszData, size);
+		CHECK_READ_STEP_SIGNAL2(cassetteTypeReply[m_nIndex], pszData, size);
 	}
 
-	int CLoadPort::onStepEvent(CStep* pStep, int code)
+	int CLoadPort::decodePortStatusReport(CStep* pStep, const char* pszData, size_t size)
 	{
-		int nRet = CEquipment::onStepEvent(pStep, code);
-		if (nRet > 0) return nRet;
+		CPortStatusReport portStatusReport;
+		int nRet = portStatusReport.unserialize(&pszData[0], (int)size);
+		if (nRet < 0) return nRet;
+		m_portStatusReport.copyEx(portStatusReport);
 
-		if (code == STEP_EVENT_READDATA) {
-			if (isPortTypeStep(pStep)) {
-				SERVO::CEqReadIntStep* pReadIntStep = (SERVO::CEqReadIntStep*)pStep;
-				m_nType = pReadIntStep->getValue();
-			}
-			else if(isPortModeStep(pStep)) {
-				SERVO::CEqReadIntStep* pReadIntStep = (SERVO::CEqReadIntStep*)pStep;
-				m_nMode = pReadIntStep->getValue();
-			}
-			else if (isPortCassetteTypeStep(pStep)) {
-				SERVO::CEqReadIntStep* pReadIntStep = (SERVO::CEqReadIntStep*)pStep;
-				m_nCassetteType = pReadIntStep->getValue();
-			}
-			else if (isPortTransferModeStep(pStep)) {
-				SERVO::CEqReadIntStep* pReadIntStep = (SERVO::CEqReadIntStep*)pStep;
-				m_nTransferMode = pReadIntStep->getValue();
-			}
-			else if (isPortEnableStep(pStep)) {
-				SERVO::CEqReadIntStep* pReadIntStep = (SERVO::CEqReadIntStep*)pStep;
-				m_bEnable = pReadIntStep->getValue() == 1;
-			}
-			else if (isPortTypeAutoChangeEnableStep(pStep)) {
-				SERVO::CEqReadIntStep* pReadIntStep = (SERVO::CEqReadIntStep*)pStep;
-				m_bAutoChangeEnable = pReadIntStep->getValue() == 1;
-			}
+
+		// 缓存Attribute,用于调试时显示信息
+		unsigned int weight = 201;
+		CAttributeVector attrubutes;
+		m_portStatusReport.getAttributeVector(attrubutes, weight);
+		pStep->addAttributeVector(attrubutes);
+
+
+		LOGI("<CCassetteTranserStateStep>decodePortStatusReport<Status:%d, CassetteSequenceNo:%d>",
+			m_portStatusReport.getPortStatus(), m_portStatusReport.getCassetteSequenceNo());
+
+
+		return nRet;
+	}
+
+	int CLoadPort::setPortType(PortType type, ONWRITED onWritedBlock/* = nullptr*/)
+	{
+		static char* pszName[] = { STEP_PORT1_TYPE_CHANGE, STEP_PORT2_TYPE_CHANGE, STEP_PORT3_TYPE_CHANGE, STEP_PORT4_TYPE_CHANGE };
+		SERVO::CEqWriteStep* pStep = (SERVO::CEqWriteStep*)getStepWithName(pszName[m_nIndex]);
+		if (pStep == nullptr) {
+			return -1;
 		}
 
+		LOGI("<CLoadPort-%d>准备设置Port type<%d>", m_nIndex, (int)type);
+		short value = (short)type;
+		if (onWritedBlock != nullptr) {
+			pStep->writeDataEx((const char*)&value, sizeof(short), onWritedBlock);
+		}
+		else {
+			pStep->writeDataEx((const char*)&value, sizeof(short), [&](int code) -> int {
+				if (code == WOK) {
+					LOGI("<CLoadPort-%d>设置Port type成功.", m_nIndex);
+				}
+				else {
+					LOGI("<CLoadPort-%d>设置Port type失败,code:%d", m_nIndex, code);
+				}
+
+				return 0;
+				});
+		}
+
+		return 0;
+	}
+
+	int CLoadPort::eablePort(BOOL bEnable, ONWRITED onWritedBlock/* = nullptr*/)
+	{
+		static char* pszName[] = { STEP_PORT1_ENABLE_MODE_CHANGE, STEP_PORT2_ENABLE_MODE_CHANGE, STEP_PORT3_ENABLE_MODE_CHANGE, STEP_PORT4_ENABLE_MODE_CHANGE };
+		SERVO::CEqWriteStep* pStep = (SERVO::CEqWriteStep*)getStepWithName(pszName[m_nIndex]);
+		if (pStep == nullptr) {
+			return -1;
+		}
+
+		LOGI("<CLoadPort-%d>准备%s Port", m_nIndex, bEnable ? _T("启用") : _T("禁用"));
+		short value = bEnable ? 1 : 2;
+		if (onWritedBlock != nullptr) {
+			pStep->writeDataEx((const char*)&value, sizeof(short), onWritedBlock);
+		}
+		else {
+			pStep->writeDataEx((const char*)&value, sizeof(short), [&](int code) -> int {
+				if (code == WOK) {
+					LOGI("<CLoadPort-%d>%s Port成功.", m_nIndex, bEnable ? _T("启用") : _T("禁用"));
+				}
+				else {
+					LOGI("<CLoadPort-%d>%s  Port失败,code:%d", m_nIndex, bEnable ? _T("启用") : _T("禁用"), code);
+				}
+
+				return 0;
+				});
+		}
+
+		return 0;
+	}
+
+	int CLoadPort::setPortMode(PortMode mode, ONWRITED onWritedBlock/* = nullptr*/)
+	{
+		static char* pszName[] = { STEP_PORT1_MODE_CHANGE, STEP_PORT2_MODE_CHANGE, STEP_PORT3_MODE_CHANGE, STEP_PORT4_MODE_CHANGE };
+		SERVO::CEqWriteStep* pStep = (SERVO::CEqWriteStep*)getStepWithName(pszName[m_nIndex]);
+		if (pStep == nullptr) {
+			return -1;
+		}
+
+		LOGI("<CLoadPort-%d>准备设置Port mode<%d>", m_nIndex, (int)mode);
+		short value = (short)mode;
+		if (onWritedBlock != nullptr) {
+			pStep->writeDataEx((const char*)&value, sizeof(short), onWritedBlock);
+		}
+		else {
+			pStep->writeDataEx((const char*)&value, sizeof(short), [&](int code) -> int {
+				if (code == WOK) {
+					LOGI("<CLoadPort-%d>设置Port mode成功.", m_nIndex);
+				}
+				else {
+					LOGI("<CLoadPort-%d>设置Port mode失败,code:%d", m_nIndex, code);
+				}
+
+				return 0;
+				});
+		}
+
+		return 0;
+	}
+
+	int CLoadPort::setCassetteType(CassetteType type, ONWRITED onWritedBlock/* = nullptr*/)
+	{
+		static char* pszName[] = { STEP_PORT1_CASSETTE_TYPE_CHANGE, STEP_PORT2_CASSETTE_TYPE_CHANGE, STEP_PORT3_CASSETTE_TYPE_CHANGE, STEP_PORT4_CASSETTE_TYPE_CHANGE };
+		SERVO::CEqWriteStep* pStep = (SERVO::CEqWriteStep*)getStepWithName(pszName[m_nIndex]);
+		if (pStep == nullptr) {
+			return -1;
+		}
+
+		LOGI("<CLoadPort-%d>准备设置Cassette Type<%d>", m_nIndex, (int)type);
+		short value = (short)type;
+		if (onWritedBlock != nullptr) {
+			pStep->writeDataEx((const char*)&value, sizeof(short), onWritedBlock);
+		}
+		else {
+			pStep->writeDataEx((const char*)&value, sizeof(short), [&](int code) -> int {
+				if (code == WOK) {
+					LOGI("<CLoadPort-%d>设置Cassette Type成功.", m_nIndex);
+				}
+				else {
+					LOGI("<CLoadPort-%d>设置Cassette Type失败,code:%d", m_nIndex, code);
+				}
+
+				return 0;
+				});
+		}
+
+		return 0;
+	}
+
+	int CLoadPort::setTransferMode(TransferMode mode, ONWRITED onWritedBlock/* = nullptr*/)
+	{
+		static char* pszName[] = { STEP_PORT1_TRANSFER_MODE_CHANGE, STEP_PORT2_TRANSFER_MODE_CHANGE, STEP_PORT3_TRANSFER_MODE_CHANGE, STEP_PORT4_TRANSFER_MODE_CHANGE };
+		SERVO::CEqWriteStep* pStep = (SERVO::CEqWriteStep*)getStepWithName(pszName[m_nIndex]);
+		if (pStep == nullptr) {
+			return -1;
+		}
+
+		LOGI("<CLoadPort-%d>准备设置Transfer mode<%d>", m_nIndex, (int)mode);
+		short value = (short)mode;
+		if (onWritedBlock != nullptr) {
+			pStep->writeDataEx((const char*)&value, sizeof(short), onWritedBlock);
+		}
+		else {
+			pStep->writeDataEx((const char*)&value, sizeof(short), [&](int code) -> int {
+				if (code == WOK) {
+					LOGI("<CLoadPort-%d>设置Transfer mode成功.", m_nIndex + 1);
+				}
+				else {
+					LOGI("<CLoadPort-%d>设置Transfer mode失败,code:%d", m_nIndex + 1, code);
+				}
+
+				return 0;
+				});
+		}
+
+		return 0;
+	}
+
+	int CLoadPort::eableAutoChange(BOOL bEnable, ONWRITED onWritedBlock/* = nullptr*/)
+	{
+		static char* pszName[] = { STEP_PORT1_TYPE_AUTO_CHANGE, STEP_PORT2_TYPE_AUTO_CHANGE, STEP_PORT3_TYPE_AUTO_CHANGE, STEP_PORT4_TYPE_AUTO_CHANGE };
+		SERVO::CEqWriteStep* pStep = (SERVO::CEqWriteStep*)getStepWithName(pszName[m_nIndex]);
+		if (pStep == nullptr) {
+			return -1;
+		}
+
+		LOGI("<CLoadPort-%d>准备%s Auto Change", m_nIndex, bEnable ? _T("启用") : _T("禁用"));
+		short value = bEnable ? 1 : 2;
+		if (onWritedBlock != nullptr) {
+			pStep->writeDataEx((const char*)&value, sizeof(short), onWritedBlock);
+		}
+		else {
+			pStep->writeDataEx((const char*)&value, sizeof(short), [&](int code) -> int {
+				if (code == WOK) {
+					LOGI("<CLoadPort-%d>%s Auto Change成功.", m_nIndex, bEnable ? _T("启用") : _T("禁用"));
+				}
+				else {
+					LOGI("<CLoadPort-%d>%s  Auto Change失败,code:%d", m_nIndex, bEnable ? _T("启用") : _T("禁用"), code);
+				}
+
+				return 0;
+				});
+		}
 
 		return 0;
 	}
diff --git a/SourceCode/Bond/Servo/CLoadPort.h b/SourceCode/Bond/Servo/CLoadPort.h
index 0b28400..3e011fc 100644
--- a/SourceCode/Bond/Servo/CLoadPort.h
+++ b/SourceCode/Bond/Servo/CLoadPort.h
@@ -1,5 +1,6 @@
 #pragma once
 #include "CEquipment.h"
+#include "ServoCommo.h"
 
 
 namespace SERVO {
@@ -22,7 +23,14 @@
 		virtual int recvIntent(CPin* pPin, CIntent* pIntent);
 		virtual BOOL glassWillArrive(CGlass* pGlass);
 		virtual void onReceiveLBData(const char* pszData, size_t size);
-		virtual int onStepEvent(CStep* pStep, int code);
+
+	public:
+		int setPortType(PortType type, ONWRITED onWritedBlock = nullptr);
+		int eablePort(BOOL bEnable, ONWRITED onWritedBlock = nullptr);
+		int setPortMode(PortMode mode, ONWRITED onWritedBlock = nullptr);
+		int setCassetteType(CassetteType type, ONWRITED onWritedBlock = nullptr);
+		int setTransferMode(TransferMode mode, ONWRITED onWritedBlock = nullptr);
+		int eableAutoChange(BOOL bEnable, ONWRITED onWritedBlock = nullptr);
 
 	public:
 		void setIndex(unsigned int index);
@@ -33,6 +41,13 @@
 		int getCessetteType();
 		int getTransferMode();
 		BOOL isAutoChange();
+		int getPortStatus();
+		int getCassetteSequenceNo();
+		std::string& getCassetteId();
+		int getLoadingCassetteType();
+		int getQTimeFlag();
+		int getCassetteMappingState();
+		int getCassetteStatus();
 		int testGenerateGlassList(MaterialsType type, int count, const char* pszPrefix, int startSuffix);
 
 	public:
@@ -41,6 +56,11 @@
 		static std::string& getPortCassetteTypeDescription(int casseteType, std::string& strDescription);
 		static std::string& getPortTransferModeDescription(int mode, std::string& strDescription);
 		static std::string& getEnableModeDescription(int mode, std::string& strDescription);
+		static std::string& getPortStatusDescription(int portStatus, std::string& strDescription);
+		static std::string& getLoadingCassetteTypeDescription(int type, std::string& strDescription);
+		static std::string& getQTimeFlagDescription(int flag, std::string& strDescription);
+		static std::string& getCassetteMappingStateDescription(int state, std::string& strDescription);
+		static std::string& getCassetteStatusDescription(int state, std::string& strDescription);
 
 	public:
 		virtual int outputGlass(int port);
@@ -53,6 +73,9 @@
 		CStep* getCassetteCtrlCmdStep();
 
 	private:
+		int decodePortStatusReport(CStep* pStep, const char* pszData, size_t size);
+
+	private:
 		unsigned int m_nIndex;
 		int m_nType;
 		int m_nMode;
@@ -60,6 +83,7 @@
 		int m_nTransferMode;
 		BOOL m_bEnable;
 		BOOL m_bAutoChangeEnable;
+		CPortStatusReport m_portStatusReport;
 	};
 }
 
diff --git a/SourceCode/Bond/Servo/CMaster.cpp b/SourceCode/Bond/Servo/CMaster.cpp
index 29ba607..e148025 100644
--- a/SourceCode/Bond/Servo/CMaster.cpp
+++ b/SourceCode/Bond/Servo/CMaster.cpp
@@ -95,6 +95,7 @@
 		CVacuumBake* pVacuumBake;
 		CAligner* pAligner;
 		CBakeCooling* pBakeCooling;
+		CMeasurement* pMeasurement;
 
 		pPort1 = addLoadPort(0);
 		pPort2 = addLoadPort(1);
@@ -110,6 +111,7 @@
 		pBonder1 = addBonder(0);
 		pBonder2 = addBonder(1);
 		pBakeCooling = addBakeCooling();
+		pMeasurement = addMeasurement();
 
 		ASSERT(pEfem);
 		ASSERT(pFliper);
@@ -118,6 +120,7 @@
 		ASSERT(pBonder1);
 		ASSERT(pBonder2);
 		ASSERT(pBakeCooling);
+		ASSERT(pMeasurement);
 
 		pEfem->setPort(0, pPort1);
 		pEfem->setPort(1, pPort1);
@@ -139,6 +142,7 @@
 		pBonder1->setArm(pArm);
 		pBonder2->setArm(pArm);
 		pBakeCooling->setArm(pArm);
+		pMeasurement->setArm(pArm);
 
 		connectEquipments();
 
@@ -444,6 +448,23 @@
 		return pEquipment;
 	}
 
+	CMeasurement* CMaster::addMeasurement()
+	{
+		CMeasurement* pEquipment = new CMeasurement();
+		pEquipment->setID(EQ_ID_MEASUREMENT);
+		pEquipment->setBaseAlarmId(BASE_ALARM_EFEM);
+		pEquipment->setName("Measurement");
+		pEquipment->setDescription("Measurement.");
+		pEquipment->setReadBitBlock(0x6700, 0x6e00);
+		pEquipment->setStation(0, 255);
+		addToEquipmentList(pEquipment);
+
+		pEquipment->init();
+		LOGE("已添加“Measurement”.");
+
+		return pEquipment;
+	}
+
 	void CMaster::onTimer(UINT nTimerid)
 	{
 		for (auto item : m_listEquipment) {
@@ -496,6 +517,7 @@
 		CBonder* pBonder1 = (CBonder*)getEquipment(EQ_ID_Bonder1);
 		CBonder* pBonder2 = (CBonder*)getEquipment(EQ_ID_Bonder2);
 		CBakeCooling* pBakeCooling = (CBakeCooling*)getEquipment(EQ_ID_BAKE_COOLING);
+		CMeasurement* pMeasurement = (CMeasurement*)getEquipment(EQ_ID_MEASUREMENT);
 
 		nRet = pLoadPort1->getPin("Out1")->connectPin(pFliper->getPin("In1"));
 		if (nRet < 0) {
@@ -545,12 +567,17 @@
 			LOGE("连接Bonder2-BakeCooling失败");
 		}
 
-		nRet = pBakeCooling->getPin("Out1")->connectPin(pLoadPort3->getPin("In"));
+		nRet = pBakeCooling->getPin("Out")->connectPin(pMeasurement->getPin("In"));
 		if (nRet < 0) {
 			LOGE("连接BakeCooling-LoadPort3失败");
 		}
 
-		nRet = pBakeCooling->getPin("Out2")->connectPin(pLoadPort4->getPin("In"));
+		nRet = pMeasurement->getPin("Out1")->connectPin(pLoadPort3->getPin("In"));
+		if (nRet < 0) {
+			LOGE("连接BakeCooling-LoadPort3失败");
+		}
+
+		nRet = pMeasurement->getPin("Out2")->connectPin(pLoadPort4->getPin("In"));
 		if (nRet < 0) {
 			LOGE("连接BakeCooling-LoadPort4失败");
 		}
diff --git a/SourceCode/Bond/Servo/CMaster.h b/SourceCode/Bond/Servo/CMaster.h
index 31ea5da..fbd76cf 100644
--- a/SourceCode/Bond/Servo/CMaster.h
+++ b/SourceCode/Bond/Servo/CMaster.h
@@ -8,6 +8,7 @@
 #include "CAligner.h"
 #include "CVacuumBake.h"
 #include "CBakeCooling.h"
+#include "CMeasurement.h"
 #include "CArm.h"
 #include "CArmTray.h"
 #include "CCLinkIEControl.h"
@@ -56,6 +57,7 @@
         CArmTray* addArmTray(int index);
         CBonder* addBonder(int index);
         CBakeCooling* addBakeCooling();
+        CMeasurement* addMeasurement();
         void connectEquipments();
         int saveCache();
         int saveCacheAndBackups();
diff --git a/SourceCode/Bond/Servo/CMeasurement.cpp b/SourceCode/Bond/Servo/CMeasurement.cpp
index 34ff4e6..f659453 100644
--- a/SourceCode/Bond/Servo/CMeasurement.cpp
+++ b/SourceCode/Bond/Servo/CMeasurement.cpp
@@ -33,6 +33,9 @@
 	{
 		// 加入Pin初始化代码
 		LOGI("<CMeasurement>initPins");
+		addPin(SERVO::PinType::INPUT, _T("In"));
+		addPin(SERVO::PinType::OUTPUT, _T("Out1"));
+		addPin(SERVO::PinType::OUTPUT, _T("Out2"));
 	}
 
 	void CMeasurement::onTimer(UINT nTimerid)
@@ -64,4 +67,9 @@
 
 		return m_glassList.empty();
 	}
+
+	int CMeasurement::getIndexerOperationModeBaseValue()
+	{
+		return 35000;
+	}
 }
diff --git a/SourceCode/Bond/Servo/CMeasurement.h b/SourceCode/Bond/Servo/CMeasurement.h
index 28812a1..b6d87bb 100644
--- a/SourceCode/Bond/Servo/CMeasurement.h
+++ b/SourceCode/Bond/Servo/CMeasurement.h
@@ -20,6 +20,8 @@
         virtual void getAttributeVector(CAttributeVector& attrubutes);
         virtual int recvIntent(CPin* pPin, CIntent* pIntent);
         virtual BOOL glassWillArrive(CGlass* pGlass);
+        virtual int getIndexerOperationModeBaseValue();
+
 	};
 }
 
diff --git a/SourceCode/Bond/Servo/CPageGraph2.cpp b/SourceCode/Bond/Servo/CPageGraph2.cpp
index 3e161a7..7e4811e 100644
--- a/SourceCode/Bond/Servo/CPageGraph2.cpp
+++ b/SourceCode/Bond/Servo/CPageGraph2.cpp
@@ -10,6 +10,7 @@
 #include "CEquipmentPage2.h"
 #include "CEquipmentPage3.h"
 #include "CPagePortProperty.h"
+#include "CPagePortStatus.h"
 #include "CPageCassetteCtrlCmd.h"
 #include "CJobDataB.h"
 #include "CRobotCmdContainerDlg.h"
@@ -127,13 +128,18 @@
 		ASSERT(pItem);
 		SERVO::CEquipment* pEquipment = (SERVO::CEquipment*)pItem->pData;
 
-		CHMPropertyDlg dlg(pEquipment->getName().c_str(), 600, 680);
+		CHMPropertyDlg dlg(pEquipment->getName().c_str(), 658, 788);
 
 		if (_strcmpi(pEquipment->getClassName(), "CLoadPort") == 0) {
-			CPagePortProperty* pPage1 = new CPagePortProperty();
-			pPage1->setLoadPort((SERVO::CLoadPort*)pEquipment);
-			pPage1->Create(IDD_PAGE_PORT_PROPERTY);
-			dlg.addPage(pPage1, "灞炴��");
+			CPagePortProperty* pPageA = new CPagePortProperty();
+			pPageA->setLoadPort((SERVO::CLoadPort*)pEquipment);
+			pPageA->Create(IDD_PAGE_PORT_PROPERTY);
+			dlg.addPage(pPageA, "灞炴��");
+
+			CPagePortStatus* pPageB = new CPagePortStatus();
+			pPageB->setLoadPort((SERVO::CLoadPort*)pEquipment);
+			pPageB->Create(IDD_PAGE_PORT_STATUS);
+			dlg.addPage(pPageB, "Status");
 		}
 
 		CEquipmentPage2* pPage2 = new CEquipmentPage2();
diff --git a/SourceCode/Bond/Servo/CPagePortProperty.cpp b/SourceCode/Bond/Servo/CPagePortProperty.cpp
index 88728b5..b163d01 100644
--- a/SourceCode/Bond/Servo/CPagePortProperty.cpp
+++ b/SourceCode/Bond/Servo/CPagePortProperty.cpp
@@ -5,6 +5,8 @@
 #include "Servo.h"
 #include "CPagePortProperty.h"
 #include "afxdialogex.h"
+#include "Log.h"
+#include "MsgDlg.h"
 
 
 // CPagePortProperty 瀵硅瘽妗�
@@ -32,6 +34,11 @@
 	ON_WM_DESTROY()
 	ON_WM_SIZE()
 	ON_BN_CLICKED(IDC_CHECK_ENABLE, &CPagePortProperty::OnBnClickedCheckEnable)
+	ON_CBN_SELCHANGE(IDC_COMBO_PORT_TYPE, &CPagePortProperty::OnCbnSelchangeComboPortType)
+	ON_CBN_SELCHANGE(IDC_COMBO_PORT_MODE, &CPagePortProperty::OnCbnSelchangeComboPortMode)
+	ON_CBN_SELCHANGE(IDC_COMBO_PORT_CASSERT_TYPE, &CPagePortProperty::OnCbnSelchangeComboPortCassertType)
+	ON_CBN_SELCHANGE(IDC_COMBO_PORT_TRANSFER_MODE, &CPagePortProperty::OnCbnSelchangeComboPortTransferMode)
+	ON_BN_CLICKED(IDC_CHECK_AUTO_CHANGE, &CPagePortProperty::OnBnClickedCheckAutoChange)
 END_MESSAGE_MAP()
 
 
@@ -61,12 +68,12 @@
 	}
 
 	pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_PORT_MODE);
-	for (int i = 1; i <= 3; i++) {
+	for (int i = 0; i <= 5; i++) {
 		pComboBox->InsertString(i - 1, SERVO::CLoadPort::getPortModeDescription(i, strTemp).c_str());
 	}
 	int portMode = m_pPort->getPortMode();
-	if (1 <= portMode && portMode <= 3) {
-		pComboBox->SetCurSel(portMode - 1);
+	if (0 <= portMode && portMode <= 5) {
+		pComboBox->SetCurSel(portMode);
 	}
 
 	pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_PORT_CASSERT_TYPE);
@@ -127,6 +134,266 @@
 {
 	BOOL bCheck = ((CButton*)GetDlgItem(IDC_CHECK_ENABLE))->GetCheck() == BST_CHECKED;
 	EnableCtrls(bCheck);
+
+
+	// enable port
+	CMsgDlg msgDlg("璇风瓑寰�", "姝e湪鎿嶄綔锛岃绛夊緟...");
+
+	ASSERT(m_pPort != nullptr);
+	m_pPort->eablePort(bCheck, [&](int code) -> int {
+		Sleep(100);
+		CString strMsg;
+
+		if (code == WOK) {
+			LOGI("%s Port 鎴愬姛.", bCheck ? _T("enable") : _T("disable"));
+
+			msgDlg.DelayClose(3000);
+			strMsg.Format(_T("%s Port 鎴愬姛."), bCheck ? _T("enable") : _T("disable"));
+			msgDlg.DelayClose(3000);
+			msgDlg.SetIcon(MSG_BOX_SUCCEED);
+			msgDlg.SetTitle(_T("鎿嶄綔鎴愬姛"));
+			msgDlg.SetMessage((LPTSTR)(LPCTSTR)strMsg);
+			msgDlg.SetMarquee(FALSE, 0);
+			msgDlg.SetCompleteCode(0);
+		}
+		else {
+			LOGI("%s Port 澶辫触锛宑ode:%d", bCheck ? _T("enable") : _T("disable"), code);
+
+			msgDlg.DelayClose(3000);
+			strMsg.Format(_T("%s Port 澶辫触锛宑ode:%d"), bCheck ? _T("enable") : _T("disable"), code);
+			msgDlg.DelayClose(3000);
+			msgDlg.SetIcon(MSG_BOX_ERROR);
+			msgDlg.SetTitle(_T("鎿嶄綔澶辫触"));
+			msgDlg.SetMessage((LPTSTR)(LPCTSTR)strMsg);
+			msgDlg.SetMarquee(FALSE, 0);
+			msgDlg.SetCompleteCode(-1);
+			
+			// 杩樺師鎺т欢鐘舵��
+			EnableCtrls(!bCheck);
+			((CButton*)GetDlgItem(IDC_CHECK_ENABLE))->SetCheck(!bCheck ? BST_CHECKED : BST_UNCHECKED);
+		}
+
+		return 0;
+		});
+
+	msgDlg.DoModal();
+}
+
+void CPagePortProperty::OnCbnSelchangeComboPortType()
+{
+	CMsgDlg msgDlg("璇风瓑寰�", "姝e湪鎿嶄綔锛岃绛夊緟...");
+	msgDlg.SetData((DWORD_PTR)this);
+
+	ASSERT(m_pPort != nullptr);
+	int index = ((CComboBox*)GetDlgItem(IDC_COMBO_PORT_TYPE))->GetCurSel();
+	m_pPort->setPortType(SERVO::PortType(index + 1), [&](int code) -> int {
+		Sleep(100);
+		CString strMsg;
+
+		if (code == WOK) {
+			LOGI("璁剧疆Port Type(%d)鎴愬姛.", index + 1);
+
+			msgDlg.DelayClose(3000);
+			strMsg.Format(_T("璁剧疆Port Type(%d)鎴愬姛"), index + 1);
+			msgDlg.DelayClose(3000);
+			msgDlg.SetIcon(MSG_BOX_SUCCEED);
+			msgDlg.SetTitle(_T("鎿嶄綔鎴愬姛"));
+			msgDlg.SetMessage((LPTSTR)(LPCTSTR)strMsg);
+			msgDlg.SetMarquee(FALSE, 0);
+			msgDlg.SetCompleteCode(0);
+		}
+		else {
+			LOGI("璁剧疆Port Type(%d)澶辫触锛宑ode:%d", index + 1, code);
+
+			msgDlg.DelayClose(3000);
+			strMsg.Format(_T("璁剧疆Port Type(%d)澶辫触锛宑ode:%d"), index + 1, code);
+			msgDlg.DelayClose(3000);
+			msgDlg.SetIcon(MSG_BOX_ERROR);
+			msgDlg.SetTitle(_T("鎿嶄綔澶辫触"));
+			msgDlg.SetMessage((LPTSTR)(LPCTSTR)strMsg);
+			msgDlg.SetMarquee(FALSE, 0);
+			msgDlg.SetCompleteCode(-1);
+		}
+
+		return 0;
+	});
+
+	msgDlg.DoModal();
+}
+
+void CPagePortProperty::OnCbnSelchangeComboPortMode()
+{
+	CMsgDlg msgDlg("璇风瓑寰�", "姝e湪鎿嶄綔锛岃绛夊緟...");
+	msgDlg.SetData((DWORD_PTR)this);
+
+	ASSERT(m_pPort != nullptr);
+	int index = ((CComboBox*)GetDlgItem(IDC_COMBO_PORT_MODE))->GetCurSel();
+	m_pPort->setPortMode(SERVO::PortMode(index), [&](int code) -> int {
+		Sleep(100);
+		CString strMsg;
+
+		if (code == WOK) {
+			LOGI("璁剧疆Port Mode(%d)鎴愬姛.", index);
+
+			msgDlg.DelayClose(3000);
+			strMsg.Format(_T("璁剧疆Port Mode(%d)鎴愬姛"), index);
+			msgDlg.DelayClose(3000);
+			msgDlg.SetIcon(MSG_BOX_SUCCEED);
+			msgDlg.SetTitle(_T("鎿嶄綔鎴愬姛"));
+			msgDlg.SetMessage((LPTSTR)(LPCTSTR)strMsg);
+			msgDlg.SetMarquee(FALSE, 0);
+			msgDlg.SetCompleteCode(0);
+		}
+		else {
+			LOGI("璁剧疆Port Mode(%d)澶辫触锛宑ode:%d", index, code);
+
+			msgDlg.DelayClose(3000);
+			strMsg.Format(_T("璁剧疆Port Mode(%d)澶辫触锛宑ode:%d"), index, code);
+			msgDlg.DelayClose(3000);
+			msgDlg.SetIcon(MSG_BOX_ERROR);
+			msgDlg.SetTitle(_T("鎿嶄綔澶辫触"));
+			msgDlg.SetMessage((LPTSTR)(LPCTSTR)strMsg);
+			msgDlg.SetMarquee(FALSE, 0);
+			msgDlg.SetCompleteCode(-1);
+		}
+
+		return 0;
+		});
+
+	msgDlg.DoModal();
+}
+
+void CPagePortProperty::OnCbnSelchangeComboPortCassertType()
+{
+	CMsgDlg msgDlg("璇风瓑寰�", "姝e湪鎿嶄綔锛岃绛夊緟...");
+	msgDlg.SetData((DWORD_PTR)this);
+
+	ASSERT(m_pPort != nullptr);
+	int index = ((CComboBox*)GetDlgItem(IDC_COMBO_PORT_CASSERT_TYPE))->GetCurSel();
+	m_pPort->setPortMode(SERVO::PortMode(index + 1), [&](int code) -> int {
+		Sleep(100);
+		CString strMsg;
+
+		if (code == WOK) {
+			LOGI("璁剧疆Cassette type(%d)鎴愬姛.", index + 1);
+
+			msgDlg.DelayClose(3000);
+			strMsg.Format(_T("璁剧疆Cassette type(%d)鎴愬姛"), index + 1);
+			msgDlg.DelayClose(3000);
+			msgDlg.SetIcon(MSG_BOX_SUCCEED);
+			msgDlg.SetTitle(_T("鎿嶄綔鎴愬姛"));
+			msgDlg.SetMessage((LPTSTR)(LPCTSTR)strMsg);
+			msgDlg.SetMarquee(FALSE, 0);
+			msgDlg.SetCompleteCode(0);
+		}
+		else {
+			LOGI("璁剧疆Cassette type(%d)澶辫触锛宑ode:%d", index + 1, code);
+
+			msgDlg.DelayClose(3000);
+			strMsg.Format(_T("璁剧疆Cassette type(%d)澶辫触锛宑ode:%d"), index + 1, code);
+			msgDlg.DelayClose(3000);
+			msgDlg.SetIcon(MSG_BOX_ERROR);
+			msgDlg.SetTitle(_T("鎿嶄綔澶辫触"));
+			msgDlg.SetMessage((LPTSTR)(LPCTSTR)strMsg);
+			msgDlg.SetMarquee(FALSE, 0);
+			msgDlg.SetCompleteCode(-1);
+		}
+
+		return 0;
+		});
+
+	msgDlg.DoModal();
+}
+
+void CPagePortProperty::OnCbnSelchangeComboPortTransferMode()
+{
+	// TODO: 鍦ㄦ娣诲姞鎺т欢閫氱煡澶勭悊绋嬪簭浠g爜
+	CMsgDlg msgDlg("璇风瓑寰�", "姝e湪鎿嶄綔锛岃绛夊緟...");
+	msgDlg.SetData((DWORD_PTR)this);
+
+	ASSERT(m_pPort != nullptr);
+	int index = ((CComboBox*)GetDlgItem(IDC_COMBO_PORT_TRANSFER_MODE))->GetCurSel();
+	m_pPort->setPortMode(SERVO::PortMode(index + 1), [&](int code) -> int {
+		Sleep(100);
+		CString strMsg;
+
+		if (code == WOK) {
+			LOGI("璁剧疆Transfer mode(%d)鎴愬姛.", index + 1);
+
+			msgDlg.DelayClose(3000);
+			strMsg.Format(_T("璁剧疆Transfer mode(%d)鎴愬姛"), index + 1);
+			msgDlg.DelayClose(3000);
+			msgDlg.SetIcon(MSG_BOX_SUCCEED);
+			msgDlg.SetTitle(_T("鎿嶄綔鎴愬姛"));
+			msgDlg.SetMessage((LPTSTR)(LPCTSTR)strMsg);
+			msgDlg.SetMarquee(FALSE, 0);
+			msgDlg.SetCompleteCode(0);
+		}
+		else {
+			LOGI("璁剧疆Transfer mode(%d)澶辫触锛宑ode:%d", index + 1, code);
+
+			msgDlg.DelayClose(3000);
+			strMsg.Format(_T("璁剧疆Transfer mode(%d)澶辫触锛宑ode:%d"), index + 1, code);
+			msgDlg.DelayClose(3000);
+			msgDlg.SetIcon(MSG_BOX_ERROR);
+			msgDlg.SetTitle(_T("鎿嶄綔澶辫触"));
+			msgDlg.SetMessage((LPTSTR)(LPCTSTR)strMsg);
+			msgDlg.SetMarquee(FALSE, 0);
+			msgDlg.SetCompleteCode(-1);
+		}
+
+		return 0;
+		});
+
+	msgDlg.DoModal();
+}
+
+void CPagePortProperty::OnBnClickedCheckAutoChange()
+{
+	BOOL bCheck = ((CButton*)GetDlgItem(IDC_CHECK_AUTO_CHANGE))->GetCheck() == BST_CHECKED;
+	EnableCtrls(bCheck);
+
+
+	// enable port
+	CMsgDlg msgDlg("璇风瓑寰�", "姝e湪鎿嶄綔锛岃绛夊緟...");
+
+	ASSERT(m_pPort != nullptr);
+	m_pPort->eableAutoChange(bCheck, [&](int code) -> int {
+		Sleep(100);
+		CString strMsg;
+
+		if (code == WOK) {
+			LOGI("%s Auto Change 鎴愬姛.", bCheck ? _T("enable") : _T("disable"));
+
+			msgDlg.DelayClose(3000);
+			strMsg.Format(_T("%s Auto Change 鎴愬姛."), bCheck ? _T("enable") : _T("disable"));
+			msgDlg.DelayClose(3000);
+			msgDlg.SetIcon(MSG_BOX_SUCCEED);
+			msgDlg.SetTitle(_T("鎿嶄綔鎴愬姛"));
+			msgDlg.SetMessage((LPTSTR)(LPCTSTR)strMsg);
+			msgDlg.SetMarquee(FALSE, 0);
+			msgDlg.SetCompleteCode(0);
+		}
+		else {
+			LOGI("%s Auto Change 澶辫触锛宑ode:%d", bCheck ? _T("enable") : _T("disable"), code);
+
+			msgDlg.DelayClose(3000);
+			strMsg.Format(_T("%s Auto Change 澶辫触锛宑ode:%d"), bCheck ? _T("enable") : _T("disable"), code);
+			msgDlg.DelayClose(3000);
+			msgDlg.SetIcon(MSG_BOX_ERROR);
+			msgDlg.SetTitle(_T("鎿嶄綔澶辫触"));
+			msgDlg.SetMessage((LPTSTR)(LPCTSTR)strMsg);
+			msgDlg.SetMarquee(FALSE, 0);
+			msgDlg.SetCompleteCode(-1);
+
+			// 杩樺師鎺т欢鐘舵��
+			((CButton*)GetDlgItem(IDC_CHECK_AUTO_CHANGE))->SetCheck(!bCheck ? BST_CHECKED : BST_UNCHECKED);
+		}
+
+		return 0;
+		});
+
+	msgDlg.DoModal();
 }
 
 void CPagePortProperty::EnableCtrls(BOOL bEnable)
@@ -137,3 +404,4 @@
 	GetDlgItem(IDC_COMBO_PORT_TRANSFER_MODE)->EnableWindow(bEnable);
 	GetDlgItem(IDC_CHECK_AUTO_CHANGE)->EnableWindow(bEnable);
 }
+
diff --git a/SourceCode/Bond/Servo/CPagePortProperty.h b/SourceCode/Bond/Servo/CPagePortProperty.h
index f7e159c..7be09fb 100644
--- a/SourceCode/Bond/Servo/CPagePortProperty.h
+++ b/SourceCode/Bond/Servo/CPagePortProperty.h
@@ -37,4 +37,9 @@
 	afx_msg void OnDestroy();
 	afx_msg void OnSize(UINT nType, int cx, int cy);
 	afx_msg void OnBnClickedCheckEnable();
+	afx_msg void OnCbnSelchangeComboPortType();
+	afx_msg void OnCbnSelchangeComboPortMode();
+	afx_msg void OnCbnSelchangeComboPortCassertType();
+	afx_msg void OnCbnSelchangeComboPortTransferMode();
+	afx_msg void OnBnClickedCheckAutoChange();
 };
diff --git a/SourceCode/Bond/Servo/CPagePortStatus.cpp b/SourceCode/Bond/Servo/CPagePortStatus.cpp
new file mode 100644
index 0000000..ff38c73
--- /dev/null
+++ b/SourceCode/Bond/Servo/CPagePortStatus.cpp
@@ -0,0 +1,148 @@
+锘�// CPagePortStatus.cpp: 瀹炵幇鏂囦欢
+//
+
+#include "stdafx.h"
+#include "Servo.h"
+#include "CPagePortStatus.h"
+#include "afxdialogex.h"
+
+
+// CPagePortStatus 瀵硅瘽妗�
+
+IMPLEMENT_DYNAMIC(CPagePortStatus, CHMPropertyPage)
+
+CPagePortStatus::CPagePortStatus(CWnd* pParent /*=nullptr*/)
+	: CHMPropertyPage(IDD_PAGE_PORT_STATUS, pParent)
+{
+	m_pPort = nullptr;
+}
+
+CPagePortStatus::~CPagePortStatus()
+{
+}
+
+void CPagePortStatus::DoDataExchange(CDataExchange* pDX)
+{
+	CHMPropertyPage::DoDataExchange(pDX);
+}
+
+
+BEGIN_MESSAGE_MAP(CPagePortStatus, CHMPropertyPage)
+	ON_WM_CTLCOLOR()
+	ON_WM_DESTROY()
+	ON_WM_SIZE()
+END_MESSAGE_MAP()
+
+
+// CPagePortStatus 娑堟伅澶勭悊绋嬪簭
+void CPagePortStatus::setLoadPort(SERVO::CLoadPort* pPort)
+{
+	m_pPort = pPort;
+}
+
+BOOL CPagePortStatus::OnInitDialog()
+{
+	CHMPropertyPage::OnInitDialog();
+
+
+	ASSERT(m_pPort);
+	CComboBox* pComboBox;
+	std::string strTemp;
+
+	pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_PORT_STATUS);
+	for (int i = 1; i <= 6; i++) {
+		pComboBox->InsertString(i - 1, SERVO::CLoadPort::getPortStatusDescription(i, strTemp).c_str());
+	}
+	int portStatus = m_pPort->getPortStatus();
+	if (1 <= portStatus && portStatus <= 6) {
+		pComboBox->SetCurSel(portStatus - 1);
+	}
+
+	SetDlgItemInt(IDC_EDIT_CASSETTE_NO, m_pPort->getCassetteSequenceNo());
+	SetDlgItemText(IDC_EDIT_CASSETTE_ID, m_pPort->getCassetteId().c_str());
+
+	pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_LOADING_CASSETTE_TYPE);
+	for (int i = 1; i <= 4; i++) {
+		pComboBox->InsertString(i - 1, SERVO::CLoadPort::getLoadingCassetteTypeDescription(i, strTemp).c_str());
+	}
+	int loadingCassetteType = m_pPort->getLoadingCassetteType();
+	if (1 <= loadingCassetteType && loadingCassetteType <= 4) {
+		pComboBox->SetCurSel(loadingCassetteType - 1);
+	}
+
+	pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_QTIME_FLAG);
+	for (int i = 1; i <= 2; i++) {
+		pComboBox->InsertString(i - 1, SERVO::CLoadPort::getQTimeFlagDescription(i, strTemp).c_str());
+	}
+	int qTimeFlag = m_pPort->getQTimeFlag();
+	if (1 <= qTimeFlag && qTimeFlag <= 2) {
+		pComboBox->SetCurSel(qTimeFlag - 1);
+	}
+	
+	pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_CASSETTE_MAPPING_STATE);
+	for (int i = 1; i <= 2; i++) {
+		pComboBox->InsertString(i - 1, SERVO::CLoadPort::getCassetteMappingStateDescription(i, strTemp).c_str());
+	}
+	int mappingState = m_pPort->getCassetteMappingState();
+	if (1 <= mappingState && mappingState <= 2) {
+		pComboBox->SetCurSel(mappingState - 1);
+	}
+	
+	pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_CASSETTE_STATUS);
+	for (int i = 1; i <= 7; i++) {
+		pComboBox->InsertString(i - 1, SERVO::CLoadPort::getCassetteStatusDescription(i, strTemp).c_str());
+	}
+	int cassetteStatus = m_pPort->getCassetteStatus();
+	if (1 <= cassetteStatus && cassetteStatus <= 7) {
+		pComboBox->SetCurSel(cassetteStatus - 1);
+	}
+
+	// 鍒涘缓Job Existence Slots鎺т欢
+	m_ctrlJobSlotGrid.Create(AfxRegisterWndClass(0), _T("JobSlotGrid"),
+		WS_CHILD | WS_VISIBLE, CRect(0, 0, 100, 100), this, 1001);
+	m_ctrlJobSlotGrid.SetGridSize(12, 16);
+	m_ctrlJobSlotGrid.SetColors(RGB(34, 177, 76), RGB(200, 200, 200));
+
+	m_ctrlJobSlotGrid.SetSlotStatus(0, 1, true);
+	m_ctrlJobSlotGrid.SetSlotStatus(1, 9, true);
+	m_ctrlJobSlotGrid.SetSlotStatus(4, 9, false);
+	m_ctrlJobSlotGrid.SetSlotStatus(4, 10, true, TRUE);
+
+	return TRUE;  // return TRUE unless you set the focus to a control
+				  // 寮傚父: OCX 灞炴�ч〉搴旇繑鍥� FALSE
+}
+
+HBRUSH CPagePortStatus::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
+{
+	HBRUSH hbr = CHMPropertyPage::OnCtlColor(pDC, pWnd, nCtlColor);
+
+	// TODO:  鍦ㄦ鏇存敼 DC 鐨勪换浣曠壒鎬�
+
+	// TODO:  濡傛灉榛樿鐨勪笉鏄墍闇�鐢荤瑪锛屽垯杩斿洖鍙︿竴涓敾绗�
+	return hbr;
+}
+
+void CPagePortStatus::OnDestroy()
+{
+	CHMPropertyPage::OnDestroy();
+
+	// TODO: 鍦ㄦ澶勬坊鍔犳秷鎭鐞嗙▼搴忎唬鐮�
+}
+
+void CPagePortStatus::OnSize(UINT nType, int cx, int cy)
+{
+	CHMPropertyPage::OnSize(nType, cx, cy);
+	if (GetDlgItem(IDC_COMBO_PORT_STATUS) == nullptr) return;
+
+
+	// 鍒涘缓Job Existence Slots鎺т欢
+	CRect rcLabel, rcComboBox, rcClient;
+	GetDlgItem(IDC_LABEL_JOB_EXISTENCE_SLOTS)->GetWindowRect(&rcLabel);
+	ScreenToClient(rcLabel);
+	GetDlgItem(IDC_COMBO_CASSETTE_STATUS)->GetWindowRect(&rcComboBox);
+	ScreenToClient(rcComboBox);
+	GetClientRect(rcClient);
+
+	m_ctrlJobSlotGrid.MoveWindow(rcComboBox.left, rcLabel.top, 
+		rcClient.right - 22 - rcComboBox.left, rcClient.bottom - 12 - rcLabel.top);
+}
\ No newline at end of file
diff --git a/SourceCode/Bond/Servo/CPagePortStatus.h b/SourceCode/Bond/Servo/CPagePortStatus.h
new file mode 100644
index 0000000..5a40b72
--- /dev/null
+++ b/SourceCode/Bond/Servo/CPagePortStatus.h
@@ -0,0 +1,38 @@
+锘�#pragma once
+#include "CHMPropertyPage.h"
+#include "JobSlotGrid.h"
+
+
+// CPagePortStatus 瀵硅瘽妗�
+
+class CPagePortStatus : public CHMPropertyPage
+{
+	DECLARE_DYNAMIC(CPagePortStatus)
+
+public:
+	CPagePortStatus(CWnd* pParent = nullptr);   // 鏍囧噯鏋勯�犲嚱鏁�
+	virtual ~CPagePortStatus();
+
+public:
+	void setLoadPort(SERVO::CLoadPort* pPort);
+
+private:
+	SERVO::CLoadPort* m_pPort;
+	CJobSlotGrid m_ctrlJobSlotGrid;
+
+
+// 瀵硅瘽妗嗘暟鎹�
+#ifdef AFX_DESIGN_TIME
+	enum { IDD = IDD_PAGE_PORT_STATUS };
+#endif
+
+protected:
+	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 鏀寔
+
+	DECLARE_MESSAGE_MAP()
+public:
+	virtual BOOL OnInitDialog();
+	afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor);
+	afx_msg void OnDestroy();
+	afx_msg void OnSize(UINT nType, int cx, int cy);
+};
diff --git a/SourceCode/Bond/Servo/CPortStatusReport.cpp b/SourceCode/Bond/Servo/CPortStatusReport.cpp
new file mode 100644
index 0000000..6b2b7ca
--- /dev/null
+++ b/SourceCode/Bond/Servo/CPortStatusReport.cpp
@@ -0,0 +1,212 @@
+#include "stdafx.h"
+#include "CPortStatusReport.h"
+#include "ToolUnits.h"
+#include "Common.h"
+#include "Log.h"
+
+
+namespace SERVO {
+	CPortStatusReport::CPortStatusReport()
+	{
+		m_nPortStatus = 0;
+		m_nCassetteSequenceNo = 0;
+		m_nLoadingCassetteType = 0;
+		m_nQTimeFlag = 0;
+		m_nCassetteMappingState = 0;
+		m_nCassetteStatus = 0;
+	}
+
+	CPortStatusReport::~CPortStatusReport()
+	{
+
+	}
+
+	void CPortStatusReport::copyEx(CPortStatusReport& other)
+	{
+		m_nPortStatus = other.m_nPortStatus;
+		m_nCassetteSequenceNo = other.m_nCassetteSequenceNo;
+		m_strCassetteID = other.m_strCassetteID;
+
+		// Job Existence Slot
+		if (PORT_INUSE == m_nPortStatus) {
+			for (int i = 0; i < 12; i++) {
+				m_nJobExistenceSlot[i] = other.m_nJobExistenceSlot[i];
+			}
+		}
+
+		if (!m_strCassetteID.empty()) {
+			m_nLoadingCassetteType = other.m_nLoadingCassetteType;
+		}
+
+		if (PORT_UNLOAD_READY == m_nPortStatus) {
+			m_nQTimeFlag = other.m_nQTimeFlag;
+		}
+
+		m_nCassetteMappingState = other.m_nCassetteMappingState;
+		m_nCassetteStatus = other.m_nCassetteStatus;
+	}
+
+	short CPortStatusReport::getPortStatus()
+	{
+		return m_nPortStatus;
+	}
+
+	short CPortStatusReport::getCassetteSequenceNo()
+	{
+		return m_nCassetteSequenceNo;
+	}
+
+	std::string& CPortStatusReport::getCassetteId()
+	{
+		return m_strCassetteID;
+	}
+
+	short CPortStatusReport::getLoadingCassetteType()
+	{
+		return m_nLoadingCassetteType;
+	}
+
+	short CPortStatusReport::getQTimeFlag()
+	{
+		return m_nQTimeFlag;
+	}
+
+	short CPortStatusReport::getCassetteMappingState()
+	{
+		return m_nCassetteMappingState;
+	}
+
+	short CPortStatusReport::getCassetteStatus()
+	{
+		return m_nCassetteStatus;
+	}
+
+	int CPortStatusReport::serialize(char* pszBuffer, int nBufferSize)
+	{
+		if (nBufferSize < 32 * 2) return -1;
+
+		int index = 0;
+		memcpy(&pszBuffer[index], &m_nPortStatus, sizeof(short));
+		index += sizeof(short);
+
+		memcpy(&pszBuffer[index], &m_nCassetteSequenceNo, sizeof(short));
+		index += sizeof(short);
+
+		int strLen = min(20, m_strCassetteID.size());
+		memcpy(&pszBuffer[index], m_strCassetteID.c_str(), strLen);
+		index += 20;
+
+		memcpy(&pszBuffer[index], &m_nJobExistenceSlot[0], sizeof(short));
+		index += 12 * sizeof(short);
+
+		memcpy(&pszBuffer[index], &m_nLoadingCassetteType, sizeof(short));
+		index += sizeof(short);
+
+		memcpy(&pszBuffer[index], &m_nQTimeFlag, sizeof(short));
+		index += sizeof(short);
+
+		memcpy(&pszBuffer[index], &m_nCassetteMappingState, sizeof(short));
+		index += sizeof(short);
+
+		memcpy(&pszBuffer[index], &m_nCassetteStatus, sizeof(short));
+		index += sizeof(short);
+
+		return 32 * 2;
+	}
+
+	int CPortStatusReport::unserialize(const char* pszBuffer, int nBufferSize)
+	{
+		if (nBufferSize < 32 * 2) return -1;
+
+		int index = 0;
+		memcpy(&m_nPortStatus, &pszBuffer[index], sizeof(short));
+		index += sizeof(short);
+
+		memcpy(&m_nCassetteSequenceNo, &pszBuffer[index], sizeof(short));
+		index += sizeof(short);
+
+		CToolUnits::convertString(&pszBuffer[index], 20, m_strCassetteID);
+		index += 20;
+
+		memcpy(&m_nJobExistenceSlot[0], &pszBuffer[index], sizeof(short));
+		index += 12 * sizeof(short);
+
+		memcpy(&m_nLoadingCassetteType, &pszBuffer[index], sizeof(short));
+		index += sizeof(short);
+
+		memcpy(&m_nLoadingCassetteType, &pszBuffer[index], sizeof(short));
+		index += sizeof(short);
+
+		memcpy(&m_nQTimeFlag, &pszBuffer[index], sizeof(short));
+		index += sizeof(short);
+
+		memcpy(&m_nCassetteMappingState, &pszBuffer[index], sizeof(short));
+		index += sizeof(short);
+
+		memcpy(&m_nCassetteStatus, &pszBuffer[index], sizeof(short));
+		index += sizeof(short);
+
+		return 15 * 2;
+	}
+
+	void CPortStatusReport::getAttributeVector(CAttributeVector& attrubutes, int beginWeight)
+	{
+		unsigned int weight = beginWeight;
+		std::string strTemp;
+
+		attrubutes.addAttribute(new CAttribute("PortStatus",
+			std::to_string(m_nPortStatus).c_str(), "", weight++));
+
+		attrubutes.addAttribute(new CAttribute("CassetteSequenceNo",
+			std::to_string(m_nCassetteSequenceNo).c_str(), "", weight++));
+
+		attrubutes.addAttribute(new CAttribute("CassetteID",
+			m_strCassetteID.c_str(), "", weight++));
+
+		attrubutes.addAttribute(new CAttribute("LoadingCassetteType",
+			std::to_string(m_nLoadingCassetteType).c_str(), "", weight++));
+
+		attrubutes.addAttribute(new CAttribute("QTimeFlag",
+			std::to_string(m_nQTimeFlag).c_str(), "", weight++));
+
+		attrubutes.addAttribute(new CAttribute("CassetteMappingState",
+			std::to_string(m_nCassetteMappingState).c_str(), "", weight++));
+
+		attrubutes.addAttribute(new CAttribute("CassetteStatus",
+			std::to_string(m_nCassetteStatus).c_str(), "", weight++));
+	}
+
+	bool CPortStatusReport::canPickFromPort()
+	{
+		// 1. Port 状态必须是 Load Ready(上料请求)
+		if (m_nPortStatus != PORT_LOAD_REQUEST) return false;
+
+		// 2. Cassette 状态必须不是“无盒子”,应为等待开始或处理中等
+		if (m_nCassetteStatus == CASSETTE_NO_EXIST || m_nCassetteStatus == CASSETTE_PROCCESS_PAUSED)
+			return false;
+
+		// 3. Cassette ID 不可为空
+		if (m_strCassetteID.empty()) return false;
+
+		// 4. 至少一个Slot存在玻璃
+		if (!isJobExistenceSlot()) return false;
+
+		// 5. Mapping状态必须已使用
+		if (m_nCassetteMappingState != 1) return false;
+
+		// 6. Cassette 类型必须是有效盒子
+		if (m_nLoadingCassetteType != 1) return false;
+
+		return true;
+	}
+
+	bool CPortStatusReport::isJobExistenceSlot()
+	{
+		for (int i = 0; i < 12; i++) {
+			if (m_nJobExistenceSlot[i] != 0) return true;
+		}
+
+		return false;
+	}
+}
+
diff --git a/SourceCode/Bond/Servo/CPortStatusReport.h b/SourceCode/Bond/Servo/CPortStatusReport.h
new file mode 100644
index 0000000..4aede52
--- /dev/null
+++ b/SourceCode/Bond/Servo/CPortStatusReport.h
@@ -0,0 +1,42 @@
+#pragma once
+#include <string>
+#include "CAttributeVector.h"
+#include "CReadStep.h"
+
+
+namespace SERVO {
+	class CPortStatusReport
+	{
+	public:
+		CPortStatusReport();
+		~CPortStatusReport();
+
+	public:
+		void copyEx(CPortStatusReport& other);
+		short getPortStatus();
+		short getCassetteSequenceNo();
+		std::string& getCassetteId();
+		short getLoadingCassetteType();
+		short getQTimeFlag();
+		short getCassetteMappingState();
+		short getCassetteStatus();
+		int serialize(char* pszBuffer, int nBufferSize);
+		int unserialize(const char* pszBuffer, int nBufferSize);
+		void getAttributeVector(CAttributeVector& attrubutes, int beginWeight);
+		
+	public:
+		bool canPickFromPort();
+		bool isJobExistenceSlot();
+
+	private:
+		short m_nPortStatus;
+		short m_nCassetteSequenceNo;
+		std::string m_strCassetteID;
+		short m_nJobExistenceSlot[12];		// 12 * 16 = 192 个slot是否存在glass
+		short m_nLoadingCassetteType;		// 1: Actual Cassette 2 : Empty Cassette
+		short m_nQTimeFlag;
+		short m_nCassetteMappingState;		// 1: mapping use  2: mapping not use
+		short m_nCassetteStatus;
+	};
+}
+
diff --git a/SourceCode/Bond/Servo/CVacuumBake.cpp b/SourceCode/Bond/Servo/CVacuumBake.cpp
index 71b7143..790e3e3 100644
--- a/SourceCode/Bond/Servo/CVacuumBake.cpp
+++ b/SourceCode/Bond/Servo/CVacuumBake.cpp
@@ -92,4 +92,9 @@
 
 		return TRUE;
 	}
+
+	int CVacuumBake::getIndexerOperationModeBaseValue()
+	{
+		return 30000;
+	}
 }
diff --git a/SourceCode/Bond/Servo/CVacuumBake.h b/SourceCode/Bond/Servo/CVacuumBake.h
index dc0c59f..ef0e1ea 100644
--- a/SourceCode/Bond/Servo/CVacuumBake.h
+++ b/SourceCode/Bond/Servo/CVacuumBake.h
@@ -21,6 +21,8 @@
         virtual int recvIntent(CPin* pPin, CIntent* pIntent);
         virtual BOOL glassWillArrive(CGlass* pGlass);
         virtual BOOL onPreStoredJob(int port, CJobDataB* pJobDataB);
+        virtual int getIndexerOperationModeBaseValue();
+
 	};
 }
 
diff --git a/SourceCode/Bond/Servo/CVcrEventReport.cpp b/SourceCode/Bond/Servo/CVcrEventReport.cpp
index 914b0d0..248cd03 100644
--- a/SourceCode/Bond/Servo/CVcrEventReport.cpp
+++ b/SourceCode/Bond/Servo/CVcrEventReport.cpp
@@ -71,7 +71,7 @@
 		return 15 * 2;
 	}
 
-	int CVcrEventReport::unserialize(char* pszBuffer, int nBufferSize)
+	int CVcrEventReport::unserialize(const char* pszBuffer, int nBufferSize)
 	{
 		if (nBufferSize < 640) return -1;
 
@@ -97,6 +97,30 @@
 		return 15 * 2;
 	}
 
+	void CVcrEventReport::getAttributeVector(CAttributeVector& attrubutes, int beginWeight)
+	{
+		unsigned int weight = beginWeight;
+		std::string strTemp;
+
+		attrubutes.addAttribute(new CAttribute("GlassId",
+			m_strGlassId.c_str(), "", weight++));
+
+		attrubutes.addAttribute(new CAttribute("CassetteSequenceNo",
+			std::to_string(m_nCassetteSequenceNo).c_str(), "", weight++));
+
+		attrubutes.addAttribute(new CAttribute("JobSequenceNo",
+			std::to_string(m_nJobSequenceNo).c_str(), "", weight++));
+
+		attrubutes.addAttribute(new CAttribute("UnitNo",
+			std::to_string(m_nUnitNo).c_str(), "", weight++));
+
+		attrubutes.addAttribute(new CAttribute("VcrNo",
+			std::to_string(m_nVcrNo).c_str(), "", weight++));
+
+		attrubutes.addAttribute(new CAttribute("VcrResult",
+			std::to_string(m_nVcrResult).c_str(), "", weight++));
+	}
+
 	std::string& CVcrEventReport::getVcrResultDescription(std::string& strDescription)
 	{
 		static char* pszDescription[4] = {
diff --git a/SourceCode/Bond/Servo/CVcrEventReport.h b/SourceCode/Bond/Servo/CVcrEventReport.h
index 275cf30..8ff3992 100644
--- a/SourceCode/Bond/Servo/CVcrEventReport.h
+++ b/SourceCode/Bond/Servo/CVcrEventReport.h
@@ -1,5 +1,6 @@
 #pragma once
 #include <string>
+#include "CAttributeVector.h"
 
 
 namespace SERVO {
@@ -18,7 +19,8 @@
 		short getVcrResult();
 		std::string& getVcrResultDescription(std::string& strDescription);
 		int serialize(char* pszBuffer, int nBufferSize);
-		int unserialize(char* pszBuffer, int nBufferSize);
+		int unserialize(const char* pszBuffer, int nBufferSize);
+		void getAttributeVector(CAttributeVector& attrubutes, int beginWeight);
 
 	private:
 		std::string m_strGlassId;			// Read Data
diff --git a/SourceCode/Bond/Servo/Common.h b/SourceCode/Bond/Servo/Common.h
index cf7464a..7d09612 100644
--- a/SourceCode/Bond/Servo/Common.h
+++ b/SourceCode/Bond/Servo/Common.h
@@ -34,6 +34,9 @@
 #define EQ_BOX_ONLINE						RGB(0, 176, 80)
 #define EQ_BOX_FRAME1						RGB(22, 22, 22)
 #define EQ_BOX_FRAME2						RGB(255, 127, 39)
+#define CR_MSGBOX_BKGND						RGB(7, 71, 166)
+#define CR_MSGBOX_TITLE						RGB(200, 216, 246)
+#define CR_MSGBOX_MESSAGE					RGB(200, 216, 246)
 
 
 /* LOG BTN */
@@ -64,9 +67,10 @@
 #define EQ_ID_VACUUMBAKE		9
 #define EQ_ID_ALIGNER			10
 #define EQ_ID_BAKE_COOLING		11
-#define EQ_ID_ARM				12
-#define EQ_ID_ARM_TRAY1			13
-#define EQ_ID_ARM_TRAY2			14
+#define EQ_ID_MEASUREMENT		12
+#define EQ_ID_ARM				13
+#define EQ_ID_ARM_TRAY1			14
+#define EQ_ID_ARM_TRAY2			15
 #define EQ_ID_OPERATOR_REMOVE	999
 
 
@@ -110,30 +114,30 @@
 #define STEP_EQ_PORT4_TRANSFER_MODE		_T("EQPort4TransferMode")
 #define STEP_EQ_PORT4_ENABLE			_T("EQPort4Enable")
 #define STEP_EQ_PORT4_TYPE_ATUO			_T("EQPort4TypeAuto")
-#define STEP_EQ_P1_CASSETTE_EMPTY		_T("EQPort1CassetteEmpty")
-#define STEP_EQ_P1_CASSETTE_LOAD_EADY	_T("EQPort1CassetteLoadReady")
-#define STEP_EQ_P1_CASSETTE_LOADED		_T("EQPort1CassetteLoaded")
-#define STEP_EQ_P1_CASSETTE_INUSE		_T("EQPort1CassetteInUse")
-#define STEP_EQ_P1_CASSETTE_UNLOAD_EADY	_T("EQPort1CassetteUnloadReady")
-#define STEP_EQ_P1_CASSETTE_BLOCKED		_T("EQPort1CassetteBlocked")
-#define STEP_EQ_P2_CASSETTE_EMPTY		_T("EQPort2CassetteEmpty")
-#define STEP_EQ_P2_CASSETTE_LOAD_EADY	_T("EQPort2CassetteLoadReady")
-#define STEP_EQ_P2_CASSETTE_LOADED		_T("EQPort2CassetteLoaded")
-#define STEP_EQ_P2_CASSETTE_INUSE		_T("EQPort2CassetteInUse")
-#define STEP_EQ_P2_CASSETTE_UNLOAD_EADY	_T("EQPort2CassetteUnloadReady")
-#define STEP_EQ_P2_CASSETTE_BLOCKED		_T("EQPort2CassetteBlocked")
-#define STEP_EQ_P3_CASSETTE_EMPTY		_T("EQPort3CassetteEmpty")
-#define STEP_EQ_P3_CASSETTE_LOAD_EADY	_T("EQPort3CassetteLoadReady")
-#define STEP_EQ_P3_CASSETTE_LOADED		_T("EQPort3CassetteLoaded")
-#define STEP_EQ_P3_CASSETTE_INUSE		_T("EQPort3CassetteInUse")
-#define STEP_EQ_P3_CASSETTE_UNLOAD_EADY	_T("EQPort3CassetteUnloadReady")
-#define STEP_EQ_P3_CASSETTE_BLOCKED		_T("EQPort3CassetteBlocked")
-#define STEP_EQ_P4_CASSETTE_EMPTY		_T("EQPort4CassetteEmpty")
-#define STEP_EQ_P4_CASSETTE_LOAD_EADY	_T("EQPort4CassetteLoadReady")
-#define STEP_EQ_P4_CASSETTE_LOADED		_T("EQPort4CassetteLoaded")
-#define STEP_EQ_P4_CASSETTE_INUSE		_T("EQPort4CassetteInUse")
-#define STEP_EQ_P4_CASSETTE_UNLOAD_EADY	_T("EQPort4CassetteUnloadReady")
-#define STEP_EQ_P4_CASSETTE_BLOCKED		_T("EQPort4CassetteBlocked")
+#define STEP_EQ_PORT1_EMPTY				_T("EQPort1Empty")
+#define STEP_EQ_PORT1_LOAD_EADY			_T("EQPort1LoadReady")
+#define STEP_EQ_PORT1_LOADED			_T("EQPort1Loaded")
+#define STEP_EQ_PORT1_INUSE				_T("EQPort1InUse")
+#define STEP_EQ_PORT1_UNLOAD_EADY		_T("EQPort1UnloadReady")
+#define STEP_EQ_PORT1_BLOCKED			_T("EQPort1Blocked")
+#define STEP_EQ_PORT2_EMPTY				_T("EQPort2Empty")
+#define STEP_EQ_PORT2_LOAD_EADY			_T("EQPort2LoadReady")
+#define STEP_EQ_PORT2_LOADED			_T("EQPort2Loaded")
+#define STEP_EQ_PORT2_INUSE				_T("EQPort2InUse")
+#define STEP_EQ_PORT2_UNLOAD_EADY		_T("EQPort2UnloadReady")
+#define STEP_EQ_PORT2_BLOCKED			_T("EQPort2Blocked")
+#define STEP_EQ_PORT3_EMPTY				_T("EQPort3Empty")
+#define STEP_EQ_PORT3_LOAD_EADY			_T("EQPort3LoadReady")
+#define STEP_EQ_PORT3_LOADED			_T("EQPort3Loaded")
+#define STEP_EQ_PORT3_INUSE				_T("EQPort3InUse")
+#define STEP_EQ_PORT3_UNLOAD_EADY		_T("EQPort3UnloadReady")
+#define STEP_EQ_PORT3_BLOCKED			_T("EQPort3Blocked")
+#define STEP_EQ_PORT4_EMPTY				_T("EQPort4Empty")
+#define STEP_EQ_PORT4_LOAD_EADY			_T("EQPort4LoadReady")
+#define STEP_EQ_PORT4_LOADED			_T("EQPort4Loaded")
+#define STEP_EQ_PORT4_INUSE				_T("EQPort4InUse")
+#define STEP_EQ_PORT4_UNLOAD_EADY		_T("EQPort4UnloadReady")
+#define STEP_EQ_PORT4_BLOCKED			_T("EQPort4Blocked")
 #define STEP_EQ_P1_CASSETTE_CTRL_CMD	_T("EQPort1CassetteCtrlCmd")
 #define STEP_EQ_P2_CASSETTE_CTRL_CMD	_T("EQPort2CassetteCtrlCmd")
 #define STEP_EQ_P3_CASSETTE_CTRL_CMD	_T("EQPort3CassetteCtrlCmd")
@@ -209,7 +213,31 @@
 #define STEP_EQ_STORED_JOB15			_T("EQStoredJobReport15")
 #define STEP_EQ_DISPATCHINT_MODE_CHANGE	_T("EQDispatchingModeChangeCommand")
 #define STEP_EFEM_ROBOT_CMD				_T("EFEMRobotCmd")
-
+#define STEP_EFEM_IN_OP_MODE_CHANGE		_T("EFEMIndexerOperationModeChangeCommand")
+#define STEP_PORT1_TYPE_CHANGE			_T("Port1TypeChange")
+#define STEP_PORT2_TYPE_CHANGE			_T("Port2TypeChange")
+#define STEP_PORT3_TYPE_CHANGE			_T("Port3TypeChange")
+#define STEP_PORT4_TYPE_CHANGE			_T("Port4TypeChange")
+#define STEP_PORT1_MODE_CHANGE			_T("Port1ModeChange")
+#define STEP_PORT2_MODE_CHANGE			_T("Port2ModeChange")
+#define STEP_PORT3_MODE_CHANGE			_T("Port3ModeChange")
+#define STEP_PORT4_MODE_CHANGE			_T("Port4ModeChange")
+#define STEP_PORT1_TRANSFER_MODE_CHANGE	_T("Port1TransferModeChange")
+#define STEP_PORT2_TRANSFER_MODE_CHANGE	_T("Port2TransferModeChange")
+#define STEP_PORT3_TRANSFER_MODE_CHANGE	_T("Port3TransferModeChange")
+#define STEP_PORT4_TRANSFER_MODE_CHANGE	_T("Port4TransferModeChange")
+#define STEP_PORT1_ENABLE_MODE_CHANGE	_T("Port1EnableModeChange")
+#define STEP_PORT2_ENABLE_MODE_CHANGE	_T("Port2EnableModeChange")
+#define STEP_PORT3_ENABLE_MODE_CHANGE	_T("Port3EnableModeChange")
+#define STEP_PORT4_ENABLE_MODE_CHANGE	_T("Port4EnableModeChange")
+#define STEP_PORT1_TYPE_AUTO_CHANGE		_T("Port1TypeAutoChange")
+#define STEP_PORT2_TYPE_AUTO_CHANGE		_T("Port2TypeAutoChange")
+#define STEP_PORT3_TYPE_AUTO_CHANGE		_T("Port3TypeAutoChange")
+#define STEP_PORT4_TYPE_AUTO_CHANGE		_T("Port4TypeAutoChange")
+#define STEP_PORT1_CASSETTE_TYPE_CHANGE	_T("Port1CassetteTypeChange")
+#define STEP_PORT2_CASSETTE_TYPE_CHANGE	_T("Port2CassetteTypeChange")
+#define STEP_PORT3_CASSETTE_TYPE_CHANGE	_T("Port3CassetteTypeChange")
+#define STEP_PORT4_CASSETTE_TYPE_CHANGE	_T("Port4CassetteTypeChange")
 
 
 /* Step ID */
@@ -282,7 +310,8 @@
 #define STEP_ID_FETCHED_OUT_JOB_REPORT13		0x5BB
 #define STEP_ID_FETCHED_OUT_JOB_REPORT14		0x5BC
 #define STEP_ID_FETCHED_OUT_JOB_REPORT15		0x5BD
-#define STEP_ID_DISPATCHING_MODE_CHANGE_REPLY	0x5E2
+#define STEP_ID_IN_OP_CMD_REPLY					0x5F0
+#define STEP_ID_DISPATCHING_MODE_CHANGE_REPLY	0x5F1
 #define STEP_ID_PORT1_TYPE_CHANGE				0x600
 #define STEP_ID_PORT2_TYPE_CHANGE				0x601
 #define STEP_ID_PORT3_TYPE_CHANGE				0x602
@@ -307,31 +336,56 @@
 #define STEP_ID_PORT2_TYPE_AUTO_CHANGE			0x629
 #define STEP_ID_PORT3_TYPE_AUTO_CHANGE			0x62A
 #define STEP_ID_PORT4_TYPE_AUTO_CHANGE			0x62B
-#define STEP_ID_PORT1_CASSETTIE_EMPTY			0x638
-#define STEP_ID_PORT1_CASSETTIE_LOAD_READY		0x640
-#define STEP_ID_PORT1_CASSETTIE_LOADED			0x648
-#define STEP_ID_PORT1_CASSETTIE_INUSE			0x650
-#define STEP_ID_PORT1_CASSETTIE_UNLOAD_READY	0x658
-#define STEP_ID_PORT1_CASSETTIE_BLOCKED			0x660
-#define STEP_ID_PORT2_CASSETTIE_EMPTY			0x639
-#define STEP_ID_PORT2_CASSETTIE_LOAD_READY		0x641
-#define STEP_ID_PORT2_CASSETTIE_LOADED			0x649
-#define STEP_ID_PORT2_CASSETTIE_INUSE			0x651
-#define STEP_ID_PORT2_CASSETTIE_UNLOAD_READY	0x659
-#define STEP_ID_PORT2_CASSETTIE_BLOCKED			0x661
-#define STEP_ID_PORT3_CASSETTIE_EMPTY			0x63a
-#define STEP_ID_PORT3_CASSETTIE_LOAD_READY		0x642
-#define STEP_ID_PORT3_CASSETTIE_LOADED			0x64a
-#define STEP_ID_PORT3_CASSETTIE_INUSE			0x652
-#define STEP_ID_PORT3_CASSETTIE_UNLOAD_READY	0x65a
-#define STEP_ID_PORT3_CASSETTIE_BLOCKED			0x662
-#define STEP_ID_PORT4_CASSETTIE_EMPTY			0x63b
-#define STEP_ID_PORT4_CASSETTIE_LOAD_READY		0x643
-#define STEP_ID_PORT4_CASSETTIE_LOADED			0x64b
-#define STEP_ID_PORT4_CASSETTIE_INUSE			0x653
-#define STEP_ID_PORT4_CASSETTIE_UNLOAD_READY	0x65b
-#define STEP_ID_PORT4_CASSETTIE_BLOCKED			0x663
-#define STEP_ID_ROBOT_CMD_REPLY					0x6b0
+#define STEP_ID_PORT1_EMPTY						0x638
+#define STEP_ID_PORT1_LOAD_READY				0x640
+#define STEP_ID_PORT1_LOADED					0x648
+#define STEP_ID_PORT1_INUSE						0x650
+#define STEP_ID_PORT1_UNLOAD_READY				0x658
+#define STEP_ID_PORT1_BLOCKED					0x660
+#define STEP_ID_PORT2_EMPTY						0x639
+#define STEP_ID_PORT2_LOAD_READY				0x641
+#define STEP_ID_PORT2_LOADED					0x649
+#define STEP_ID_PORT2_INUSE						0x651
+#define STEP_ID_PORT2_UNLOAD_READY				0x659
+#define STEP_ID_PORT2_BLOCKED					0x661
+#define STEP_ID_PORT3_EMPTY						0x63a
+#define STEP_ID_PORT3_LOAD_READY				0x642
+#define STEP_ID_PORT3_LOADED					0x64a
+#define STEP_ID_PORT3_INUSE						0x652
+#define STEP_ID_PORT3_UNLOAD_READY				0x65a
+#define STEP_ID_PORT3_BLOCKED					0x662
+#define STEP_ID_PORT4_EMPTY						0x63b
+#define STEP_ID_PORT4_LOAD_READY				0x643
+#define STEP_ID_PORT4_LOADED					0x64b
+#define STEP_ID_PORT4_INUSE						0x653
+#define STEP_ID_PORT4_UNLOAD_READY				0x65b
+#define STEP_ID_PORT4_BLOCKED					0x663
+#define STEP_ID_PROT1_TYPE_CHANGE_REPLY			0x670
+#define STEP_ID_PROT2_TYPE_CHANGE_REPLY			0x671
+#define STEP_ID_PROT3_TYPE_CHANGE_REPLY			0x672
+#define STEP_ID_PROT4_TYPE_CHANGE_REPLY			0x673
+#define STEP_ID_PROT1_MODE_CHANGE_REPLY			0x678
+#define STEP_ID_PROT2_MODE_CHANGE_REPLY			0x679
+#define STEP_ID_PROT3_MODE_CHANGE_REPLY			0x67A
+#define STEP_ID_PROT4_MODE_CHANGE_REPLY			0x67B
+#define STEP_ID_PROT1_TRANSFER_MODE_CHANGE_REPLY	0x680
+#define STEP_ID_PROT2_TRANSFER_MODE_CHANGE_REPLY	0x681
+#define STEP_ID_PROT3_TRANSFER_MODE_CHANGE_REPLY	0x682
+#define STEP_ID_PROT4_TRANSFER_MODE_CHANGE_REPLY	0x683
+#define STEP_ID_PROT1_ENABLE_MODE_CHANGE_REPLY		0x688
+#define STEP_ID_PROT2_ENABLE_MODE_CHANGE_REPLY		0x689
+#define STEP_ID_PROT3_ENABLE_MODE_CHANGE_REPLY		0x68A
+#define STEP_ID_PROT4_ENABLE_MODE_CHANGE_REPLY		0x68B
+#define STEP_ID_PROT1_TYPE_AUTO_CHANGE_REPLY		0x690
+#define STEP_ID_PROT2_TYPE_AUTO_CHANGE_REPLY		0x691
+#define STEP_ID_PROT3_TYPE_AUTO_CHANGE_REPLY		0x692
+#define STEP_ID_PROT4_TYPE_AUTO_CHANGE_REPLY		0x693
+#define STEP_ID_PROT1_CASSETTE_TYPE_CHANGE_REPLY	0x698
+#define STEP_ID_PROT2_CASSETTE_TYPE_CHANGE_REPLY	0x699
+#define STEP_ID_PROT3_CASSETTE_TYPE_CHANGE_REPLY	0x69A
+#define STEP_ID_PROT4_CASSETTE_TYPE_CHANGE_REPLY	0x69B
+#define STEP_ID_ROBOT_CMD_REPLY						0x6b0
+
 
 
 /* base alarm */
@@ -361,6 +415,7 @@
 
 /* Port Status */
 #define PORT_LOAD_READY				1
+#define PORT_LOAD_REQUEST			PORT_LOAD_READY
 #define PORT_LOADED					2
 #define PORT_INUSE					3
 #define PORT_LOAD_COMPLETE			PORT_INUSE
diff --git a/SourceCode/Bond/Servo/JobSlotGrid.cpp b/SourceCode/Bond/Servo/JobSlotGrid.cpp
new file mode 100644
index 0000000..cf7df72
--- /dev/null
+++ b/SourceCode/Bond/Servo/JobSlotGrid.cpp
@@ -0,0 +1,170 @@
+锘�#include "stdafx.h"
+#include "JobSlotGrid.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#endif
+
+IMPLEMENT_DYNAMIC(CJobSlotGrid, CWnd)
+
+BEGIN_MESSAGE_MAP(CJobSlotGrid, CWnd)
+    ON_WM_PAINT()
+    ON_WM_ERASEBKGND()
+END_MESSAGE_MAP()
+
+CJobSlotGrid::CJobSlotGrid() {
+    // 鍒濆鍖栭粯璁よ鍒楁暟
+    int m_nRows = 12;
+    int m_nCols = 16;
+
+    // 鍒濆鍖栭粯璁ゅ瓧浣�
+    m_fontText.CreatePointFont(60, _T("Arial"));
+
+	// 鍒濆鍖栭粯璁ら鑹�
+    COLORREF m_colorHasJob = RGB(0, 200, 0);      // 榛樿缁胯壊
+    COLORREF m_colorNoJob = RGB(220, 220, 220);   // 榛樿鐏拌壊
+
+    // 鍒濆鍖栭粯璁ょ敾鍒�
+    m_brushHasJob.CreateSolidBrush(m_colorHasJob);
+    m_brushNoJob.CreateSolidBrush(m_colorNoJob);
+}
+
+CJobSlotGrid::~CJobSlotGrid() {
+    if (m_fontText.GetSafeHandle()) {
+        m_fontText.DeleteObject();
+    }
+
+    if (m_brushHasJob.GetSafeHandle()) {
+        m_brushHasJob.DeleteObject();
+    }
+
+    if (m_brushNoJob.GetSafeHandle()) {
+        m_brushNoJob.DeleteObject();
+    }
+}
+
+void CJobSlotGrid::SetGridSize(int nRows, int nCols)
+{
+    m_nRows = nRows;
+    m_nCols = nCols;
+    m_vSlotStatus.assign(nRows, std::vector<bool>(nCols, false));
+
+    // 鍒濆鍖栨枃鏈暟缁�
+    m_vSlotText.assign(nRows, std::vector<CString>(nCols));
+    for (int i = 0; i < nRows; ++i) {
+        for (int j = 0; j < nCols; ++j) {
+            if (i == 0) {
+                m_vSlotText[i][j].Format(_T("%d"), j + 1);
+            }
+            else if (j == 0) {
+                m_vSlotText[i][j].Format(_T("%d"), i + 1);
+            }
+        }
+    }
+
+    Invalidate();
+}
+
+void CJobSlotGrid::SetColors(COLORREF colorHasJob, COLORREF colorNoJob)
+{
+    m_colorHasJob = colorHasJob;
+    m_colorNoJob = colorNoJob;
+
+    if (m_brushHasJob.GetSafeHandle()) {
+        m_brushHasJob.DeleteObject();
+    }
+
+    if (m_brushNoJob.GetSafeHandle()) { 
+        m_brushNoJob.DeleteObject();
+    }
+
+    m_brushHasJob.CreateSolidBrush(m_colorHasJob);
+    m_brushNoJob.CreateSolidBrush(m_colorNoJob);
+
+
+    Invalidate();
+}
+
+void CJobSlotGrid::SetSlotStatus(int nRow, int nCol, bool bHasJob, BOOL bInvalidate/* = TRUE*/)
+{
+    if (nRow >= 0 && nRow < m_nRows && nCol >= 0 && nCol < m_nCols) {
+        m_vSlotStatus[nRow][nCol] = bHasJob;
+        if (bInvalidate) {
+            Invalidate();
+        }
+    }
+}
+
+void CJobSlotGrid::SetSlotText(int nRow, int nCol, const CString& strText)
+{
+    if (nRow >= 0 && nRow < m_nRows && nCol >= 0 && nCol < m_nCols) {
+        m_vSlotText[nRow][nCol] = strText;
+        Invalidate();
+    }
+}
+
+void CJobSlotGrid::SetTextFont(const CString& strFontName, int nPointSize)
+{
+    // 鍒犻櫎鏃у瓧浣�
+    if (m_fontText.GetSafeHandle()) {
+        m_fontText.DeleteObject();
+    }
+
+    // CreatePointFont expects size in 1/10 pt
+    m_fontText.CreatePointFont(nPointSize * 10, strFontName);
+
+    Invalidate();
+}
+
+void CJobSlotGrid::ClearAll()
+{
+    if (m_vSlotStatus.empty()) {
+        return;
+    }
+
+    for (int i = 0; i < m_nRows; ++i) {
+        if (i < (int)m_vSlotStatus.size()) {
+            std::fill(m_vSlotStatus[i].begin(), m_vSlotStatus[i].end(), false);
+        }
+    }
+    Invalidate();
+}
+
+BOOL CJobSlotGrid::OnEraseBkgnd(CDC* pDC) {
+    return TRUE;
+}
+
+void CJobSlotGrid::OnPaint() {
+    CPaintDC dc(this);
+    DrawGrid(&dc);
+}
+
+void CJobSlotGrid::DrawGrid(CDC* pDC)
+{
+    CRect rect;
+    GetClientRect(&rect);
+
+    int nCellWidth = rect.Width() / m_nCols;
+    int nCellHeight = rect.Height() / m_nRows;
+    CFont* pOldFont = pDC->SelectObject(&m_fontText);
+
+    for (int i = 0; i < m_nRows; ++i) {
+        for (int j = 0; j < m_nCols; ++j) {
+            CRect cellRect(j * nCellWidth, i * nCellHeight, (j + 1) * nCellWidth, (i + 1) * nCellHeight);
+
+            // 鑳屾櫙
+            CBrush* pBrush = m_vSlotStatus[i][j] ? &m_brushHasJob : &m_brushNoJob;
+            pDC->FillRect(&cellRect, pBrush);
+
+            // 杈规
+            pDC->DrawEdge(&cellRect, EDGE_SUNKEN, BF_RECT);
+
+            // 鏂囧瓧锛堝眳涓級
+            pDC->SetBkMode(TRANSPARENT);
+            pDC->SetTextColor(RGB(0, 0, 0));
+            pDC->DrawText(m_vSlotText[i][j], &cellRect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
+        }
+    }
+
+    pDC->SelectObject(pOldFont);
+}
diff --git a/SourceCode/Bond/Servo/JobSlotGrid.h b/SourceCode/Bond/Servo/JobSlotGrid.h
new file mode 100644
index 0000000..f904aea
--- /dev/null
+++ b/SourceCode/Bond/Servo/JobSlotGrid.h
@@ -0,0 +1,37 @@
+#pragma once
+#include <afxwin.h>
+#include <vector>
+
+class CJobSlotGrid : public CWnd
+{
+    DECLARE_DYNAMIC(CJobSlotGrid)
+
+public:
+    CJobSlotGrid();
+    virtual ~CJobSlotGrid();
+
+    void SetGridSize(int nRows, int nCols);
+    void SetColors(COLORREF colorHasJob, COLORREF colorNoJob);
+    void SetSlotStatus(int nRow, int nCol, bool bHasJob, BOOL bInvalidate = TRUE);
+    void SetSlotText(int nRow, int nCol, const CString& strText);
+    void SetTextFont(const CString& strFontName, int nPointSize);
+    void ClearAll();
+
+protected:
+    afx_msg void OnPaint();
+    afx_msg BOOL OnEraseBkgnd(CDC* pDC);
+    DECLARE_MESSAGE_MAP()
+
+private:
+    int m_nRows;
+    int m_nCols;
+    CFont m_fontText;
+    COLORREF m_colorHasJob;
+    COLORREF m_colorNoJob;
+    CBrush m_brushHasJob;
+    CBrush m_brushNoJob;
+    std::vector<std::vector<bool>> m_vSlotStatus;
+    std::vector<std::vector<CString>> m_vSlotText;
+
+    void DrawGrid(CDC* pDC);
+};
\ No newline at end of file
diff --git a/SourceCode/Bond/Servo/MsgDlg.cpp b/SourceCode/Bond/Servo/MsgDlg.cpp
new file mode 100644
index 0000000..9e797c0
--- /dev/null
+++ b/SourceCode/Bond/Servo/MsgDlg.cpp
@@ -0,0 +1,303 @@
+锘�// MsgDlg.cpp: 瀹炵幇鏂囦欢
+//
+
+#include "stdafx.h"
+#include "Servo.h"
+#include "MsgDlg.h"
+#include "afxdialogex.h"
+
+
+// CMsgDlg 瀵硅瘽妗�
+
+IMPLEMENT_DYNAMIC(CMsgDlg, CDialogEx)
+
+CMsgDlg::CMsgDlg(CWnd* pParent /*=nullptr*/)
+	: CDialogEx(IDD_DIALOG_MSG, pParent)
+{
+	m_nCompleteCode = 0;
+	m_dwData = 0;
+	m_dwDataEx = 0;
+	m_crBkgnd = CR_MSGBOX_BKGND;
+	m_brBkgnd.CreateSolidBrush(m_crBkgnd);
+	m_crTitle = CR_MSGBOX_TITLE;
+	m_crMessage = CR_MSGBOX_MESSAGE;
+	m_nIcon = MSG_BOX_TIP;
+}
+
+CMsgDlg::CMsgDlg(CString strTitle, CString strMessage)
+	: CDialogEx(IDD_DIALOG_MSG, NULL)
+{
+	m_strTitle = strTitle;
+	m_strMessage = strMessage;
+	m_crBkgnd = CR_MSGBOX_BKGND;
+	m_brBkgnd.CreateSolidBrush(m_crBkgnd);
+	m_crTitle = CR_MSGBOX_TITLE;
+	m_crMessage = CR_MSGBOX_MESSAGE;
+	m_nIcon = MSG_BOX_TIP;
+}
+
+CMsgDlg::CMsgDlg(int nIcon, CString strTitle, CString strMessage)
+	: CDialogEx(IDD_DIALOG_MSG, NULL)
+{
+	m_strTitle = strTitle;
+	m_strMessage = strMessage;
+	m_crBkgnd = CR_MSGBOX_BKGND;
+	m_brBkgnd.CreateSolidBrush(m_crBkgnd);
+	m_crTitle = CR_MSGBOX_TITLE;
+	m_crMessage = CR_MSGBOX_MESSAGE;
+	m_nIcon = nIcon;
+}
+
+CMsgDlg::~CMsgDlg()
+{
+}
+
+void CMsgDlg::DoDataExchange(CDataExchange* pDX)
+{
+	CDialogEx::DoDataExchange(pDX);
+}
+
+
+BEGIN_MESSAGE_MAP(CMsgDlg, CDialogEx)
+	ON_WM_TIMER()
+	ON_WM_CTLCOLOR()
+	ON_WM_SIZE()
+END_MESSAGE_MAP()
+
+
+// CMsgDlg 娑堟伅澶勭悊绋嬪簭
+
+void CMsgDlg::SetCompleteCode(int code)
+{
+	m_nCompleteCode = code;
+	CWnd* pProgressCtrl = GetDlgItem(IDC_PROGRESS1);
+	if(pProgressCtrl != nullptr) pProgressCtrl->ShowWindow(SW_HIDE);
+}
+
+int CMsgDlg::GetCompleteCode()
+{
+	return m_nCompleteCode;
+}
+
+void CMsgDlg::SetData(DWORD_PTR dwData)
+{
+	m_dwData = dwData;
+}
+
+DWORD_PTR CMsgDlg::GetData()
+{
+	return m_dwData;
+}
+
+void CMsgDlg::SetDataEx(DWORD_PTR dwData)
+{
+	m_dwDataEx = dwData;
+}
+
+DWORD_PTR CMsgDlg::GetDataEx()
+{
+	return m_dwDataEx;
+}
+
+void CMsgDlg::SetIcon(int nIcon)
+{
+	m_nIcon = nIcon;
+	if (::IsWindow(m_hWnd)) {
+		UpdateIcon();
+	}
+}
+
+void CMsgDlg::UpdateIcon()
+{
+	static char* pszFile[] = { "msgbox_tip.ico", "msgbox_question.ico", "msgbox_warning.ico", "msgbox_error.ico",
+	"msgbox_succeed.ico"};
+	if (MSG_BOX_TIP <= m_nIcon && m_nIcon <= MSG_BOX_SUCCEED) {
+		CStatic* pStatic = (CStatic*)GetDlgItem(IDC_ICON_MAIN);
+		if (pStatic != NULL) {
+			CString strFile;
+			strFile.Format(_T("%s\\res\\%s"), (LPTSTR)(LPCTSTR)theApp.m_strAppDir, pszFile[m_nIcon]);
+			HICON hIcon = (HICON)LoadImage(AfxGetInstanceHandle(), strFile, IMAGE_ICON,
+				48, 48, LR_DEFAULTCOLOR | LR_CREATEDIBSECTION | LR_LOADFROMFILE);
+			pStatic->SetIcon(hIcon);
+			SetMarquee(TRUE, 1);
+		}
+	}
+}
+
+void CMsgDlg::SetTitle(CString strTitle)
+{
+	m_strTitle = strTitle;
+	if (::IsWindow(m_hWnd) && GetDlgItem(IDC_LABEL_TITLE) != NULL) {
+		SetWindowText(m_strTitle);
+		SetDlgItemText(IDC_LABEL_TITLE, m_strTitle);
+	}
+}
+
+void CMsgDlg::SetMessage(CString strMessage)
+{
+	m_strMessage = strMessage;
+	if (::IsWindow(m_hWnd) && GetDlgItem(IDC_LABEL_MSG) != NULL) {
+		SetDlgItemText(IDC_LABEL_MSG, m_strMessage);
+	}
+}
+
+void CMsgDlg::SetMarquee(_In_ BOOL fMarqueeMode, _In_ int nInterval)
+{
+	if (!::IsWindow(m_hWnd)) {
+		return;
+	}
+
+	CProgressCtrl* pProgressCtrl = (CProgressCtrl*)GetDlgItem(IDC_PROGRESS1);
+	if (pProgressCtrl != NULL) {
+		pProgressCtrl->SendMessage(PBM_SETMARQUEE, (WPARAM)fMarqueeMode, (LPARAM)nInterval);
+		if (!fMarqueeMode) {
+			pProgressCtrl->ModifyStyle(PBS_MARQUEE, 0);
+			pProgressCtrl->SetRange32(0, 100);
+			pProgressCtrl->SetPos(0);
+		}
+		else {
+			pProgressCtrl->ModifyStyle(0, PBS_MARQUEE);
+		}
+	}
+}
+
+void CMsgDlg::BeginThread(AFX_THREADPROC pfnThreadProc)
+{
+	CWinThread* pThread = AfxBeginThread(pfnThreadProc, (LPVOID)this,
+		THREAD_PRIORITY_NORMAL, 0, DEBUG_PROCESS);
+}
+
+void CMsgDlg::DelayClose(int nDelay)
+{
+	SetTimer(1, nDelay, NULL);
+}
+
+void CMsgDlg::ShowCloseButton(BOOL bVisible)
+{
+	if (::IsWindow(m_hWnd) && GetDlgItem(IDCANCEL) != NULL) {
+		GetDlgItem(IDCANCEL)->ShowWindow(bVisible ? SW_SHOW : SW_HIDE);
+	}
+}
+
+BOOL CMsgDlg::OnInitDialog()
+{
+	CDialogEx::OnInitDialog();
+
+	SetWindowText(m_strTitle);
+	SetDlgItemText(IDC_LABEL_TITLE, m_strTitle);
+	SetDlgItemText(IDC_LABEL_MSG, m_strMessage);
+
+
+	// 瀛椾綋
+	HFONT hFontDefault = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
+	CFont* pFont = CFont::FromHandle(hFontDefault);
+	LOGFONT lf;
+	pFont->GetLogFont(&lf);
+	lf.lfHeight -= 12;
+	lf.lfWeight = FW_SEMIBOLD;
+	m_fontTitle.CreateFontIndirect(&lf);
+	GetDlgItem(IDC_LABEL_TITLE)->SetFont(&m_fontTitle);
+
+	pFont->GetLogFont(&lf);
+	lf.lfHeight -= 2;
+	m_fontMsg.CreateFontIndirect(&lf);
+	GetDlgItem(IDC_LABEL_MSG)->SetFont(&m_fontMsg);
+
+
+	// 鍥炬爣
+	UpdateIcon();
+	SetMarquee(TRUE, 1);
+	MoveWindow(0, 0, 320, 268);
+	CenterWindow();
+	Resize();
+
+
+	return TRUE;  // return TRUE unless you set the focus to a control
+				  // 寮傚父: OCX 灞炴�ч〉搴旇繑鍥� FALSE
+}
+
+
+void CMsgDlg::OnTimer(UINT_PTR nIDEvent)
+{
+	// TODO: 鍦ㄦ娣诲姞娑堟伅澶勭悊绋嬪簭浠g爜鍜�/鎴栬皟鐢ㄩ粯璁ゅ��
+	if (nIDEvent == 1) {
+		KillTimer(1);
+		PostMessage(WM_CLOSE);
+	}
+
+	CDialogEx::OnTimer(nIDEvent);
+}
+
+
+BOOL CMsgDlg::PreTranslateMessage(MSG* pMsg)
+{
+	// TODO: 鍦ㄦ娣诲姞涓撶敤浠g爜鍜�/鎴栬皟鐢ㄥ熀绫�
+	if (pMsg->message == WM_KEYDOWN) {
+		if ((pMsg->wParam == VK_RETURN) || (pMsg->wParam == VK_ESCAPE) || (pMsg->wParam == VK_SPACE)) {
+			return TRUE;
+		}
+	}
+	return CDialogEx::PreTranslateMessage(pMsg);
+}
+
+HBRUSH CMsgDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
+{
+	HBRUSH hbr = CDialogEx::OnCtlColor(pDC, pWnd, nCtlColor);
+
+	if (nCtlColor == CTLCOLOR_STATIC) {
+		pDC->SetBkColor(m_crBkgnd);
+		int nID = pWnd->GetDlgCtrlID();
+		if (nID == IDC_LABEL_TITLE) {
+			pDC->SetTextColor(CR_MSGBOX_TITLE);
+		}
+		else if (nID == IDC_LABEL_MSG) {
+			pDC->SetTextColor(CR_MSGBOX_MESSAGE);
+		}
+	}
+
+	return m_brBkgnd;
+}
+
+void CMsgDlg::OnSize(UINT nType, int cx, int cy)
+{
+	CDialogEx::OnSize(nType, cx, cy);
+	if (GetDlgItem(IDC_LABEL_TITLE) == nullptr) return;
+	Resize();
+}
+
+void CMsgDlg::Resize()
+{
+	int x = 28;
+	int y = 28;
+	CWnd* pItem;
+	CRect rcClient, rcIcon, rcItem;
+	GetClientRect(&rcClient);
+
+	pItem = GetDlgItem(IDC_ICON_MAIN);
+	pItem->GetWindowRect(&rcIcon);
+	pItem->MoveWindow(x, y, rcIcon.Width(), rcIcon.Height());
+	x += rcIcon.Width();
+	x += 12;
+
+	// title
+	pItem->GetWindowRect(&rcIcon);
+	ScreenToClient(&rcIcon);
+	pItem = GetDlgItem(IDC_LABEL_TITLE);
+	pItem->GetWindowRect(&rcItem);
+	pItem->MoveWindow(x, rcIcon.top + rcIcon.Height() / 2  - rcItem.Height() / 2,
+		rcClient.Width() - 24 - x, rcItem.Height());
+	x = rcIcon.left;
+	y += rcIcon.Height();
+	y += 18;
+
+	// msg
+	pItem = GetDlgItem(IDC_LABEL_MSG);
+	pItem->GetClientRect(&rcItem);
+	pItem->MoveWindow(x, y, rcClient.Width() - 24 - x, rcItem.Height());
+
+
+	y = rcClient.bottom - 12;
+	pItem = GetDlgItem(IDC_PROGRESS1);
+	pItem->GetClientRect(&rcItem);
+	pItem->MoveWindow(12, y - rcItem.Height(), rcClient.Width() - 24, rcItem.Height());
+}
\ No newline at end of file
diff --git a/SourceCode/Bond/Servo/MsgDlg.h b/SourceCode/Bond/Servo/MsgDlg.h
new file mode 100644
index 0000000..d9f08d9
--- /dev/null
+++ b/SourceCode/Bond/Servo/MsgDlg.h
@@ -0,0 +1,72 @@
+锘�#pragma once
+
+
+// CMsgDlg 瀵硅瘽妗�
+
+#define MSG_BOX_TIP			0x00
+#define MSG_BOX_QUESTION	0x01
+#define MSG_BOX_WARNING		0x02
+#define MSG_BOX_ERROR		0x03
+#define MSG_BOX_SUCCEED		0x04
+
+class CMsgDlg : public CDialogEx
+{
+	DECLARE_DYNAMIC(CMsgDlg)
+
+public:
+	CMsgDlg(CWnd* pParent = nullptr);   // 鏍囧噯鏋勯�犲嚱鏁�
+	CMsgDlg(CString strTitle, CString strMessage);
+	CMsgDlg(int nIcon, CString strTitle, CString strMessage);
+	virtual ~CMsgDlg();
+
+
+public:
+	void BeginThread(AFX_THREADPROC pfnThreadProc);
+	void SetIcon(int nIcon);
+	void SetTitle(CString strTitle);
+	void SetMessage(CString strMessage);
+	void DelayClose(int nDelay);
+	void SetMarquee(_In_ BOOL fMarqueeMode, _In_ int nInterval);
+	void ShowCloseButton(BOOL bVisible);
+	void SetCompleteCode(int code);
+	int GetCompleteCode();
+	void SetData(DWORD_PTR dwData);
+	DWORD_PTR GetData();
+	void SetDataEx(DWORD_PTR dwData);
+	DWORD_PTR GetDataEx();
+
+private:
+	void Resize();
+	void UpdateIcon();
+
+private:
+	COLORREF m_crBkgnd;
+	CBrush m_brBkgnd;
+	int m_nIcon;
+	CString m_strTitle;
+	CString m_strMessage;
+	COLORREF m_crTitle;
+	COLORREF m_crMessage;
+	CFont m_fontTitle;
+	CFont m_fontMsg;
+	int m_nCompleteCode;
+	DWORD_PTR m_dwData;
+	DWORD_PTR m_dwDataEx;
+
+
+// 瀵硅瘽妗嗘暟鎹�
+#ifdef AFX_DESIGN_TIME
+	enum { IDD = IDD_DIALOG_MSG };
+#endif
+
+protected:
+	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 鏀寔
+
+	DECLARE_MESSAGE_MAP()
+public:
+	virtual BOOL OnInitDialog();
+	afx_msg void OnTimer(UINT_PTR nIDEvent);
+	virtual BOOL PreTranslateMessage(MSG* pMsg);
+	afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor);
+	afx_msg void OnSize(UINT nType, int cx, int cy);
+};
diff --git a/SourceCode/Bond/Servo/Servo.rc b/SourceCode/Bond/Servo/Servo.rc
index b5e2fdf..7bdf825 100644
--- a/SourceCode/Bond/Servo/Servo.rc
+++ b/SourceCode/Bond/Servo/Servo.rc
Binary files differ
diff --git a/SourceCode/Bond/Servo/Servo.vcxproj b/SourceCode/Bond/Servo/Servo.vcxproj
index d39cf16..8fac7f2 100644
--- a/SourceCode/Bond/Servo/Servo.vcxproj
+++ b/SourceCode/Bond/Servo/Servo.vcxproj
@@ -202,6 +202,10 @@
     <ClInclude Include="CGlassPool.h" />
     <ClInclude Include="CRobotCmdContainerDlg.h" />
     <ClInclude Include="CRobotCmdTestDlg.h" />
+    <ClInclude Include="CPagePortStatus.h" />
+    <ClInclude Include="CPortStatusReport.h" />
+    <ClInclude Include="JobSlotGrid.h" />
+    <ClInclude Include="MsgDlg.h" />
     <ClInclude Include="PageRecipe.h" />
     <ClInclude Include="CDoubleGlass.h" />
     <ClInclude Include="CProcessData.h" />
@@ -291,6 +295,7 @@
     <ClInclude Include="SECSRuntimeManager.h" />
     <ClInclude Include="SecsTestDlg.h" />
     <ClInclude Include="Servo.h" />
+    <ClInclude Include="ServoCommo.h" />
     <ClInclude Include="ServoDlg.h" />
     <ClInclude Include="ServoGraph.h" />
     <ClInclude Include="stdafx.h" />
@@ -304,6 +309,10 @@
     <ClCompile Include="CGlassPool.cpp" />
     <ClCompile Include="CRobotCmdContainerDlg.cpp" />
     <ClCompile Include="CRobotCmdTestDlg.cpp" />
+    <ClCompile Include="CPagePortStatus.cpp" />
+    <ClCompile Include="CPortStatusReport.cpp" />
+    <ClCompile Include="JobSlotGrid.cpp" />
+    <ClCompile Include="MsgDlg.cpp" />
     <ClCompile Include="PageRecipe.cpp" />
     <ClCompile Include="CDoubleGlass.cpp" />
     <ClCompile Include="CProcessData.cpp" />
diff --git a/SourceCode/Bond/Servo/Servo.vcxproj.filters b/SourceCode/Bond/Servo/Servo.vcxproj.filters
index 76d5897..68273f0 100644
--- a/SourceCode/Bond/Servo/Servo.vcxproj.filters
+++ b/SourceCode/Bond/Servo/Servo.vcxproj.filters
@@ -108,6 +108,10 @@
     <ClCompile Include="PageRobotCmd.cpp" />
     <ClCompile Include="CRobotCmdContainerDlg.cpp" />
     <ClCompile Include="CRobotCmdTestDlg.cpp" />
+    <ClCompile Include="CPortStatusReport.cpp" />
+    <ClCompile Include="MsgDlg.cpp" />
+    <ClCompile Include="CPagePortStatus.cpp" />
+    <ClCompile Include="JobSlotGrid.cpp" />
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="AlarmManager.h" />
@@ -214,6 +218,11 @@
     <ClInclude Include="PageRobotCmd.h" />
     <ClInclude Include="CRobotCmdContainerDlg.h" />
     <ClInclude Include="CRobotCmdTestDlg.h" />
+    <ClInclude Include="CPortStatusReport.h" />
+    <ClInclude Include="MsgDlg.h" />
+    <ClInclude Include="CPagePortStatus.h" />
+    <ClInclude Include="ServoCommo.h" />
+    <ClInclude Include="JobSlotGrid.h" />
   </ItemGroup>
   <ItemGroup>
     <ResourceCompile Include="Servo.rc" />
diff --git a/SourceCode/Bond/Servo/ServoCommo.h b/SourceCode/Bond/Servo/ServoCommo.h
new file mode 100644
index 0000000..959a8a1
--- /dev/null
+++ b/SourceCode/Bond/Servo/ServoCommo.h
@@ -0,0 +1,37 @@
+#pragma once
+
+
+namespace SERVO {
+	enum PortType {
+		Loading = 1,
+		Unloading,
+		Both,
+		Buffer,
+		LoaderInBuffer,
+		UnloaderInBuffer,
+		UnloadingPartial
+	};
+
+	enum PortMode {
+		OutOfService = 0,
+		TransferBlocked,
+		ReadyToLoad,
+		ReadyToUnload,
+		InService,
+		TransferReady
+	};
+
+	enum MaterialsType {
+		G1 = 0,
+		G2 = 1,
+		G1G2 = 2
+	};
+	typedef MaterialsType CassetteType;
+
+	enum TransferMode {
+		MGVMode = 1,
+		AGVMode,
+		StockerInlineMode
+	};
+}
+
diff --git a/SourceCode/Bond/Servo/resource.h b/SourceCode/Bond/Servo/resource.h
index 1aa8644..3b75c47 100644
--- a/SourceCode/Bond/Servo/resource.h
+++ b/SourceCode/Bond/Servo/resource.h
Binary files differ
diff --git a/SourceCode/Bond/x64/Debug/EqsGraph.ini b/SourceCode/Bond/x64/Debug/EqsGraph.ini
new file mode 100644
index 0000000..9b63e87
--- /dev/null
+++ b/SourceCode/Bond/x64/Debug/EqsGraph.ini
@@ -0,0 +1,51 @@
+[LoadPort 1]
+Left=23
+Top=88
+[LoadPort 2]
+Left=23
+Top=437
+[LoadPort 3]
+Left=1253
+Top=297
+[LoadPort 4]
+Left=1253
+Top=457
+[EFEM(ROBOT)]
+Left=294
+Top=63
+[Bonder 1]
+Left=659
+Top=297
+[Bonder 2]
+Left=659
+Top=437
+[Fliper]
+Left=279
+Top=297
+[Aligner]
+Left=446
+Top=363
+[VacuumBake]
+Left=279
+Top=437
+[BakeCooling]
+Left=853
+Top=363
+[ARM]
+Left=628
+Top=63
+[Arm Tray1]
+Left=467
+Top=63
+[Arm Tray2]
+Left=467
+Top=166
+[Fliper(G2)]
+Left=238
+Top=251
+[VacuumBake(G1)]
+Left=238
+Top=386
+[Measurement]
+Left=1041
+Top=363
diff --git a/SourceCode/Bond/x64/Debug/Master.dat b/SourceCode/Bond/x64/Debug/Master.dat
new file mode 100644
index 0000000..86656a2
--- /dev/null
+++ b/SourceCode/Bond/x64/Debug/Master.dat
Binary files differ
diff --git a/SourceCode/Bond/x64/Debug/Res/msgbox_error.ico b/SourceCode/Bond/x64/Debug/Res/msgbox_error.ico
new file mode 100644
index 0000000..91d0c14
--- /dev/null
+++ b/SourceCode/Bond/x64/Debug/Res/msgbox_error.ico
Binary files differ
diff --git a/SourceCode/Bond/x64/Debug/Res/msgbox_question.ico b/SourceCode/Bond/x64/Debug/Res/msgbox_question.ico
new file mode 100644
index 0000000..fd55f81
--- /dev/null
+++ b/SourceCode/Bond/x64/Debug/Res/msgbox_question.ico
Binary files differ
diff --git a/SourceCode/Bond/x64/Debug/Res/msgbox_succeed.ico b/SourceCode/Bond/x64/Debug/Res/msgbox_succeed.ico
new file mode 100644
index 0000000..60bea0a
--- /dev/null
+++ b/SourceCode/Bond/x64/Debug/Res/msgbox_succeed.ico
Binary files differ
diff --git a/SourceCode/Bond/x64/Debug/Res/msgbox_tip.ico b/SourceCode/Bond/x64/Debug/Res/msgbox_tip.ico
new file mode 100644
index 0000000..190c14b
--- /dev/null
+++ b/SourceCode/Bond/x64/Debug/Res/msgbox_tip.ico
Binary files differ
diff --git a/SourceCode/Bond/x64/Debug/Res/msgbox_warning.ico b/SourceCode/Bond/x64/Debug/Res/msgbox_warning.ico
new file mode 100644
index 0000000..20d21ad
--- /dev/null
+++ b/SourceCode/Bond/x64/Debug/Res/msgbox_warning.ico
Binary files differ
diff --git a/SourceCode/Bond/x64/Debug/Servo.ini b/SourceCode/Bond/x64/Debug/Servo.ini
new file mode 100644
index 0000000..7a7bf01
--- /dev/null
+++ b/SourceCode/Bond/x64/Debug/Servo.ini
@@ -0,0 +1,4 @@
+[App]
+MasterPanelWidth=245
+AttributesPanelWidth=306
+EquipmentPanelWidth=277

--
Gitblit v1.9.3