From 3c387cc7bcd469938fbfac8bc5435bb1e846c70f Mon Sep 17 00:00:00 2001
From: LAPTOP-SNT8I5JK\Boounion <Chenluhua@qq.com>
Date: 星期二, 17 六月 2025 17:42:53 +0800
Subject: [PATCH] Merge branch 'liuyang' into clh

---
 SourceCode/Bond/Servo/CVacuumBake.cpp      |  295 ++++++++++++
 SourceCode/Bond/Servo/TransferManager.h    |   17 
 SourceCode/Bond/Servo/CRobotCmdTestDlg.cpp |  198 ++++++-
 SourceCode/Bond/Servo/Model.cpp            |    2 
 SourceCode/Bond/Servo/CLoadPort.cpp        |   56 ++
 SourceCode/Bond/Servo/CMeasurement.h       |    2 
 SourceCode/Bond/Servo/CVacuumBake.h        |    1 
 SourceCode/Bond/Servo/TransferManager.cpp  |   90 +--
 SourceCode/Bond/Servo/CPageGraph1.cpp      |   12 
 SourceCode/Bond/Servo/CRobotCmdTestDlg.h   |    7 
 SourceCode/Bond/Servo/CBakeCooling.cpp     |  295 ++++++++++++
 SourceCode/Bond/Servo/CMeasurement.cpp     |  295 ++++++++++++
 SourceCode/Bond/Servo/CBakeCooling.h       |    1 
 SourceCode/Bond/Servo/CEquipment.cpp       |    4 
 SourceCode/Bond/Servo/CEFEM.cpp            |   66 --
 SourceCode/Bond/Servo/CMaster.cpp          |   19 
 SourceCode/Bond/Servo/CBonder.cpp          |    8 
 17 files changed, 1,172 insertions(+), 196 deletions(-)

diff --git a/SourceCode/Bond/Servo/CBakeCooling.cpp b/SourceCode/Bond/Servo/CBakeCooling.cpp
index 422a81e..5387d13 100644
--- a/SourceCode/Bond/Servo/CBakeCooling.cpp
+++ b/SourceCode/Bond/Servo/CBakeCooling.cpp
@@ -38,6 +38,301 @@
 		addPin(SERVO::PinType::OUTPUT, _T("Out"));
 	}
 
+	void CBakeCooling::initSteps()
+	{
+		CEquipment::initSteps();
+
+		{
+			// eq mode
+			CEqModeStep* pStep = new CEqModeStep();
+			pStep->setName(STEP_MODE);
+			pStep->setWriteSignalDev(0x940);
+			pStep->setModeDev(0x11d7d);
+			if (addStep(STEP_ID_EQMODE_CHANGED, pStep) != 0) {
+				delete pStep;
+			}
+		}
+
+		{
+			// eq status
+			CEqStatusStep* pStep = new CEqStatusStep();
+			pStep->setName(STEP_STATUS);
+			pStep->setWriteSignalDev(0x941);
+			pStep->setStatusDev(0x11d59);
+			if (addStep(STEP_ID_EQSTATUS_CHANGED, pStep) != 0) {
+				delete pStep;
+			}
+		}
+
+		{
+			// Eq Alarm
+			static char* pszName[] = { STEP_ALARM_BLOCK1, STEP_ALARM_BLOCK2, STEP_ALARM_BLOCK3, STEP_ALARM_BLOCK4, STEP_ALARM_BLOCK5 };
+			static int dev[5] = { 0x11f0e , 0x11f3b, 0x11f68, 0x11f95, 0x11fc2 };
+			static int writeSignalDev[5] = { 0x942, 0x943, 0x944, 0x945, 0x946 };
+			static int addr[] = { STEP_ID_EQALARM1, STEP_ID_EQALARM2, STEP_ID_EQALARM3, STEP_ID_EQALARM4, STEP_ID_EQALARM5 };
+
+			for (int i = 0; i < 5; i++) {
+				CEqAlarmStep* pStep = new CEqAlarmStep();
+				pStep->setName(pszName[i]);
+				pStep->setWriteSignalDev(writeSignalDev[i]);
+				pStep->setAlarmDev(dev[i]);
+				if (addStep(addr[i], pStep) != 0) {
+					delete pStep;
+				}
+			}
+
+		}
+
+		{
+			CEqReadStep* pStep = new CEqReadStep(0x12b55, 538 * 2,
+				[&](void* pFrom, int code, const char* pszData, size_t size) -> int {
+					if (code == ROK && pszData != nullptr && size > 0) {
+						decodeProcessDataReport((CStep*)pFrom, pszData, size);
+					}
+					return -1;
+				});
+			pStep->setName(STEP_PROCESS);
+			pStep->setWriteSignalDev(0x947);
+			if (addStep(STEP_ID_PROCESS_DATA_REPORT, pStep) != 0) {
+				delete pStep;
+			}
+		}
+
+		{
+			// eq cim mode change
+			CEqCimModeChangeStep* pStep = new CEqCimModeChangeStep();
+			pStep->setName(STEP_CIM_MODE_CHANGE);
+			pStep->setWriteSignalDev(0x960);
+			pStep->setCimModeDev(0x1c05);
+			if (addStep(STEP_ID_CIMMODE_CHANGED_CMD_REPLY, pStep) != 0) {
+				delete pStep;
+			}
+		}
+
+		{
+			// eq cim message cmd
+			CEqCimMessageCmdStep* pStep = new CEqCimMessageCmdStep();
+			pStep->setName(STEP_CIM_MESSAGE_CMD);
+			pStep->setWriteSignalDev(0x961);
+			pStep->setCimMessageDev(0x1bf0);
+			if (addStep(STEP_ID_CIM_MSG_SET_CMD_REPLY, pStep) != 0) {
+				delete pStep;
+			}
+		}
+
+		{
+			// eq current recipe change
+			CEqCurrentRecipeChangeStep* pStep = new CEqCurrentRecipeChangeStep();
+			pStep->setName(STEP_EQ_RURRENT_RECIPE_CHANGE);
+			pStep->setWriteSignalDev(0x948);
+			pStep->setDataDev(0x12850);
+			if (addStep(STEP_ID_CURRENT_RECIPE_CHANGE_REPORT, pStep) != 0) {
+				delete pStep;
+			}
+		}
+
+		{
+			// CIM Message Confirm
+			// 要将int32的值拆分为两个short, 分别为msg id和panel id
+			// 65538, 2为msg id, 1为panel id
+			CEqReadIntStep* pStep = new CEqReadIntStep(__INT32, 0x11d80);
+			pStep->setName(STEP_EQ_CIM_MESSAGE_CONFIRM);
+			pStep->setWriteSignalDev(0x949);
+			if (addStep(STEP_ID_CIM_MSG_CONFIRM_REPORT, pStep) != 0) {
+				delete pStep;
+			}
+		}
+
+		{
+			CEqCimMessageClearStep* pStep = new CEqCimMessageClearStep();
+			pStep->setName(STEP_CIM_MESSAGE_CLEAR);
+			pStep->setWriteSignalDev(0x962);
+			pStep->setClearCimMessageDev(0x1c03);
+			if (addStep(STEP_ID_CIM_MSG_CLEAR_CMD_REPLY, pStep) != 0) {
+				delete pStep;
+			}
+		}
+
+		{
+			CEqDateTimeSetCmdStep* pStep = new CEqDateTimeSetCmdStep();
+			pStep->setName(STEP_DATETIME_SET_CMD);
+			pStep->setWriteSignalDev(0x963);
+			pStep->setDateTimeDev(0x1c06);
+			if (addStep(STEP_ID_DATETIME_SET_CMD_REPLY, pStep) != 0) {
+				delete pStep;
+			}
+		}
+
+		{
+			CEqModeChangeStep* pStep = new CEqModeChangeStep();
+			pStep->setName(STEP_EQ_MODE_CHANGE);
+			pStep->setWriteSignalDev(0x965);
+			pStep->setEqModeDev(0x1c0e);
+			if (addStep(STEP_ID_EQMODE_CHANGE_CMD_REPLY, pStep) != 0) {
+				delete pStep;
+			}
+		}
+
+		{
+			// 请求主配方列表的step
+			CEqWriteStep* pStep = new CEqWriteStep();
+			pStep->setName(STEP_EQ_MASTER_RECIPE_LIST_REQ);
+			pStep->setWriteSignalDev(0x966);
+			pStep->setDataDev(0x24fa);
+			if (addStep(STEP_ID_MASTER_RECIPE_LIST_CMD_REPLY, pStep) != 0) {
+				delete pStep;
+			}
+		}
+
+		{
+			// master recipe list report
+			CEqReadStep* pStep = new CEqReadStep(0x12955, 255 * 2,
+				[&](void* pFrom, int code, const char* pszData, size_t size) -> int {
+					if (code == ROK && pszData != nullptr && size > 0) {
+						// 此处解释配方数据
+						short ret = decodeRecipeListReport(pszData, size);
+						pStep->setReturnCode(ret);
+					}
+					pStep->setReturnCode(MRLRC_OK);
+					return -1;
+				});
+			pStep->setName(STEP_EQ_MASTER_RECIPE_LIST);
+			pStep->setWriteSignalDev(0x94b);
+			pStep->setReturnDev(0x37ad);
+			if (addStep(STEP_ID_MASTER_RECIPE_LIST_REPORT, pStep) != 0) {
+				delete pStep;
+			}
+		}
+
+		{
+			// 请求配方参数
+			//CEqWriteStep* pStep = new CEqWriteStep();
+			//pStep->setName(STEP_EQ_RECIPE_PARAMETER_REQ);
+			//pStep->setWriteSignalDev(0x967);
+			//pStep->setDataDev(0x379b);
+			//if (addStep(STEP_ID_RECIPE_PARAMETER_CMD_REPLY, pStep) != 0) {
+			//	delete pStep;
+			//}
+		}
+
+		{
+			// recipe parameter report
+			//CEqReadStep* pStep = new CEqReadStep(0x1aa54, 257 * 2,
+			//	[&](void* pFrom, int code, const char* pszData, size_t size) -> int {
+			//		if (code == ROK && pszData != nullptr && size > 0) {
+			//			// 此处解释配方数据
+			//			short ret = decodeRecipeParameterReport(pszData, size);
+			//			pStep->setReturnCode(ret);
+			//		}
+			//		pStep->setReturnCode(MRLRC_OK);
+			//		return -1;
+			//	});
+			//pStep->setName(STEP_EQ_RECIPE_PARAMETER);
+			//pStep->setWriteSignalDev(0x94c);
+			//pStep->setReturnDev(m_nIndex == 0 ? 0x126c : 0x1bbc);
+			//if (addStep(STEP_ID_RECIPE_PARAMETER_REPORT, pStep) != 0) {
+			//	delete pStep;
+			//}
+		}
+
+		// 使用CEqReadStep替换CEqJobEventStep
+		{
+			// Received Job Report Upstream #1~9
+			char szBuffer[256];
+			for (int i = 0; i < 1; i++) {
+				CEqReadStep* pStep = new CEqReadStep(0x10c90 + 320 * i, 320 * 2,
+					[&](void* pFrom, int code, const char* pszData, size_t size) -> int {
+						if (code == ROK && pszData != nullptr && size > 0) {
+							int port = (int)(__int64)((CEqReadStep*)pFrom)->getProp("Port");
+							if (port > 0) {
+								decodeReceivedJobReport((CStep*)pFrom, port, pszData, size);
+							}
+						}
+						return -1;
+					});
+				sprintf_s(szBuffer, "%s%d", STEP_EQ_RECEIVED_JOB_UPSn, i + 1);
+				pStep->setName(szBuffer);
+				pStep->setProp("Port", (void*)(__int64)(i + 1));
+				pStep->setWriteSignalDev(0x900 + i);
+				if (addStep(STEP_ID_RECIVE_JOB_UPS1 + i, pStep) != 0) {
+					delete pStep;
+				}
+			}
+		}
+
+		{
+			// Sent Out Job Report Downstream #1~9
+			char szBuffer[256];
+			for (int i = 0; i < 1; i++) {
+				CEqReadStep* pStep = new CEqReadStep(0x10000 + 320 * i, 320 * 2,
+					[&](void* pFrom, int code, const char* pszData, size_t size) -> int {
+						if (code == ROK && pszData != nullptr && size > 0) {
+							int port = (int)(__int64)((CEqReadStep*)pFrom)->getProp("Port");
+							if (port > 0) {
+								decodeReceivedJobReport((CStep*)pFrom, port, pszData, size);
+							}
+						}
+						return -1;
+					});
+				sprintf_s(szBuffer, "%s%d", STEP_EQ_SENT_OUT_JOB_DOWNSn, i + 1);
+				pStep->setName(szBuffer);
+				pStep->setProp("Port", (void*)(__int64)(i + 1));
+				pStep->setWriteSignalDev(0x90a + i);
+				if (addStep(STEP_ID_SENT_OUT_JOB_DOWNS1 + i, pStep) != 0) {
+					delete pStep;
+				}
+			}
+		}
+
+		{
+			// Fetched Out Job Report #1~15
+			char szBuffer[256];
+			for (int i = 0; i < 1; i++) {
+				CEqReadStep* pStep = new CEqReadStep(0x11c31 + 18 * i, 18 * 2,
+					[&](void* pFrom, int code, const char* pszData, size_t size) -> int {
+						if (code == ROK && pszData != nullptr && size > 0) {
+							int port = (int)(__int64)((CEqReadStep*)pFrom)->getProp("Port");
+							if (port > 0) {
+								decodeFetchedOutJobReport((CStep*)pFrom, port, pszData, size);
+							}
+						}
+						return -1;
+					});
+				sprintf_s(szBuffer, "%s%d", STEP_EQ_FETCHED_OUT_JOBn, i + 1);
+				pStep->setName(szBuffer);
+				pStep->setProp("Port", (void*)(__int64)(i + 1));
+				pStep->setWriteSignalDev(0x923 + i);
+				if (addStep(STEP_ID_FETCHED_OUT_JOB_REPORT1 + i, pStep) != 0) {
+					delete pStep;
+				}
+			}
+		}
+
+		{
+			// Stored Job Report #1~15
+			char szBuffer[256];
+			for (int i = 0; i < 1; i++) {
+				CEqReadStep* pStep = new CEqReadStep(0x11b23 + 18 * i, 18 * 2,
+					[&](void* pFrom, int code, const char* pszData, size_t size) -> int {
+						if (code == ROK && pszData != nullptr && size > 0) {
+							int port = (int)(__int64)((CEqReadStep*)pFrom)->getProp("Port");
+							if (port > 0) {
+								decodeStoredJobReport((CStep*)pFrom, port, pszData, size);
+							}
+						}
+						return -1;
+					});
+				sprintf_s(szBuffer, "%s%d", STEP_EQ_STORED_JOBn, i + 1);
+				pStep->setName(szBuffer);
+				pStep->setProp("Port", (void*)(__int64)(i + 1));
+				pStep->setWriteSignalDev(0x914 + i);
+				if (addStep(STEP_ID_STORE_JOB_REPORT1 + i, pStep) != 0) {
+					delete pStep;
+				}
+			}
+		}
+	}
+
 	// 必须要实现的虚函数,在此初始化Slot信息
 	void CBakeCooling::initSlots()
 	{
diff --git a/SourceCode/Bond/Servo/CBakeCooling.h b/SourceCode/Bond/Servo/CBakeCooling.h
index 5982b84..3b2a746 100644
--- a/SourceCode/Bond/Servo/CBakeCooling.h
+++ b/SourceCode/Bond/Servo/CBakeCooling.h
@@ -15,6 +15,7 @@
         virtual void init();
         virtual void term();
         virtual void initPins();
+        virtual void initSteps();
         virtual void initSlots();
         virtual void onTimer(UINT nTimerid);
         virtual void serialize(CArchive& ar);
diff --git a/SourceCode/Bond/Servo/CBonder.cpp b/SourceCode/Bond/Servo/CBonder.cpp
index 75021f0..51c064b 100644
--- a/SourceCode/Bond/Servo/CBonder.cpp
+++ b/SourceCode/Bond/Servo/CBonder.cpp
@@ -244,7 +244,7 @@
 		{
 			// Received Job Report Upstream #1~9
 			char szBuffer[256];
-			for (int i = 0; i < 9; i++) {
+			for (int i = 0; i < 1; i++) {
 				CEqReadStep* pStep = new CEqReadStep((m_nIndex == 0 ? 0x8c90 : 0xcc90) + 320 * i, 320 * 2,
 					[&](void* pFrom, int code, const char* pszData, size_t size) -> int {
 						if (code == ROK && pszData != nullptr && size > 0) {
@@ -267,7 +267,7 @@
 		{
 			// Sent Out Job Report Downstream #1~9
 			char szBuffer[256];
-			for (int i = 0; i < 9; i++) {
+			for (int i = 0; i < 1; i++) {
 				CEqReadStep* pStep = new CEqReadStep((m_nIndex == 0 ? 0x8000 : 0xc000) + 320 * i, 320 * 2,
 					[&](void* pFrom, int code, const char* pszData, size_t size) -> int {
 						if (code == ROK && pszData != nullptr && size > 0) {
@@ -291,7 +291,7 @@
 		{
 			// Fetched Out Job Report #1~15
 			char szBuffer[256];
-			for (int i = 0; i < 15; i++) {
+			for (int i = 0; i < 1; i++) {
 				CEqReadStep* pStep = new CEqReadStep((m_nIndex == 0 ? 0x9c31 : 0xdc31) + 18 * i, 18 * 2,
 					[&](void* pFrom, int code, const char* pszData, size_t size) -> int {
 						if (code == ROK && pszData != nullptr && size > 0) {
@@ -315,7 +315,7 @@
 		{
 			// Stored Job Report #1~15
 			char szBuffer[256];
-			for (int i = 0; i < 15; i++) {
+			for (int i = 0; i < 1; i++) {
 				CEqReadStep* pStep = new CEqReadStep((m_nIndex == 0 ? 0x9b23 : 0xdb23) + 18 * i, 18 * 2,
 					[&](void* pFrom, int code, const char* pszData, size_t size) -> int {
 						if (code == ROK && pszData != nullptr && size > 0) {
diff --git a/SourceCode/Bond/Servo/CEFEM.cpp b/SourceCode/Bond/Servo/CEFEM.cpp
index ff4581d..dd297b1 100644
--- a/SourceCode/Bond/Servo/CEFEM.cpp
+++ b/SourceCode/Bond/Servo/CEFEM.cpp
@@ -22,7 +22,7 @@
 		m_pPort[3] = nullptr;
 		m_pAligner = nullptr;
 		m_pFliper = nullptr;
-		m_robotData.status = ROBOT_STATUS::Idle;
+		m_robotData.status = ROBOT_STATUS::Setup;
 		m_robotData.position = ROBOT_POSITION::Port1;
 		m_robotData.armState[0] = FALSE;
 		m_robotData.armState[1] = FALSE;
@@ -366,7 +366,7 @@
 			// Eq mode
 			CEqModeStep* pStep = new CEqModeStep();
 			pStep->setName(STEP_MODE);
-			pStep->setWriteSignalDev(0x50);
+			pStep->setWriteSignalDev(0x40);
 			pStep->setModeDev(0x5d7d);
 			if (addStep(STEP_ID_EQMODE_CHANGED, pStep) != 0) {
 				delete pStep;
@@ -377,7 +377,7 @@
 			// Eq Status
 			CEqStatusStep* pStep = new CEqStatusStep();
 			pStep->setName(STEP_STATUS);
-			pStep->setWriteSignalDev(0x51);
+			pStep->setWriteSignalDev(0x41);
 			pStep->setStatusDev(0x5d59);
 			if (addStep(STEP_ID_EQSTATUS_CHANGED, pStep) != 0) {
 				delete pStep;
@@ -388,7 +388,7 @@
 			// Eq Alarm
 			static char* pszName[] = { STEP_ALARM_BLOCK1, STEP_ALARM_BLOCK2, STEP_ALARM_BLOCK3, STEP_ALARM_BLOCK4, STEP_ALARM_BLOCK5 };
 			static int dev[] = { 0x5f0e , 0x5f3b, 0x5f68, 0x5f95, 0x5fc2 };
-			static int writeSignalDev[] = { 0x52, 0x53, 0x54, 0x55, 0x56 };
+			static int writeSignalDev[] = { 0x42, 0x43, 0x44, 0x45, 0x46 };
 			static int addr[] = { STEP_ID_EQALARM1, STEP_ID_EQALARM2, STEP_ID_EQALARM3, STEP_ID_EQALARM4, STEP_ID_EQALARM5 };
 
 			for (int i = 0; i < 5; i++) {
@@ -407,7 +407,7 @@
 			// eq process
 			CEqProcessStep* pStep = new CEqProcessStep();
 			pStep->setName(STEP_PROCESS);
-			pStep->setWriteSignalDev(0x57);
+			pStep->setWriteSignalDev(0x47);
 			pStep->setProcessDev(0x6b55);
 			if (addStep(STEP_ID_PROCESS_DATA_REPORT, pStep) != 0) {
 				delete pStep;
@@ -439,7 +439,7 @@
 
 		{
 			// CIM Message Confirm
-			CEqReadIntStep* pStep = new CEqReadIntStep(__INT32, 0x5f80);
+			CEqReadIntStep* pStep = new CEqReadIntStep(__INT32, 0x5d80);
 			pStep->setName(STEP_EQ_CIM_MESSAGE_CONFIRM);
 			pStep->setWriteSignalDev(0x49);
 			if (addStep(STEP_ID_CIM_MSG_CONFIRM_REPORT, pStep) != 0) {
@@ -502,7 +502,7 @@
 			// eq mode change
 			CEqModeChangeStep* pStep = new CEqModeChangeStep();
 			pStep->setName(STEP_EQ_MODE_CHANGE);
-			pStep->setWriteSignalDev(0x65);
+			pStep->setWriteSignalDev(0x40);
 			pStep->setEqModeDev(0x1E);
 			if (addStep(STEP_ID_EQMODE_CHANGE_CMD_REPLY, pStep) != 0) {
 				delete pStep;
@@ -549,55 +549,7 @@
 				pStep->setName(szBuffer);
 				pStep->setProp("Upstream", (void*)(__int64)(i + 1));
 				pStep->setWriteSignalDev(0x0 + i);
-				if (addStep(STEP_ID_FETCHED_OUT_JOB_REPORT1 + i, pStep) != 0) {
-					delete pStep;
-				}
-			}
-		}
-
-		{
-			// Fetched Out Job Report #1~15
-			char szBuffer[256];
-			for (int i = 0; i < 15; i++) {
-				CEqReadStep* pStep = new CEqReadStep(0x5c31 + 18 * i, 18 * 2,
-					[&](void* pFrom, int code, const char* pszData, size_t size) -> int {
-						if (code == ROK && pszData != nullptr && size > 0) {
-							int port = (int)(__int64)((CEqReadStep*)pFrom)->getProp("Port");
-							if (port > 0) {
-								decodeFetchedOutJobReport((CStep*)pFrom, port, pszData, size);
-							}
-						}
-						return -1;
-					});
-				sprintf_s(szBuffer, "%s%d", STEP_EQ_FETCHED_OUT_JOBn, i+1);
-				pStep->setName(szBuffer);
-				pStep->setProp("Port", (void*)(__int64)(i + 1));
-				pStep->setWriteSignalDev(0x023 + i);
-				if (addStep(STEP_ID_FETCHED_OUT_JOB_REPORT1 + i, pStep) != 0) {
-					delete pStep;
-				}
-			}
-		}
-
-		{
-			// Store Job Report #1~15
-			char szBuffer[256];
-			for (int i = 0; i < 15; i++) {
-				CEqReadStep* pStep = new CEqReadStep(0x5b23 + 18 * i, 18 * 2,
-					[&](void* pFrom, int code, const char* pszData, size_t size) -> int {
-						if (code == ROK && pszData != nullptr && size > 0) {
-							int port = (int)(__int64)((CEqReadStep*)pFrom)->getProp("Port");
-							if (port > 0) {
-								decodeStoredJobReport((CStep*)pFrom, port, pszData, size);
-							}
-						}
-						return -1;
-					});
-				sprintf_s(szBuffer, "%s%d", STEP_EQ_STORED_JOBn, i + 1);
-				pStep->setName(szBuffer);
-				pStep->setProp("Port", (void*)(__int64)(i + 1));
-				pStep->setWriteSignalDev(0x014 + i);
-				if (addStep(STEP_ID_STORE_JOB_REPORT1 + i, pStep) != 0) {
+				if (addStep(STEP_ID_RECIVE_JOB_UPS1 + i, pStep) != 0) {
 					delete pStep;
 				}
 			}
@@ -619,7 +571,7 @@
 			CEqWriteStep* pStep = new CEqWriteStep();
 			pStep->setName(STEP_EFEM_ROBOT_CMD);
 			pStep->setWriteSignalDev(0x14D);
-			pStep->setDataDev(0x90a);
+			pStep->setDataDev(0x5c7);
 			if (addStep(STEP_ID_ROBOT_CMD_REPLY, pStep) != 0) {
 				delete pStep;
 			}
diff --git a/SourceCode/Bond/Servo/CEquipment.cpp b/SourceCode/Bond/Servo/CEquipment.cpp
index d8f61fa..d380f13 100644
--- a/SourceCode/Bond/Servo/CEquipment.cpp
+++ b/SourceCode/Bond/Servo/CEquipment.cpp
@@ -575,6 +575,10 @@
 		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);
+
+		// robot cmd reply
+		CHECK_WRITE_STEP_SIGNAL(STEP_ID_ROBOT_CMD_REPLY, pszData, size);
+		
 	}
 
 	BOOL CEquipment::isBitOn(const char* pszData, size_t size, int index)
diff --git a/SourceCode/Bond/Servo/CLoadPort.cpp b/SourceCode/Bond/Servo/CLoadPort.cpp
index fc3f5c5..81361bc 100644
--- a/SourceCode/Bond/Servo/CLoadPort.cpp
+++ b/SourceCode/Bond/Servo/CLoadPort.cpp
@@ -92,7 +92,7 @@
 			// Type
 			static char* pszName[] = { STEP_EQ_PORT1_TYPE, STEP_EQ_PORT2_TYPE, STEP_EQ_PORT3_TYPE, STEP_EQ_PORT4_TYPE };
 			static int dev[] = { 0x6010 , 0x6020, 0x6030, 0x6040 };
-			static int writeSignalDev[] = { 0xa0, 0xa1, 0xa2, 0xa3 };
+			static int writeSignalDev[] = { 0x90, 0x91, 0x92, 0x93 };
 			static int addr[] = { STEP_ID_PORT1_TYPE_CHANGE, STEP_ID_PORT2_TYPE_CHANGE, STEP_ID_PORT3_TYPE_CHANGE, STEP_ID_PORT4_TYPE_CHANGE };
 
 			CEqReadStep* pStep = new CEqReadStep(dev[m_nIndex], sizeof(short),
@@ -113,7 +113,7 @@
 			// Mode
 			static char* pszName[] = { STEP_EQ_PORT1_MODE, STEP_EQ_PORT2_MODE, STEP_EQ_PORT3_MODE, STEP_EQ_PORT4_MODE };
 			static int dev[] = { 0x6011, 0x6021, 0x6031, 0x6041 };
-			static int writeSignalDev[] = { 0xa8, 0xa9, 0xaa, 0xab };
+			static int writeSignalDev[] = { 0x98, 0x99, 0x9a, 0x9b };
 			static int addr[] = { STEP_ID_PORT1_MODE_CHANGE, STEP_ID_PORT2_MODE_CHANGE, STEP_ID_PORT3_MODE_CHANGE, STEP_ID_PORT4_MODE_CHANGE };
 
 			CEqReadStep* pStep = new CEqReadStep(dev[m_nIndex], sizeof(short),
@@ -134,7 +134,7 @@
 			// Cassette type
 			static char* pszName[] = { STEP_EQ_PORT1_CASSETTE_TYPE, STEP_EQ_PORT2_CASSETTE_TYPE, STEP_EQ_PORT3_CASSETTE_TYPE, STEP_EQ_PORT4_CASSETTE_TYPE };
 			static int dev[] = { 0x6012, 0x6022, 0x6032, 0x6042 };
-			static int writeSignalDev[] = { 0xb0, 0xb1, 0xb2, 0xb3 };
+			static int writeSignalDev[] = { 0xa0, 0xa1, 0xa2, 0xa3 };
 			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 };
 
 			CEqReadStep* pStep = new CEqReadStep(dev[m_nIndex], sizeof(short),
@@ -155,7 +155,7 @@
 			// Transfer type
 			static char* pszName[] = { STEP_EQ_PORT1_TRANSFER_MODE, STEP_EQ_PORT2_TRANSFER_MODE, STEP_EQ_PORT3_TRANSFER_MODE, STEP_EQ_PORT4_TRANSFER_MODE };
 			static int dev[] = { 0x6014, 0x6024, 0x6034, 0x6044 };
-			static int writeSignalDev[] = { 0xb8, 0xb9, 0xba, 0xbb };
+			static int writeSignalDev[] = { 0xa8, 0xa9, 0xaa, 0xab };
 			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 };
 
 			CEqReadStep* pStep = new CEqReadStep(dev[m_nIndex], sizeof(short),
@@ -176,7 +176,7 @@
 			// Port enable
 			static char* pszName[] = { STEP_EQ_PORT1_ENABLE, STEP_EQ_PORT2_ENABLE, STEP_EQ_PORT3_ENABLE, STEP_EQ_PORT4_ENABLE };
 			static int dev[] = { 0x6015, 0x6025, 0x6035, 0x6045 };
-			static int writeSignalDev[] = { 0xc0, 0xc1, 0xc2, 0xc3 };
+			static int writeSignalDev[] = { 0xb0, 0xb1, 0xb2, 0xb3 };
 			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 };
 
 			CEqReadStep* pStep = new CEqReadStep(dev[m_nIndex], sizeof(short),
@@ -345,6 +345,50 @@
 				if (addStep(addr[i][m_nIndex], pStep) != 0) {
 					delete pStep;
 				}
+			}
+		}
+		
+		{
+			// Fetched Out Job Report #1~15
+			char szBuffer[256];
+			CEqReadStep* pStep = new CEqReadStep(0x5c31 + 18 * m_nIndex, 18 * 2,
+				[&](void* pFrom, int code, const char* pszData, size_t size) -> int {
+					if (code == ROK && pszData != nullptr && size > 0) {
+						int port = (int)(__int64)((CEqReadStep*)pFrom)->getProp("Port");
+						if (port > 0) {
+							decodeFetchedOutJobReport((CStep*)pFrom, port, pszData, size);
+						}
+					}
+					return -1;
+				});
+			sprintf_s(szBuffer, "%s%d", STEP_EQ_FETCHED_OUT_JOBn, m_nIndex + 1);
+			pStep->setName(szBuffer);
+			pStep->setProp("Port", (void*)(__int64)(m_nIndex + 1));
+			pStep->setWriteSignalDev(0x023 + m_nIndex);
+			if (addStep(STEP_ID_FETCHED_OUT_JOB_REPORT1 + m_nIndex, pStep) != 0) {
+				delete pStep;
+			}
+		}
+
+		{
+			// Store Job Report #1~15
+			char szBuffer[256];
+			CEqReadStep* pStep = new CEqReadStep(0x5b23 + 18 * m_nIndex, 18 * 2,
+				[&](void* pFrom, int code, const char* pszData, size_t size) -> int {
+					if (code == ROK && pszData != nullptr && size > 0) {
+						int port = (int)(__int64)((CEqReadStep*)pFrom)->getProp("Port");
+						if (port > 0) {
+							decodeStoredJobReport((CStep*)pFrom, port, pszData, size);
+						}
+					}
+					return -1;
+				});
+			sprintf_s(szBuffer, "%s%d", STEP_EQ_STORED_JOBn, m_nIndex + 1);
+			pStep->setName(szBuffer);
+			pStep->setProp("Port", (void*)(__int64)(m_nIndex + 1));
+			pStep->setWriteSignalDev(0x014 + m_nIndex);
+			if (addStep(STEP_ID_STORE_JOB_REPORT1 + m_nIndex, pStep) != 0) {
+				delete pStep;
 			}
 		}
 	}
@@ -820,6 +864,8 @@
 
 	void CLoadPort::onReceiveLBData(const char* pszData, size_t size)
 	{
+		__super::onReceiveLBData(pszData, size);
+
 		static int type[] = { STEP_ID_PORT1_TYPE_CHANGE, STEP_ID_PORT2_TYPE_CHANGE,
 			STEP_ID_PORT3_TYPE_CHANGE, STEP_ID_PORT4_TYPE_CHANGE };
 		static int mode[] = { STEP_ID_PORT1_MODE_CHANGE, STEP_ID_PORT2_MODE_CHANGE,
diff --git a/SourceCode/Bond/Servo/CMaster.cpp b/SourceCode/Bond/Servo/CMaster.cpp
index 79aff87..a751764 100644
--- a/SourceCode/Bond/Servo/CMaster.cpp
+++ b/SourceCode/Bond/Servo/CMaster.cpp
@@ -613,16 +613,13 @@
 
 			// 读标志位
 			for (auto item : m_listEquipment) {
-				if (item->getID() == EQ_ID_Bonder1 || item->getID() == EQ_ID_Bonder2
-					|| item->getID() == EQ_ID_EFEM) {
-					const StationIdentifier& station = item->getStation();
-					MemoryBlock& block = item->getReadBitBlock();
+				const StationIdentifier& station = item->getStation();
+				MemoryBlock& block = item->getReadBitBlock();
 
-					int nRet = m_cclink.ReadData2(station, (DeviceType)block.type,
-						block.start, block.size, block.buffer);
-					if (0 == nRet) {
-						item->onReceiveLBData(block.buffer, block.size);
-					}
+				int nRet = m_cclink.ReadData2(station, (DeviceType)block.type,
+					block.start, block.size, block.buffer);
+				if (0 == nRet) {
+					item->onReceiveLBData(block.buffer, block.size);
 				}
 			}
 		}
@@ -854,7 +851,7 @@
 		pEquipment->setBaseAlarmId(BASE_ALARM_EFEM);
 		pEquipment->setName("VacuumBake(G1)");
 		pEquipment->setDescription("VacuumBake(G1).");
-		pEquipment->setReadBitBlock(0x4000, 0x45ff);
+		pEquipment->setReadBitBlock(0x5c00, 0x66ff);
 		pEquipment->setStation(0, 255);
 		addToEquipmentList(pEquipment);
 
@@ -965,7 +962,7 @@
 		pEquipment->setBaseAlarmId(BASE_ALARM_EFEM);
 		pEquipment->setName("BakeCooling");
 		pEquipment->setDescription("BakeCooling.");
-		pEquipment->setReadBitBlock(0x4000, 0x45ff);
+		pEquipment->setReadBitBlock(0x5100, 0x5bff);
 		pEquipment->setStation(0, 255);
 		addToEquipmentList(pEquipment);
 
diff --git a/SourceCode/Bond/Servo/CMeasurement.cpp b/SourceCode/Bond/Servo/CMeasurement.cpp
index 4821891..46478f0 100644
--- a/SourceCode/Bond/Servo/CMeasurement.cpp
+++ b/SourceCode/Bond/Servo/CMeasurement.cpp
@@ -38,6 +38,301 @@
 		addPin(SERVO::PinType::OUTPUT, _T("Out2"));
 	}
 
+	void CMeasurement::initSteps()
+	{
+		CEquipment::initSteps();
+
+		{
+			// eq mode
+			CEqModeStep* pStep = new CEqModeStep();
+			pStep->setName(STEP_MODE);
+			pStep->setWriteSignalDev(0xf40);
+			pStep->setModeDev(0x19d7d);
+			if (addStep(STEP_ID_EQMODE_CHANGED, pStep) != 0) {
+				delete pStep;
+			}
+		}
+
+		{
+			// eq status
+			CEqStatusStep* pStep = new CEqStatusStep();
+			pStep->setName(STEP_STATUS);
+			pStep->setWriteSignalDev(0xf41);
+			pStep->setStatusDev(0x19d59);
+			if (addStep(STEP_ID_EQSTATUS_CHANGED, pStep) != 0) {
+				delete pStep;
+			}
+		}
+
+		{
+			// Eq Alarm
+			static char* pszName[] = { STEP_ALARM_BLOCK1, STEP_ALARM_BLOCK2, STEP_ALARM_BLOCK3, STEP_ALARM_BLOCK4, STEP_ALARM_BLOCK5 };
+			static int dev[5] = { 0x19f0e , 0x19f3b, 0x19f68, 0x19f95, 0x19fc2 };
+			static int writeSignalDev[5] = { 0xf42, 0xf43, 0xf44, 0xf45, 0xf46 };
+			static int addr[] = { STEP_ID_EQALARM1, STEP_ID_EQALARM2, STEP_ID_EQALARM3, STEP_ID_EQALARM4, STEP_ID_EQALARM5 };
+
+			for (int i = 0; i < 5; i++) {
+				CEqAlarmStep* pStep = new CEqAlarmStep();
+				pStep->setName(pszName[i]);
+				pStep->setWriteSignalDev(writeSignalDev[i]);
+				pStep->setAlarmDev(dev[i]);
+				if (addStep(addr[i], pStep) != 0) {
+					delete pStep;
+				}
+			}
+
+		}
+
+		{
+			CEqReadStep* pStep = new CEqReadStep(0x1ab55, 538 * 2,
+				[&](void* pFrom, int code, const char* pszData, size_t size) -> int {
+					if (code == ROK && pszData != nullptr && size > 0) {
+						decodeProcessDataReport((CStep*)pFrom, pszData, size);
+					}
+					return -1;
+				});
+			pStep->setName(STEP_PROCESS);
+			pStep->setWriteSignalDev(0xf47);
+			if (addStep(STEP_ID_PROCESS_DATA_REPORT, pStep) != 0) {
+				delete pStep;
+			}
+		}
+
+		{
+			// eq cim mode change
+			CEqCimModeChangeStep* pStep = new CEqCimModeChangeStep();
+			pStep->setName(STEP_CIM_MODE_CHANGE);
+			pStep->setWriteSignalDev(0xf60);
+			pStep->setCimModeDev(0x2ea5);
+			if (addStep(STEP_ID_CIMMODE_CHANGED_CMD_REPLY, pStep) != 0) {
+				delete pStep;
+			}
+		}
+
+		{
+			// eq cim message cmd
+			CEqCimMessageCmdStep* pStep = new CEqCimMessageCmdStep();
+			pStep->setName(STEP_CIM_MESSAGE_CMD);
+			pStep->setWriteSignalDev(0xf61);
+			pStep->setCimMessageDev(0x2e90);
+			if (addStep(STEP_ID_CIM_MSG_SET_CMD_REPLY, pStep) != 0) {
+				delete pStep;
+			}
+		}
+
+		{
+			// eq current recipe change
+			CEqCurrentRecipeChangeStep* pStep = new CEqCurrentRecipeChangeStep();
+			pStep->setName(STEP_EQ_RURRENT_RECIPE_CHANGE);
+			pStep->setWriteSignalDev(0xf48);
+			pStep->setDataDev(0x1a850);
+			if (addStep(STEP_ID_CURRENT_RECIPE_CHANGE_REPORT, pStep) != 0) {
+				delete pStep;
+			}
+		}
+
+		{
+			// CIM Message Confirm
+			// 要将int32的值拆分为两个short, 分别为msg id和panel id
+			// 65538, 2为msg id, 1为panel id
+			CEqReadIntStep* pStep = new CEqReadIntStep(__INT32, 0x19d80);
+			pStep->setName(STEP_EQ_CIM_MESSAGE_CONFIRM);
+			pStep->setWriteSignalDev(0xf49);
+			if (addStep(STEP_ID_CIM_MSG_CONFIRM_REPORT, pStep) != 0) {
+				delete pStep;
+			}
+		}
+
+		{
+			CEqCimMessageClearStep* pStep = new CEqCimMessageClearStep();
+			pStep->setName(STEP_CIM_MESSAGE_CLEAR);
+			pStep->setWriteSignalDev(0xf62);
+			pStep->setClearCimMessageDev(0x2ea3);
+			if (addStep(STEP_ID_CIM_MSG_CLEAR_CMD_REPLY, pStep) != 0) {
+				delete pStep;
+			}
+		}
+
+		{
+			CEqDateTimeSetCmdStep* pStep = new CEqDateTimeSetCmdStep();
+			pStep->setName(STEP_DATETIME_SET_CMD);
+			pStep->setWriteSignalDev(0xf63);
+			pStep->setDateTimeDev(0x2ea6);
+			if (addStep(STEP_ID_DATETIME_SET_CMD_REPLY, pStep) != 0) {
+				delete pStep;
+			}
+		}
+
+		{
+			CEqModeChangeStep* pStep = new CEqModeChangeStep();
+			pStep->setName(STEP_EQ_MODE_CHANGE);
+			pStep->setWriteSignalDev(0xf65);
+			pStep->setEqModeDev(0x2eae);
+			if (addStep(STEP_ID_EQMODE_CHANGE_CMD_REPLY, pStep) != 0) {
+				delete pStep;
+			}
+		}
+
+		{
+			// 请求主配方列表的step
+			CEqWriteStep* pStep = new CEqWriteStep();
+			pStep->setName(STEP_EQ_MASTER_RECIPE_LIST_REQ);
+			pStep->setWriteSignalDev(0xf66);
+			pStep->setDataDev(0x379a);
+			if (addStep(STEP_ID_MASTER_RECIPE_LIST_CMD_REPLY, pStep) != 0) {
+				delete pStep;
+			}
+		}
+
+		{
+			// master recipe list report
+			CEqReadStep* pStep = new CEqReadStep(0x1a955, 255 * 2,
+				[&](void* pFrom, int code, const char* pszData, size_t size) -> int {
+					if (code == ROK && pszData != nullptr && size > 0) {
+						// 此处解释配方数据
+						short ret = decodeRecipeListReport(pszData, size);
+						pStep->setReturnCode(ret);
+					}
+					pStep->setReturnCode(MRLRC_OK);
+					return -1;
+				});
+			pStep->setName(STEP_EQ_MASTER_RECIPE_LIST);
+			pStep->setWriteSignalDev(0xf4b);
+			pStep->setReturnDev(0x37ad);
+			if (addStep(STEP_ID_MASTER_RECIPE_LIST_REPORT, pStep) != 0) {
+				delete pStep;
+			}
+		}
+
+		{
+			// 请求配方参数
+			//CEqWriteStep* pStep = new CEqWriteStep();
+			//pStep->setName(STEP_EQ_RECIPE_PARAMETER_REQ);
+			//pStep->setWriteSignalDev(0xf67);
+			//pStep->setDataDev(0x379b);
+			//if (addStep(STEP_ID_RECIPE_PARAMETER_CMD_REPLY, pStep) != 0) {
+			//	delete pStep;
+			//}
+		}
+
+		{
+			// recipe parameter report
+			//CEqReadStep* pStep = new CEqReadStep(0x1aa54, 257 * 2,
+			//	[&](void* pFrom, int code, const char* pszData, size_t size) -> int {
+			//		if (code == ROK && pszData != nullptr && size > 0) {
+			//			// 此处解释配方数据
+			//			short ret = decodeRecipeParameterReport(pszData, size);
+			//			pStep->setReturnCode(ret);
+			//		}
+			//		pStep->setReturnCode(MRLRC_OK);
+			//		return -1;
+			//	});
+			//pStep->setName(STEP_EQ_RECIPE_PARAMETER);
+			//pStep->setWriteSignalDev(0xf4c);
+			//pStep->setReturnDev(m_nIndex == 0 ? 0x126c : 0x1bbc);
+			//if (addStep(STEP_ID_RECIPE_PARAMETER_REPORT, pStep) != 0) {
+			//	delete pStep;
+			//}
+		}
+
+		// 使用CEqReadStep替换CEqJobEventStep
+		{
+			// Received Job Report Upstream #1~9
+			char szBuffer[256];
+			for (int i = 0; i < 1; i++) {
+				CEqReadStep* pStep = new CEqReadStep(0x18c90 + 320 * i, 320 * 2,
+					[&](void* pFrom, int code, const char* pszData, size_t size) -> int {
+						if (code == ROK && pszData != nullptr && size > 0) {
+							int port = (int)(__int64)((CEqReadStep*)pFrom)->getProp("Port");
+							if (port > 0) {
+								decodeReceivedJobReport((CStep*)pFrom, port, pszData, size);
+							}
+						}
+						return -1;
+					});
+				sprintf_s(szBuffer, "%s%d", STEP_EQ_RECEIVED_JOB_UPSn, i + 1);
+				pStep->setName(szBuffer);
+				pStep->setProp("Port", (void*)(__int64)(i + 1));
+				pStep->setWriteSignalDev(0xf00 + i);
+				if (addStep(STEP_ID_RECIVE_JOB_UPS1 + i, pStep) != 0) {
+					delete pStep;
+				}
+			}
+		}
+
+		{
+			// Sent Out Job Report Downstream #1~9
+			char szBuffer[256];
+			for (int i = 0; i < 1; i++) {
+				CEqReadStep* pStep = new CEqReadStep(0x18000 + 320 * i, 320 * 2,
+					[&](void* pFrom, int code, const char* pszData, size_t size) -> int {
+						if (code == ROK && pszData != nullptr && size > 0) {
+							int port = (int)(__int64)((CEqReadStep*)pFrom)->getProp("Port");
+							if (port > 0) {
+								decodeReceivedJobReport((CStep*)pFrom, port, pszData, size);
+							}
+						}
+						return -1;
+					});
+				sprintf_s(szBuffer, "%s%d", STEP_EQ_SENT_OUT_JOB_DOWNSn, i + 1);
+				pStep->setName(szBuffer);
+				pStep->setProp("Port", (void*)(__int64)(i + 1));
+				pStep->setWriteSignalDev(0xf0a + i);
+				if (addStep(STEP_ID_SENT_OUT_JOB_DOWNS1 + i, pStep) != 0) {
+					delete pStep;
+				}
+			}
+		}
+
+		{
+			// Fetched Out Job Report #1~15
+			char szBuffer[256];
+			for (int i = 0; i < 1; i++) {
+				CEqReadStep* pStep = new CEqReadStep(0x19c31 + 18 * i, 18 * 2,
+					[&](void* pFrom, int code, const char* pszData, size_t size) -> int {
+						if (code == ROK && pszData != nullptr && size > 0) {
+							int port = (int)(__int64)((CEqReadStep*)pFrom)->getProp("Port");
+							if (port > 0) {
+								decodeFetchedOutJobReport((CStep*)pFrom, port, pszData, size);
+							}
+						}
+						return -1;
+					});
+				sprintf_s(szBuffer, "%s%d", STEP_EQ_FETCHED_OUT_JOBn, i + 1);
+				pStep->setName(szBuffer);
+				pStep->setProp("Port", (void*)(__int64)(i + 1));
+				pStep->setWriteSignalDev(0xf23 + i);
+				if (addStep(STEP_ID_FETCHED_OUT_JOB_REPORT1 + i, pStep) != 0) {
+					delete pStep;
+				}
+			}
+		}
+
+		{
+			// Stored Job Report #1~15
+			char szBuffer[256];
+			for (int i = 0; i < 1; i++) {
+				CEqReadStep* pStep = new CEqReadStep(0x19b23 + 18 * i, 18 * 2,
+					[&](void* pFrom, int code, const char* pszData, size_t size) -> int {
+						if (code == ROK && pszData != nullptr && size > 0) {
+							int port = (int)(__int64)((CEqReadStep*)pFrom)->getProp("Port");
+							if (port > 0) {
+								decodeStoredJobReport((CStep*)pFrom, port, pszData, size);
+							}
+						}
+						return -1;
+					});
+				sprintf_s(szBuffer, "%s%d", STEP_EQ_STORED_JOBn, i + 1);
+				pStep->setName(szBuffer);
+				pStep->setProp("Port", (void*)(__int64)(i + 1));
+				pStep->setWriteSignalDev(0xf14 + i);
+				if (addStep(STEP_ID_STORE_JOB_REPORT1 + i, pStep) != 0) {
+					delete pStep;
+				}
+			}
+		}
+	}
+
 	// 必须要实现的虚函数,在此初始化Slot信息
 	void CMeasurement::initSlots()
 	{
diff --git a/SourceCode/Bond/Servo/CMeasurement.h b/SourceCode/Bond/Servo/CMeasurement.h
index a1d8bac..519aa53 100644
--- a/SourceCode/Bond/Servo/CMeasurement.h
+++ b/SourceCode/Bond/Servo/CMeasurement.h
@@ -15,13 +15,13 @@
         virtual void init();
         virtual void term();
         virtual void initPins();
+        virtual void initSteps();
         virtual void initSlots();
         virtual void onTimer(UINT nTimerid);
         virtual void serialize(CArchive& ar);
         virtual void getAttributeVector(CAttributeVector& attrubutes);
         virtual int recvIntent(CPin* pPin, CIntent* pIntent);
         virtual int getIndexerOperationModeBaseValue();
-
 	};
 }
 
diff --git a/SourceCode/Bond/Servo/CPageGraph1.cpp b/SourceCode/Bond/Servo/CPageGraph1.cpp
index b9c2555..08f689b 100644
--- a/SourceCode/Bond/Servo/CPageGraph1.cpp
+++ b/SourceCode/Bond/Servo/CPageGraph1.cpp
@@ -100,6 +100,18 @@
 							DeviceStatus status = bAlive ? DeviceStatus::ONLINE : DeviceStatus::OFFLINE;
 							UpdateDeviceStatus(INDICATE_BONDER2, status);
 						}
+						else if (EQ_ID_VACUUMBAKE == nID) {
+							DeviceStatus status = bAlive ? DeviceStatus::ONLINE : DeviceStatus::OFFLINE;
+							UpdateDeviceStatus(INDICATE_VACUUM_BAKE, status);
+						}
+						else if (EQ_ID_BAKE_COOLING == nID) {
+							DeviceStatus status = bAlive ? DeviceStatus::ONLINE : DeviceStatus::OFFLINE;
+							UpdateDeviceStatus(INDICATE_BAKE_COOLING, status);
+						}
+						else if (EQ_ID_MEASUREMENT == nID) {
+							DeviceStatus status = bAlive ? DeviceStatus::ONLINE : DeviceStatus::OFFLINE;
+							UpdateDeviceStatus(INDICATE_MEASUREMENT, status);
+						}
 					}
 				}
 			}
diff --git a/SourceCode/Bond/Servo/CRobotCmdTestDlg.cpp b/SourceCode/Bond/Servo/CRobotCmdTestDlg.cpp
index 804335e..f8da27b 100644
--- a/SourceCode/Bond/Servo/CRobotCmdTestDlg.cpp
+++ b/SourceCode/Bond/Servo/CRobotCmdTestDlg.cpp
@@ -32,6 +32,28 @@
 	{_T("SendPutAndHome"),       {true,  false, false, true,  true }}
 };
 
+std::map<CString, int> g_mapDeviceSlotCount = {
+	{_T("Port1"), 8},
+	{_T("Port2"), 8},
+	{_T("Port3"), 8},
+	{_T("Port4"), 8},
+	{_T("RB1"), 1},
+	{_T("RB2"), 1},
+	{_T("AL"), 1},
+	{_T("FLIP"), 1},
+	{_T("Bonder1-涓婁骇鍝�"), 1},
+	{_T("Bonder1-涓嬩骇鍝�"), 1},
+	{_T("Bonder2-涓婁骇鍝�"), 1},
+	{_T("Bonder2-涓嬩骇鍝�"), 1},
+	{_T("VacBakeA鑵�"), 1},
+	{_T("VacBakeB鑵�"), 1},
+	{_T("BakecCoolingA鐑樼儰"), 1},
+	{_T("BakecCoolingA鍐峰嵈"), 1},
+	{_T("BakecCoolingB鐑樼儰"), 1},
+	{_T("BakecCoolingB鍐峰嵈"), 1},
+	{_T("Measurement"), 1}
+};
+
 // CRobotCmdTestDlg 瀵硅瘽妗�
 
 IMPLEMENT_DYNAMIC(CRobotCmdTestDlg, CDialogEx)
@@ -64,8 +86,10 @@
 }
 
 BEGIN_MESSAGE_MAP(CRobotCmdTestDlg, CDialogEx)
-	ON_CBN_SELCHANGE(IDC_COMBO_CMD_TYPE, &CRobotCmdTestDlg::OnCbnSelchangeComboCmdType)
 	ON_BN_CLICKED(IDC_BUTTON_EXECUTE, &CRobotCmdTestDlg::OnBnClickedButtonExecute)
+	ON_CBN_SELCHANGE(IDC_COMBO_CMD_TYPE, &CRobotCmdTestDlg::OnSelchangeComboCmdType)
+	ON_CBN_SELCHANGE(IDC_COMBO_GET_POS, &CRobotCmdTestDlg::OnSelchangeComboGetPos)
+	ON_CBN_SELCHANGE(IDC_COMBO_PUT_POS, &CRobotCmdTestDlg::OnSelchangeComboPutPos)
 END_MESSAGE_MAP()
 
 // CRobotCmdTestDlg 娑堟伅澶勭悊绋嬪簭
@@ -81,11 +105,6 @@
 	}
 	m_comboCmdType.SetCurSel(0);
 
-	// 鍒濆鍖栧懡浠よ緭鍏ユ帶浠�
-	if (!g_mapQuickCmd.empty()) {
-		UpdateCommandInputUI(g_mapQuickCmd.begin()->first);
-	}
-
 	// 鍒濆鍖� Arm No锛�1锛欰rm#1锛�2锛欰rm#2锛�
 	m_comboArmNo.AddString(_T("1"));
 	m_comboArmNo.AddString(_T("2"));
@@ -93,19 +112,25 @@
 
 	// 绀轰緥璁惧鍚嶇О鍒楄〃
 	CStringList eqNameList;
-	eqNameList.AddTail(_T("PORT 1"));				// 1 1 UNIT
-	eqNameList.AddTail(_T("PORT 2"));				// 2 1 UNIT
-	eqNameList.AddTail(_T("PORT 3"));				// 3 1 UNIT
-	eqNameList.AddTail(_T("PORT 4"));				// 4 1 UNIT
-	eqNameList.AddTail(_T("RB1"));					// 5 1 UNIT
-	eqNameList.AddTail(_T("RB2"));					// 6 1 UNIT
-	eqNameList.AddTail(_T("ALIGN"));				// 7 1 UNIT
-	eqNameList.AddTail(_T("FLIP"));					// 8 1 UNIT
-	eqNameList.AddTail(_T("VAC BAKE"));				// 9 2 UNIT
-	eqNameList.AddTail(_T("BONDER1"));				// 10 2 UNIT
-	eqNameList.AddTail(_T("BONDER2"));				// 11 2 UNIT
-	eqNameList.AddTail(_T("POST BAKE(COOLING)"));	// 12 4 UNIT
-	eqNameList.AddTail(_T("MEASUREMENT"));			// 13 1 UNIT
+	eqNameList.AddTail(_T("Port1"));
+	eqNameList.AddTail(_T("Port2"));
+	eqNameList.AddTail(_T("Port3"));
+	eqNameList.AddTail(_T("Port4"));
+	eqNameList.AddTail(_T("RB1"));	
+	eqNameList.AddTail(_T("RB2"));
+	eqNameList.AddTail(_T("AL"));
+	eqNameList.AddTail(_T("FLIP"));
+	eqNameList.AddTail(_T("Bonder1-涓婁骇鍝�"));
+	eqNameList.AddTail(_T("Bonder1-涓嬩骇鍝�"));
+	eqNameList.AddTail(_T("Bonder2-涓婁骇鍝�"));
+	eqNameList.AddTail(_T("Bonder2-涓嬩骇鍝�"));
+	eqNameList.AddTail(_T("VacBakeA鑵�"));
+	eqNameList.AddTail(_T("VacBakeB鑵�"));
+	eqNameList.AddTail(_T("BakecCoolingA鐑樼儰"));
+	eqNameList.AddTail(_T("BakecCoolingA鍐峰嵈"));
+	eqNameList.AddTail(_T("BakecCoolingB鐑樼儰"));
+	eqNameList.AddTail(_T("BakecCoolingB鍐峰嵈"));
+	eqNameList.AddTail(_T("Measurement"));	
 
 	for (POSITION pos = eqNameList.GetHeadPosition(); pos != NULL;) {
 		CString item = eqNameList.GetNext(pos);
@@ -115,15 +140,16 @@
 	m_comboGetPos.SetCurSel(0);
 	m_comboPutPos.SetCurSel(0);
 
-	// 鍒濆鍖� Slot锛堥粯璁や粠 1 鍒� 25锛�
-	for (int i = 1; i < 26; ++i) {
-		CString str;
-		str.Format(_T("%d"), i);
-		m_comboGetSlot.AddString(str);
-		m_comboPutSlot.AddString(str);
+	// 鍒濆鍖� Slot
+	m_comboGetPos.SetCurSel(0);
+	m_comboPutPos.SetCurSel(0);
+	UpdateSlotList(&m_comboGetPos, &m_comboGetSlot);
+	UpdateSlotList(&m_comboPutPos, &m_comboPutSlot);
+
+	// 鍒濆鍖栧懡浠よ緭鍏ユ帶浠�
+	if (!g_mapQuickCmd.empty()) {
+		UpdateCommandInputUI(g_mapQuickCmd.begin()->first);
 	}
-	m_comboGetSlot.SetCurSel(0);
-	m_comboPutSlot.SetCurSel(0);
 
 	// 蹇嵎鍛戒护鎵ц鏄犲皠琛�
 	m_mapCmdExec = {
@@ -204,11 +230,16 @@
 	}
 
 	const QuickCmdFieldMask& mask = it->second;
-	GetDlgItem(IDC_COMBO_ARM_NO)->EnableWindow(mask.useArm);
-	GetDlgItem(IDC_COMBO_GET_POS)->EnableWindow(mask.useGetPos);
-	GetDlgItem(IDC_COMBO_GET_SLOT)->EnableWindow(mask.useGetSlot);
-	GetDlgItem(IDC_COMBO_PUT_POS)->EnableWindow(mask.usePutPos);
-	GetDlgItem(IDC_COMBO_PUT_SLOT)->EnableWindow(mask.usePutSlot);
+	m_comboArmNo.SetCurSel(0);
+	m_comboArmNo.EnableWindow(mask.useArm);
+	m_comboGetPos.SetCurSel(0);
+	m_comboGetPos.EnableWindow(mask.useGetPos);
+	m_comboGetSlot.SetCurSel(0);
+	m_comboGetSlot.EnableWindow(mask.useGetSlot);
+	m_comboPutPos.SetCurSel(0);
+	m_comboPutPos.EnableWindow(mask.usePutPos);
+	m_comboPutSlot.SetCurSel(0);
+	m_comboPutSlot.EnableWindow(mask.usePutSlot);
 }
 
 void CRobotCmdTestDlg::AppendLogLineBatchBegin()
@@ -239,6 +270,8 @@
 
 void CRobotCmdTestDlg::AppendLogLineRichStyled(const CString& content, COLORREF color /*= RGB(0, 0, 0)*/)
 {
+	if (!::IsWindow(GetSafeHwnd())) return;
+
 	// 鏃堕棿鎴�
 	CString timestamp;
 	CTime now = CTime::GetCurrentTime();
@@ -296,19 +329,73 @@
 	m_editLog.SetSel(-1, 0);
 }
 
-void CRobotCmdTestDlg::OnCbnSelchangeComboCmdType()
+void CRobotCmdTestDlg::UpdateSlotList(CComboBox* pComboDevice, CComboBox* pComboSlot)
 {
-	int nSel = m_comboCmdType.GetCurSel();
-	if (nSel < 0) {
+	if (pComboDevice == nullptr || pComboSlot == nullptr) {
 		return;
 	}
 
-	CString str;
-	m_comboCmdType.GetLBText(nSel, str);
-	UpdateCommandInputUI(str);
+	int nSelIndex = pComboDevice->GetCurSel();
+	if (nSelIndex < 0) {
+		return;
+	}
 
-	str.Format(_T("鍒囨崲褰撳墠鍛戒护绫诲瀷锛�%s"), str);
-	AppendLogLineRichStyled(str, LOG_COLOR_NORMAL);
+	CString strDeviceName;
+	pComboDevice->GetLBText(nSelIndex, strDeviceName);
+
+	int nMaxSlot = 1; // 榛樿妲戒綅鏁�
+	auto it = g_mapDeviceSlotCount.find(strDeviceName);
+	if (it != g_mapDeviceSlotCount.end()) {
+		nMaxSlot = it->second;
+	}
+	else {
+		CString strLog;
+		strLog.Format(_T("璁惧 %s 鏈畾涔夋Ы浣嶆暟锛屼娇鐢ㄩ粯璁ゅ�� 1"), strDeviceName.GetString());
+		AppendLogLineRichStyled(strLog, LOG_COLOR_WARNING);
+	}
+
+	// 娓呯┖骞舵坊鍔犳Ы鍙�
+	pComboSlot->ResetContent();
+	for (int i = 1; i <= nMaxSlot; ++i) {
+		CString str;
+		str.Format(_T("%d"), i);
+		pComboSlot->AddString(str);
+	}
+
+	pComboSlot->SetCurSel(0);
+	pComboSlot->EnableWindow(1 != nMaxSlot);
+}
+
+void CRobotCmdTestDlg::UpdateArmList(CComboBox* pComboDevice, CComboBox* pComboArm)
+{
+	if (pComboDevice == nullptr || pComboArm == nullptr) {
+		return;
+	}
+
+	int nSelIndex = pComboDevice->GetCurSel();
+	if (nSelIndex < 0) {
+		return;
+	}
+
+	CString strDeviceName;
+	pComboDevice->GetLBText(nSelIndex, strDeviceName);
+	if (IsDualArmSupported(strDeviceName)) {
+		pComboArm->EnableWindow(TRUE);
+	}
+	else {
+		pComboArm->EnableWindow(FALSE);
+	}
+
+	pComboArm->SetCurSel(0);
+}
+
+bool CRobotCmdTestDlg::IsDualArmSupported(const CString& strDeviceName)
+{
+	// 娉ㄦ剰鍖归厤瑙勫垯鏄惁鍖哄垎鈥�-涓婁骇鍝佲�濄�佲��-涓嬩骇鍝佲�濈瓑鍚庣紑
+	if (strDeviceName.Find(_T("FLIP")) >= 0) return true;
+	if (strDeviceName.Find(_T("Bonder1")) >= 0) return true;
+	if (strDeviceName.Find(_T("Bonder2")) >= 0) return true;
+	return false;
 }
 
 void CRobotCmdTestDlg::OnBnClickedButtonExecute()
@@ -333,7 +420,7 @@
 	// 鏌ユ壘鍑芥暟骞舵墽琛�
 	auto it = m_mapCmdExec.find(cmdName);
 	if (it != m_mapCmdExec.end() && nullptr != m_pEFEM) {
-		int ret = it->second(1, armNo, getPos, getSlot, putPos, putSlot, [&](int code) -> int {
+		int ret = it->second(1, armNo, getPos, putPos, getSlot, putSlot, [&](int code) -> int {
 			if (code == WOK) {
 				AppendLogLineRichStyled(_T("宸叉敹鍒癛obot鍥炲簲锛�"), LOG_COLOR_SUCCESS);
 			}
@@ -360,3 +447,32 @@
 		AppendLogLineRichStyled(log, LOG_COLOR_ERROR);
 	}
 }
+
+void CRobotCmdTestDlg::OnSelchangeComboCmdType()
+{
+	int nSel = m_comboCmdType.GetCurSel();
+	if (nSel < 0) {
+		return;
+	}
+
+	CString str;
+	m_comboCmdType.GetLBText(nSel, str);
+	UpdateCommandInputUI(str);
+
+	str.Format(_T("鍒囨崲褰撳墠鍛戒护绫诲瀷锛�%s"), str);
+	AppendLogLineRichStyled(str, LOG_COLOR_NORMAL);
+}
+
+void CRobotCmdTestDlg::OnSelchangeComboGetPos()
+{
+	// TODO: 鍦ㄦ娣诲姞鎺т欢閫氱煡澶勭悊绋嬪簭浠g爜
+	UpdateSlotList(&m_comboGetPos, &m_comboGetSlot);
+	UpdateArmList(&m_comboGetPos, &m_comboArmNo);
+}
+
+void CRobotCmdTestDlg::OnSelchangeComboPutPos()
+{
+	// TODO: 鍦ㄦ娣诲姞鎺т欢閫氱煡澶勭悊绋嬪簭浠g爜
+	UpdateSlotList(&m_comboPutPos, &m_comboPutSlot);
+	UpdateArmList(&m_comboPutPos, &m_comboArmNo);
+}
diff --git a/SourceCode/Bond/Servo/CRobotCmdTestDlg.h b/SourceCode/Bond/Servo/CRobotCmdTestDlg.h
index c605e58..0169495 100644
--- a/SourceCode/Bond/Servo/CRobotCmdTestDlg.h
+++ b/SourceCode/Bond/Servo/CRobotCmdTestDlg.h
@@ -35,8 +35,10 @@
 protected:
 	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 鏀寔
 	virtual BOOL OnInitDialog();
-	afx_msg void OnCbnSelchangeComboCmdType();
 	afx_msg void OnBnClickedButtonExecute();
+	afx_msg void OnSelchangeComboCmdType();
+	afx_msg void OnSelchangeComboGetPos();
+	afx_msg void OnSelchangeComboPutPos();
 	DECLARE_MESSAGE_MAP()
 
 private:
@@ -46,6 +48,9 @@
 	void TrimRichEditLineLimit(int maxLines = 100);
 	void AppendLogLineRichStyled(const CString& content, COLORREF color = RGB(0, 0, 0));
 	void HighlightAllMatches(const CString& strSearch, COLORREF clrHighlight = RGB(255, 165, 0));
+	void UpdateSlotList(CComboBox* pComboDevice, CComboBox* pComboSlot);
+	void UpdateArmList(CComboBox* pComboDevice, CComboBox* pComboArm);
+	bool IsDualArmSupported(const CString& strDeviceName);
 
 	// 鎺т欢
 	CComboBox m_comboCmdType;
diff --git a/SourceCode/Bond/Servo/CVacuumBake.cpp b/SourceCode/Bond/Servo/CVacuumBake.cpp
index ca005e2..0dec6ba 100644
--- a/SourceCode/Bond/Servo/CVacuumBake.cpp
+++ b/SourceCode/Bond/Servo/CVacuumBake.cpp
@@ -38,6 +38,301 @@
 		addPin(SERVO::PinType::OUTPUT, _T("Out2"));
 	}
 
+	void CVacuumBake::initSteps()
+	{
+		CEquipment::initSteps();
+
+		{
+			// eq mode
+			CEqModeStep* pStep = new CEqModeStep();
+			pStep->setName(STEP_MODE);
+			pStep->setWriteSignalDev(0xc40);
+			pStep->setModeDev(0x15d7d);
+			if (addStep(STEP_ID_EQMODE_CHANGED, pStep) != 0) {
+				delete pStep;
+			}
+		}
+
+		{
+			// eq status
+			CEqStatusStep* pStep = new CEqStatusStep();
+			pStep->setName(STEP_STATUS);
+			pStep->setWriteSignalDev(0xc41);
+			pStep->setStatusDev(0x15d59);
+			if (addStep(STEP_ID_EQSTATUS_CHANGED, pStep) != 0) {
+				delete pStep;
+			}
+		}
+
+		{
+			// Eq Alarm
+			static char* pszName[] = { STEP_ALARM_BLOCK1, STEP_ALARM_BLOCK2, STEP_ALARM_BLOCK3, STEP_ALARM_BLOCK4, STEP_ALARM_BLOCK5 };
+			static int dev[5] = { 0x15f0e , 0x15f3b, 0x15f68, 0x15f95, 0x15fc2 };
+			static int writeSignalDev[5] = { 0xc42, 0xc43, 0xc44, 0xc45, 0xc46 };
+			static int addr[] = { STEP_ID_EQALARM1, STEP_ID_EQALARM2, STEP_ID_EQALARM3, STEP_ID_EQALARM4, STEP_ID_EQALARM5 };
+
+			for (int i = 0; i < 5; i++) {
+				CEqAlarmStep* pStep = new CEqAlarmStep();
+				pStep->setName(pszName[i]);
+				pStep->setWriteSignalDev(writeSignalDev[i]);
+				pStep->setAlarmDev(dev[i]);
+				if (addStep(addr[i], pStep) != 0) {
+					delete pStep;
+				}
+			}
+
+		}
+
+		{
+			CEqReadStep* pStep = new CEqReadStep(0x16b55, 538 * 2,
+				[&](void* pFrom, int code, const char* pszData, size_t size) -> int {
+					if (code == ROK && pszData != nullptr && size > 0) {
+						decodeProcessDataReport((CStep*)pFrom, pszData, size);
+					}
+					return -1;
+				});
+			pStep->setName(STEP_PROCESS);
+			pStep->setWriteSignalDev(0xc47);
+			if (addStep(STEP_ID_PROCESS_DATA_REPORT, pStep) != 0) {
+				delete pStep;
+			}
+		}
+
+		{
+			// eq cim mode change
+			CEqCimModeChangeStep* pStep = new CEqCimModeChangeStep();
+			pStep->setName(STEP_CIM_MODE_CHANGE);
+			pStep->setWriteSignalDev(0xc60);
+			pStep->setCimModeDev(0x2555);
+			if (addStep(STEP_ID_CIMMODE_CHANGED_CMD_REPLY, pStep) != 0) {
+				delete pStep;
+			}
+		}
+
+		{
+			// eq cim message cmd
+			CEqCimMessageCmdStep* pStep = new CEqCimMessageCmdStep();
+			pStep->setName(STEP_CIM_MESSAGE_CMD);
+			pStep->setWriteSignalDev(0xc61);
+			pStep->setCimMessageDev(0x2540);
+			if (addStep(STEP_ID_CIM_MSG_SET_CMD_REPLY, pStep) != 0) {
+				delete pStep;
+			}
+		}
+
+		{
+			// eq current recipe change
+			CEqCurrentRecipeChangeStep* pStep = new CEqCurrentRecipeChangeStep();
+			pStep->setName(STEP_EQ_RURRENT_RECIPE_CHANGE);
+			pStep->setWriteSignalDev(0xc48);
+			pStep->setDataDev(0x16850);
+			if (addStep(STEP_ID_CURRENT_RECIPE_CHANGE_REPORT, pStep) != 0) {
+				delete pStep;
+			}
+		}
+
+		{
+			// CIM Message Confirm
+			// 要将int32的值拆分为两个short, 分别为msg id和panel id
+			// 65538, 2为msg id, 1为panel id
+			CEqReadIntStep* pStep = new CEqReadIntStep(__INT32, 0x15d80);
+			pStep->setName(STEP_EQ_CIM_MESSAGE_CONFIRM);
+			pStep->setWriteSignalDev(0xc49);
+			if (addStep(STEP_ID_CIM_MSG_CONFIRM_REPORT, pStep) != 0) {
+				delete pStep;
+			}
+		}
+
+		{
+			CEqCimMessageClearStep* pStep = new CEqCimMessageClearStep();
+			pStep->setName(STEP_CIM_MESSAGE_CLEAR);
+			pStep->setWriteSignalDev(0xc62);
+			pStep->setClearCimMessageDev(0x2553);
+			if (addStep(STEP_ID_CIM_MSG_CLEAR_CMD_REPLY, pStep) != 0) {
+				delete pStep;
+			}
+		}
+
+		{
+			CEqDateTimeSetCmdStep* pStep = new CEqDateTimeSetCmdStep();
+			pStep->setName(STEP_DATETIME_SET_CMD);
+			pStep->setWriteSignalDev(0xc63);
+			pStep->setDateTimeDev(0x2556);
+			if (addStep(STEP_ID_DATETIME_SET_CMD_REPLY, pStep) != 0) {
+				delete pStep;
+			}
+		}
+
+		{
+			CEqModeChangeStep* pStep = new CEqModeChangeStep();
+			pStep->setName(STEP_EQ_MODE_CHANGE);
+			pStep->setWriteSignalDev(0xc65);
+			pStep->setEqModeDev(0x255e);
+			if (addStep(STEP_ID_EQMODE_CHANGE_CMD_REPLY, pStep) != 0) {
+				delete pStep;
+			}
+		}
+
+		{
+			// 请求主配方列表的step
+			CEqWriteStep* pStep = new CEqWriteStep();
+			pStep->setName(STEP_EQ_MASTER_RECIPE_LIST_REQ);
+			pStep->setWriteSignalDev(0xc66);
+			pStep->setDataDev(0x2e4a);
+			if (addStep(STEP_ID_MASTER_RECIPE_LIST_CMD_REPLY, pStep) != 0) {
+				delete pStep;
+			}
+		}
+
+		{
+			// master recipe list report
+			CEqReadStep* pStep = new CEqReadStep(0x16955, 255 * 2,
+				[&](void* pFrom, int code, const char* pszData, size_t size) -> int {
+					if (code == ROK && pszData != nullptr && size > 0) {
+						// 此处解释配方数据
+						short ret = decodeRecipeListReport(pszData, size);
+						pStep->setReturnCode(ret);
+					}
+					pStep->setReturnCode(MRLRC_OK);
+					return -1;
+				});
+			pStep->setName(STEP_EQ_MASTER_RECIPE_LIST);
+			pStep->setWriteSignalDev(0xc4b);
+			pStep->setReturnDev(0x37ad);
+			if (addStep(STEP_ID_MASTER_RECIPE_LIST_REPORT, pStep) != 0) {
+				delete pStep;
+			}
+		}
+
+		{
+			// 请求配方参数
+			//CEqWriteStep* pStep = new CEqWriteStep();
+			//pStep->setName(STEP_EQ_RECIPE_PARAMETER_REQ);
+			//pStep->setWriteSignalDev(0xc67);
+			//pStep->setDataDev(0x379b);
+			//if (addStep(STEP_ID_RECIPE_PARAMETER_CMD_REPLY, pStep) != 0) {
+			//	delete pStep;
+			//}
+		}
+
+		{
+			// recipe parameter report
+			//CEqReadStep* pStep = new CEqReadStep(0x1aa54, 257 * 2,
+			//	[&](void* pFrom, int code, const char* pszData, size_t size) -> int {
+			//		if (code == ROK && pszData != nullptr && size > 0) {
+			//			// 此处解释配方数据
+			//			short ret = decodeRecipeParameterReport(pszData, size);
+			//			pStep->setReturnCode(ret);
+			//		}
+			//		pStep->setReturnCode(MRLRC_OK);
+			//		return -1;
+			//	});
+			//pStep->setName(STEP_EQ_RECIPE_PARAMETER);
+			//pStep->setWriteSignalDev(0xc4c);
+			//pStep->setReturnDev(m_nIndex == 0 ? 0x126c : 0x1bbc);
+			//if (addStep(STEP_ID_RECIPE_PARAMETER_REPORT, pStep) != 0) {
+			//	delete pStep;
+			//}
+		}
+
+		// 使用CEqReadStep替换CEqJobEventStep
+		{
+			// Received Job Report Upstream #1~9
+			char szBuffer[256];
+			for (int i = 0; i < 1; i++) {
+				CEqReadStep* pStep = new CEqReadStep(0x14c90 + 320 * i, 320 * 2,
+					[&](void* pFrom, int code, const char* pszData, size_t size) -> int {
+						if (code == ROK && pszData != nullptr && size > 0) {
+							int port = (int)(__int64)((CEqReadStep*)pFrom)->getProp("Port");
+							if (port > 0) {
+								decodeReceivedJobReport((CStep*)pFrom, port, pszData, size);
+							}
+						}
+						return -1;
+					});
+				sprintf_s(szBuffer, "%s%d", STEP_EQ_RECEIVED_JOB_UPSn, i + 1);
+				pStep->setName(szBuffer);
+				pStep->setProp("Port", (void*)(__int64)(i + 1));
+				pStep->setWriteSignalDev(0xc00 + i);
+				if (addStep(STEP_ID_RECIVE_JOB_UPS1 + i, pStep) != 0) {
+					delete pStep;
+				}
+			}
+		}
+
+		{
+			// Sent Out Job Report Downstream #1~9
+			char szBuffer[256];
+			for (int i = 0; i < 1; i++) {
+				CEqReadStep* pStep = new CEqReadStep(0x14000 + 320 * i, 320 * 2,
+					[&](void* pFrom, int code, const char* pszData, size_t size) -> int {
+						if (code == ROK && pszData != nullptr && size > 0) {
+							int port = (int)(__int64)((CEqReadStep*)pFrom)->getProp("Port");
+							if (port > 0) {
+								decodeReceivedJobReport((CStep*)pFrom, port, pszData, size);
+							}
+						}
+						return -1;
+					});
+				sprintf_s(szBuffer, "%s%d", STEP_EQ_SENT_OUT_JOB_DOWNSn, i + 1);
+				pStep->setName(szBuffer);
+				pStep->setProp("Port", (void*)(__int64)(i + 1));
+				pStep->setWriteSignalDev(0xc0a + i);
+				if (addStep(STEP_ID_SENT_OUT_JOB_DOWNS1 + i, pStep) != 0) {
+					delete pStep;
+				}
+			}
+		}
+
+		{
+			// Fetched Out Job Report #1~15
+			char szBuffer[256];
+			for (int i = 0; i < 1; i++) {
+				CEqReadStep* pStep = new CEqReadStep(0x15c31 + 18 * i, 18 * 2,
+					[&](void* pFrom, int code, const char* pszData, size_t size) -> int {
+						if (code == ROK && pszData != nullptr && size > 0) {
+							int port = (int)(__int64)((CEqReadStep*)pFrom)->getProp("Port");
+							if (port > 0) {
+								decodeFetchedOutJobReport((CStep*)pFrom, port, pszData, size);
+							}
+						}
+						return -1;
+					});
+				sprintf_s(szBuffer, "%s%d", STEP_EQ_FETCHED_OUT_JOBn, i + 1);
+				pStep->setName(szBuffer);
+				pStep->setProp("Port", (void*)(__int64)(i + 1));
+				pStep->setWriteSignalDev(0xc23 + i);
+				if (addStep(STEP_ID_FETCHED_OUT_JOB_REPORT1 + i, pStep) != 0) {
+					delete pStep;
+				}
+			}
+		}
+
+		{
+			// Stored Job Report #1~15
+			char szBuffer[256];
+			for (int i = 0; i < 1; i++) {
+				CEqReadStep* pStep = new CEqReadStep(0x15b23 + 18 * i, 18 * 2,
+					[&](void* pFrom, int code, const char* pszData, size_t size) -> int {
+						if (code == ROK && pszData != nullptr && size > 0) {
+							int port = (int)(__int64)((CEqReadStep*)pFrom)->getProp("Port");
+							if (port > 0) {
+								decodeStoredJobReport((CStep*)pFrom, port, pszData, size);
+							}
+						}
+						return -1;
+					});
+				sprintf_s(szBuffer, "%s%d", STEP_EQ_STORED_JOBn, i + 1);
+				pStep->setName(szBuffer);
+				pStep->setProp("Port", (void*)(__int64)(i + 1));
+				pStep->setWriteSignalDev(0xc14 + i);
+				if (addStep(STEP_ID_STORE_JOB_REPORT1 + i, pStep) != 0) {
+					delete pStep;
+				}
+			}
+		}
+	}
+
 	// 必须要实现的虚函数,在此初始化Slot信息
 	void CVacuumBake::initSlots()
 	{
diff --git a/SourceCode/Bond/Servo/CVacuumBake.h b/SourceCode/Bond/Servo/CVacuumBake.h
index 8619b43..2663f59 100644
--- a/SourceCode/Bond/Servo/CVacuumBake.h
+++ b/SourceCode/Bond/Servo/CVacuumBake.h
@@ -15,6 +15,7 @@
         virtual void init();
         virtual void term();
         virtual void initPins();
+        virtual void initSteps();
         virtual void initSlots();
         virtual void onTimer(UINT nTimerid);
         virtual void serialize(CArchive& ar);
diff --git a/SourceCode/Bond/Servo/Model.cpp b/SourceCode/Bond/Servo/Model.cpp
index 04cf046..27056bd 100644
--- a/SourceCode/Bond/Servo/Model.cpp
+++ b/SourceCode/Bond/Servo/Model.cpp
@@ -244,7 +244,7 @@
 
 		// 状态映射
 		static const char* STATUS_STR[] = {
-			"Unknown", "Ready", "Running", "Error", "Abort", "Completed"
+			"Unknown", "Ready", "Running", "Picking", "Placing", "Restoring", "Error", "Abort", "Completed"
 		};
 		auto state = pTask->getState();
 		int index = static_cast<int>(state);
diff --git a/SourceCode/Bond/Servo/TransferManager.cpp b/SourceCode/Bond/Servo/TransferManager.cpp
index 6079a79..bf7e2a4 100644
--- a/SourceCode/Bond/Servo/TransferManager.cpp
+++ b/SourceCode/Bond/Servo/TransferManager.cpp
@@ -29,45 +29,6 @@
     }
 }
 
-// 任务状态转换成 int 类型
-int TransferManager::statusToInt(TransferStatus status) {
-    return static_cast<int>(status);
-}
-
-// int 类型转换成任务状态
-TransferStatus TransferManager::intToStatus(int value) {
-    switch (value) {
-        case 0: return TransferStatus::Ready;
-        case 1: return TransferStatus::Running;
-        case 2: return TransferStatus::Error;
-        case 3: return TransferStatus::Abort;
-        case 4: return TransferStatus::Completed;
-        default: return TransferStatus::Error;
-    }
-}
-
-// 任务状态转换成字符串
-std::string TransferManager::statusToString(TransferStatus status) {
-    switch (status) {
-        case TransferStatus::Ready:     return "Ready";
-        case TransferStatus::Running:   return "Running";
-        case TransferStatus::Error:     return "Error";
-        case TransferStatus::Abort:     return "Abort";
-        case TransferStatus::Completed: return "Completed";
-        default:                        return "Unknown";
-    }
-}
-
-// 字符串转换成任务状态
-TransferStatus TransferManager::stringToStatus(const std::string& str) {
-    if (str == "Ready")     return TransferStatus::Ready;
-    if (str == "Running")   return TransferStatus::Running;
-    if (str == "Error")     return TransferStatus::Error;
-    if (str == "Abort")     return TransferStatus::Abort;
-    if (str == "Completed") return TransferStatus::Completed;
-    return TransferStatus::Error;
-}
-
 // 本地编码转为 UTF-8
 std::string TransferManager::ansiToUtf8(const std::string& ansiStr) {
     // 1. ANSI → UTF-16
@@ -134,35 +95,46 @@
 }
 
 // 插入测试搬运记录
-void TransferManager::insertTestTransferRecord() {
-    if (nullptr != m_pDB) { 
-        int nCount = 10000;
+void TransferManager::insertTestTransferRecord(int nCount /*=10000*/) {
+    if (nullptr != m_pDB) {
+        static const char* STATUS_STR[] = {
+            "Unknown", "Ready", "Running", "Picking", "Placing",
+            "Restoring", "Error", "Abort", "Completed"
+        };
+
+        auto formatTime = [](const std::tm& time) {
+            char szTime[64];
+            strftime(szTime, sizeof(szTime), "%Y-%m-%d %H:%M:%S", &time);
+            return std::string(szTime);
+        };
+
+        std::time_t startTime = std::time(nullptr);
         for (int i = 0; i < nCount; ++i) {
             TransferData data;
             data.strClassID = "T-" + std::to_string(1000 + i);
-            data.strStatus = statusToString(static_cast<TransferStatus>(i % 5));
+            data.strStatus = STATUS_STR[i % 9];
 
-            std::time_t now = std::time(nullptr) + i * 60;  // 每条记录间隔1分钟
+            std::time_t baseTime = startTime + i * 60;
+            std::time_t pickTime = baseTime + 60;
+            std::time_t placeTime = pickTime + 60;
+            std::time_t endTime = placeTime + 60;
 
             std::tm tmCreate = {}, tmPick = {}, tmPlace = {}, tmEnd = {};
-            localtime_s(&tmCreate, &now);
-            localtime_s(&tmPick, &(now += 60));
-            localtime_s(&tmPlace, &(now += 60));
-            localtime_s(&tmEnd, &(now += 60));
+            localtime_s(&tmCreate, &baseTime);
+            localtime_s(&tmPick, &pickTime);
+            localtime_s(&tmPlace, &placeTime);
+            localtime_s(&tmEnd, &endTime);
 
-            char szTime[64];
-            strftime(szTime, sizeof(szTime), "%Y-%m-%d %H:%M:%S", &tmCreate);
-            data.strCreateTime = szTime;
-            strftime(szTime, sizeof(szTime), "%Y-%m-%d %H:%M:%S", &tmPick);
-            data.strPickTime = szTime;
-            strftime(szTime, sizeof(szTime), "%Y-%m-%d %H:%M:%S", &tmPlace);
-            data.strPlaceTime = szTime;
-            strftime(szTime, sizeof(szTime), "%Y-%m-%d %H:%M:%S", &tmEnd);
-            data.strEndTime = szTime;
-
+            data.strCreateTime = formatTime(tmCreate);
+            data.strPickTime = formatTime(tmPick);
+            data.strPlaceTime = formatTime(tmPlace);
+            data.strEndTime = formatTime(tmEnd);
             data.strDescription = "Mock transfer task " + std::to_string(i);
+
             int nRecordId = 0;
-            addTransferRecord(data, nRecordId);
+            if (!addTransferRecord(data, nRecordId)) {
+                std::cerr << "[Error] 插入第 " << i << " 条记录失败" << std::endl;
+            }
         }
 
         std::cout << "[Mock] 成功插入 " << nCount << " 条测试搬运记录。" << std::endl;
diff --git a/SourceCode/Bond/Servo/TransferManager.h b/SourceCode/Bond/Servo/TransferManager.h
index 9dde8c8..a6739db 100644
--- a/SourceCode/Bond/Servo/TransferManager.h
+++ b/SourceCode/Bond/Servo/TransferManager.h
@@ -8,17 +8,6 @@
 #include "Database.h"
 
 /**
- * 任务状态枚举类型
- */
-enum class TransferStatus {
-    Ready = 0,
-    Running,
-    Error,
-    Abort,
-    Completed
-};
-
-/**
  * 搬运记录结构体
  */
 struct TransferData {
@@ -51,7 +40,7 @@
 	/**
 	 * 插入测试搬运记录
 	 */
-    void insertTestTransferRecord();
+    void insertTestTransferRecord(int nCount = 10000);
 
     /**
      * 终止数据库连接
@@ -157,10 +146,6 @@
     TransferManager& operator=(const TransferManager&) = delete;
 
     // 内联函数
-    inline int statusToInt(TransferStatus status);
-    inline TransferStatus intToStatus(int value);
-    inline std::string statusToString(TransferStatus status);
-    inline TransferStatus stringToStatus(const std::string& str);
     inline std::string ansiToUtf8(const std::string& ansiStr);
     inline std::string utf8ToAnsi(const std::string& utf8Str);
 

--
Gitblit v1.9.3