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

---
 SourceCode/Bond/Servo/CArmTray.h                                |    1 
 SourceCode/Bond/Servo/CArm.cpp                                  |   40 
 Document/ESWIN_EAS_Bonder_Inline_Mapping_Address_v1.1.6(5).xlsx |    0 
 SourceCode/Bond/Servo/CVacuumBake.cpp                           |   45 
 SourceCode/Bond/Servo/CEqDateTimeSetCmdStep.h                   |    2 
 SourceCode/Bond/Servo/CJobDataS.cpp                             |   12 
 SourceCode/Bond/Servo/CEFEM.h                                   |   32 
 SourceCode/Bond/Servo/CBakeCooling.cpp                          |   19 
 SourceCode/Bond/Servo/CPath.h                                   |    2 
 SourceCode/Bond/x64/Debug/Res/robot_High_32.ico                 |    0 
 SourceCode/Bond/Servo/ToolUnits.cpp                             |    5 
 SourceCode/Bond/Servo/CPortStatusReport.h                       |    2 
 SourceCode/Bond/Servo/CAligner.h                                |    3 
 SourceCode/Bond/Servo/Servo.rc                                  |    0 
 SourceCode/Bond/Servo/CBonder.h                                 |    3 
 SourceCode/Bond/Servo/ServoDlg.h                                |    7 
 SourceCode/Bond/Servo/CEqStatusStep.h                           |    2 
 SourceCode/Bond/Servo/CEqCurrentRecipeChangeStep.h              |    2 
 SourceCode/Bond/Servo/CJobDataC.cpp                             |   11 
 SourceCode/Bond/Servo/CJobDataB.cpp                             |   12 
 SourceCode/Bond/Servo/CEqCimModeChangeStep.h                    |    2 
 SourceCode/Bond/Servo/CEqPortChangeStep.h                       |    2 
 SourceCode/Bond/Servo/CLoadPort.cpp                             |  120 +
 SourceCode/Bond/Servo/CMeasurement.h                            |    2 
 SourceCode/Bond/Servo/CSlot.h                                   |   47 
 SourceCode/Bond/Servo/CEqModeChangeStep.h                       |    2 
 SourceCode/Bond/Servo/CEqWriteStep.h                            |    2 
 SourceCode/Bond/Servo/CMeasurement.cpp                          |   19 
 SourceCode/Bond/Servo/Servo.vcxproj.filters                     |   10 
 SourceCode/Bond/Servo/CJobDataA.cpp                             |   12 
 SourceCode/Bond/Servo/CJobDataB.h                               |    5 
 SourceCode/Bond/Servo/CVcrEventReport.h                         |    2 
 SourceCode/Bond/Servo/TopToolbar.cpp                            |  218 ++++
 SourceCode/Bond/Servo/CEFEM.cpp                                 |   76 
 SourceCode/Bond/Servo/CMyStatusbar.cpp                          |  117 ++
 SourceCode/Bond/Servo/CEquipment.h                              |  116 -
 SourceCode/Bond/Servo/ServoCommo.h                              |   97 +
 SourceCode/Bond/Servo/CEqCassetteCtrlCmdStep.h                  |    2 
 SourceCode/Bond/Servo/CEqCimMessageCmdStep.h                    |    2 
 SourceCode/Bond/x64/Debug/Res/robot_Gray_32.ico                 |    0 
 SourceCode/Bond/Servo/CPagePortProperty.cpp                     |   16 
 SourceCode/Bond/Servo/Servo.vcxproj                             |   10 
 SourceCode/Bond/Servo/CMyStatusbar.h                            |   43 
 SourceCode/Bond/Servo/CEqReadIntStep.h                          |    2 
 SourceCode/Bond/Servo/resource.h                                |    0 
 SourceCode/Bond/Servo/CEqVcrEventStep.h                         |    2 
 SourceCode/Bond/Servo/CJobDataS.h                               |    5 
 SourceCode/Bond/Servo/CFliper.cpp                               |   45 
 SourceCode/Bond/Servo/CRobotTask.cpp                            |  167 +++
 SourceCode/Bond/Servo/Servo.cpp                                 |    2 
 SourceCode/Bond/Servo/CEqModeStep.h                             |    2 
 SourceCode/Bond/Servo/CMaster.h                                 |   39 
 SourceCode/Bond/Servo/CRobotCmdTestDlg.h                        |    2 
 SourceCode/Bond/Servo/CEqAlarmStep.h                            |    2 
 SourceCode/Bond/Servo/CSlot.cpp                                 |  152 +++
 SourceCode/Bond/Servo/TopToolbar.h                              |   58 +
 SourceCode/Bond/Servo/CBakeCooling.h                            |    2 
 SourceCode/Bond/Servo/CEquipment.cpp                            |  415 ++++----
 SourceCode/Bond/Servo/Model.h                                   |    1 
 SourceCode/Bond/Servo/CEqJobEventStep.h                         |    2 
 SourceCode/Bond/Servo/CEqVCREnableStep.h                        |    2 
 SourceCode/Bond/Servo/CMaster.cpp                               |  347 ++++++
 SourceCode/Bond/Servo/CArm.h                                    |    1 
 SourceCode/Bond/Servo/CEqReadStep.h                             |    2 
 SourceCode/Bond/Servo/CPageGraph2.cpp                           |   79 -
 SourceCode/Bond/Servo/CRobotCmdTestDlg.cpp                      |   71 
 SourceCode/Bond/Servo/CGlassPool.h                              |    2 
 SourceCode/Bond/Servo/CLoadPort.h                               |   29 
 SourceCode/Bond/Servo/CProcessData.h                            |    2 
 SourceCode/Bond/Servo/Model.cpp                                 |    9 
 SourceCode/Bond/Servo/CVacuumBake.h                             |    3 
 SourceCode/Bond/Servo/ServoDlg.cpp                              |  137 ++
 SourceCode/Bond/Servo/CAttributeVector.h                        |    2 
 Document/BONDER流程信息表.xls                                        |    0 
 Document/ESWIN_EAS_Bonder_Inline_Mapping_Address_v1.1.6(1).xlsx |    0 
 SourceCode/Bond/Servo/CAttribute.h                              |    2 
 SourceCode/Bond/x64/Debug/Master.dat                            |    0 
 SourceCode/Bond/Servo/CRobotTask.h                              |   52 +
 SourceCode/Bond/Servo/CJobDataA.h                               |    5 
 SourceCode/Bond/Servo/CEqCimMessageClearStep.h                  |    2 
 SourceCode/Bond/Servo/CAligner.cpp                              |   39 
 SourceCode/Bond/Servo/CEquipmentPage2.cpp                       |   16 
 SourceCode/Bond/Servo/CJobDataC.h                               |    5 
 SourceCode/Bond/Servo/CPin.cpp                                  |    2 
 SourceCode/Bond/Servo/CArmTray.cpp                              |    9 
 SourceCode/Bond/Servo/CEqProcessStep.h                          |    2 
 SourceCode/Bond/Servo/CEqCassetteTransferStateStep.h            |    2 
 SourceCode/Bond/Servo/CBonder.cpp                               |   74 -
 SourceCode/Bond/Servo/CFliper.h                                 |    3 
 SourceCode/Bond/Servo/Common.h                                  |   39 
 90 files changed, 2,164 insertions(+), 794 deletions(-)

diff --git "a/Document/BONDER\346\265\201\347\250\213\344\277\241\346\201\257\350\241\250.xls" "b/Document/BONDER\346\265\201\347\250\213\344\277\241\346\201\257\350\241\250.xls"
new file mode 100644
index 0000000..de0f4cf
--- /dev/null
+++ "b/Document/BONDER\346\265\201\347\250\213\344\277\241\346\201\257\350\241\250.xls"
Binary files differ
diff --git "a/Document/ESWIN_EAS_Bonder_Inline_Mapping_Address_v1.1.6\0501\051.xlsx" "b/Document/ESWIN_EAS_Bonder_Inline_Mapping_Address_v1.1.6\0501\051.xlsx"
new file mode 100644
index 0000000..22de365
--- /dev/null
+++ "b/Document/ESWIN_EAS_Bonder_Inline_Mapping_Address_v1.1.6\0501\051.xlsx"
Binary files differ
diff --git "a/Document/ESWIN_EAS_Bonder_Inline_Mapping_Address_v1.1.6\0505\051.xlsx" "b/Document/ESWIN_EAS_Bonder_Inline_Mapping_Address_v1.1.6\0505\051.xlsx"
new file mode 100644
index 0000000..e02265f
--- /dev/null
+++ "b/Document/ESWIN_EAS_Bonder_Inline_Mapping_Address_v1.1.6\0505\051.xlsx"
Binary files differ
diff --git a/SourceCode/Bond/Servo/CAligner.cpp b/SourceCode/Bond/Servo/CAligner.cpp
index e07f04e..c15885e 100644
--- a/SourceCode/Bond/Servo/CAligner.cpp
+++ b/SourceCode/Bond/Servo/CAligner.cpp
@@ -39,6 +39,15 @@
 		addPin(SERVO::PinType::OUTPUT, _T("Out2"));
 	}
 
+	// 必须要实现的虚函数,在此初始化Slot信息
+	void CAligner::initSlots()
+	{
+		m_slot[0].enable();
+		m_slot[0].setPosition(m_nID);
+		m_slot[0].setNo(1);
+		m_slot[0].setName("Slot 1");
+	}
+
 	void CAligner::onTimer(UINT nTimerid)
 	{
 		CEquipment::onTimer(nTimerid);
@@ -57,35 +66,5 @@
 	int CAligner::recvIntent(CPin* pPin, CIntent* pIntent)
 	{
 		return __super::recvIntent(pPin, pIntent);
-	}
-
-	BOOL CAligner::glassWillArrive(CGlass* pGlass)
-	{
-		BOOL bRet = __super::glassWillArrive(pGlass);
-		if (!bRet) {
-			return FALSE;
-		}
-
-		return m_glassList.empty();
-	}
-
-	BOOL CAligner::onPreStoredJob(int port, CJobDataB* pJobDataB)
-	{
-		CJobDataS* pJobDataS = getJobDataS(pJobDataB->getCassetteSequenceNo(), pJobDataB->getJobSequenceNo());
-		if (pJobDataS == nullptr) {
-			LOGE("<CAligner-%s>onPreFetchedOutJob,找不到对应的JobDataS(CassetteSequenceNo:%d, JobSequenceNo:%d), 注意排查风险!", m_strName.c_str(),
-				pJobDataB->getCassetteSequenceNo(), pJobDataB->getJobSequenceNo());
-			return FALSE;
-		}
-
-		// 只能一片一片的对位
-		Lock();
-		if (!m_glassList.empty()) {
-			Unlock();
-			LOGE("<CEquipment-%s>onPreFetchedOutJob,当前机器或单元存在玻璃片,不能进料,请注意风险!", m_strName.c_str());
-			return FALSE;
-		}
-
-		return TRUE;
 	}
 }
diff --git a/SourceCode/Bond/Servo/CAligner.h b/SourceCode/Bond/Servo/CAligner.h
index 66ac974..a1ce3be 100644
--- a/SourceCode/Bond/Servo/CAligner.h
+++ b/SourceCode/Bond/Servo/CAligner.h
@@ -15,12 +15,11 @@
         virtual void init();
         virtual void term();
         virtual void initPins();
+        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 BOOL glassWillArrive(CGlass* pGlass);
-        virtual BOOL onPreStoredJob(int port, CJobDataB* pJobDataB);
 	};
 }
 
diff --git a/SourceCode/Bond/Servo/CArm.cpp b/SourceCode/Bond/Servo/CArm.cpp
index 064ab30..3a8d15b 100644
--- a/SourceCode/Bond/Servo/CArm.cpp
+++ b/SourceCode/Bond/Servo/CArm.cpp
@@ -34,6 +34,19 @@
 
 	}
 
+	// 必须要实现的虚函数,在此初始化Slot信息
+	void CArm::initSlots()
+	{
+		m_slot[0].enable();
+		m_slot[0].setPosition(m_nID);
+		m_slot[0].setNo(1);
+		m_slot[0].setName("Slot 1(Temp)");
+		m_slot[1].enable();
+		m_slot[1].setPosition(m_nID);
+		m_slot[1].setNo(2);
+		m_slot[1].setName("Slot 2(Temp)");
+	}
+
 	void CArm::onTimer(UINT nTimerid)
 	{
 		CEquipment::onTimer(nTimerid);
@@ -59,13 +72,19 @@
 		// 原:保证列表中只存储一个物料
 		// 修改为:先清空之前的,再添加当前pGlass, 如果pGlass有buddy,也要加入列表中
 		Lock();
-		for (auto item : m_glassList) {
-			item->release();
+		CGlass* pPreviousGlass;
+		pPreviousGlass = (CGlass*)m_slot[0].getContext();
+		if (pPreviousGlass != nullptr) {
+			pPreviousGlass->release();
 		}
-		m_glassList.clear();
-		addGlassToList(pGlass);
+		pPreviousGlass = (CGlass*)m_slot[1].getContext();
+		if (pPreviousGlass != nullptr) {
+			pPreviousGlass->release();
+		}
+
+		m_slot[0].setContext(pGlass);
 		if (pGlass->getBuddy() != nullptr) {
-			addGlassToList(pGlass->getBuddy());
+			m_slot[1].setContext(pGlass->getBuddy());
 		}
 		Unlock();
 
@@ -79,17 +98,14 @@
 	int CArm::tempFetchOut(OUT CGlass*& pGlass)
 	{
 		Lock();
-		if (m_glassList.empty()) {
+		CGlass* pPreviousGlass = (CGlass*)m_slot[0].getContext();
+		if (pPreviousGlass == nullptr) {
 			Unlock();
 			return -1;
 		}
-
-		pGlass = m_glassList.front();
+		pGlass = pPreviousGlass;
 		pGlass->addRef();
-		for (auto item : m_glassList) {
-			item->release();
-		}
-		m_glassList.clear();
+		m_slot[0].setContext(nullptr);
 		Unlock();
 
 		if (m_listener.onDataChanged != nullptr) {
diff --git a/SourceCode/Bond/Servo/CArm.h b/SourceCode/Bond/Servo/CArm.h
index 4a12834..cedb751 100644
--- a/SourceCode/Bond/Servo/CArm.h
+++ b/SourceCode/Bond/Servo/CArm.h
@@ -15,6 +15,7 @@
         virtual void init();
         virtual void term();
         virtual void initPins();
+        virtual void initSlots();
         virtual void onTimer(UINT nTimerid);
         virtual void serialize(CArchive& ar);
         virtual void getAttributeVector(CAttributeVector& attrubutes);
diff --git a/SourceCode/Bond/Servo/CArmTray.cpp b/SourceCode/Bond/Servo/CArmTray.cpp
index ddb8b30..6e74681 100644
--- a/SourceCode/Bond/Servo/CArmTray.cpp
+++ b/SourceCode/Bond/Servo/CArmTray.cpp
@@ -34,6 +34,15 @@
 
 	}
 
+	// 必须要实现的虚函数,在此初始化Slot信息
+	void CArmTray::initSlots()
+	{
+		m_slot[0].enable();
+		m_slot[0].setPosition(m_nID);
+		m_slot[0].setNo(1);
+		m_slot[0].setName("Slot 1");
+	}
+
 	void CArmTray::onTimer(UINT nTimerid)
 	{
 		CEquipment::onTimer(nTimerid);
diff --git a/SourceCode/Bond/Servo/CArmTray.h b/SourceCode/Bond/Servo/CArmTray.h
index 8a08cf0..7da5d54 100644
--- a/SourceCode/Bond/Servo/CArmTray.h
+++ b/SourceCode/Bond/Servo/CArmTray.h
@@ -14,6 +14,7 @@
         virtual void init();
         virtual void term();
         virtual void initPins();
+        virtual void initSlots();
         virtual void onTimer(UINT nTimerid);
         virtual void serialize(CArchive& ar);
         virtual void getAttributeVector(CAttributeVector& attrubutes);
diff --git a/SourceCode/Bond/Servo/CAttribute.h b/SourceCode/Bond/Servo/CAttribute.h
index ee5098b..b91e6cc 100644
--- a/SourceCode/Bond/Servo/CAttribute.h
+++ b/SourceCode/Bond/Servo/CAttribute.h
@@ -7,7 +7,7 @@
 	public:
 		CAttribute();
 		CAttribute(const char* pszName, const char* pszValue, const char* pszDescription, unsigned int weight);
-		~CAttribute();
+		virtual ~CAttribute();
 
 	public:
 		std::string& getName();
diff --git a/SourceCode/Bond/Servo/CAttributeVector.h b/SourceCode/Bond/Servo/CAttributeVector.h
index fdbb30a..f4cb330 100644
--- a/SourceCode/Bond/Servo/CAttributeVector.h
+++ b/SourceCode/Bond/Servo/CAttributeVector.h
@@ -8,7 +8,7 @@
 	{
 	public:
 		CAttributeVector();
-		~CAttributeVector();
+		virtual ~CAttributeVector();
 
 	public:
 		void addAttribute(CAttribute* pAttribute, BOOL bReplace = FALSE);
diff --git a/SourceCode/Bond/Servo/CBakeCooling.cpp b/SourceCode/Bond/Servo/CBakeCooling.cpp
index 96367ba..4850fb6 100644
--- a/SourceCode/Bond/Servo/CBakeCooling.cpp
+++ b/SourceCode/Bond/Servo/CBakeCooling.cpp
@@ -38,6 +38,15 @@
 		addPin(SERVO::PinType::OUTPUT, _T("Out"));
 	}
 
+	// 必须要实现的虚函数,在此初始化Slot信息
+	void CBakeCooling::initSlots()
+	{
+		m_slot[0].enable();
+		m_slot[0].setPosition(m_nID);
+		m_slot[0].setNo(1);
+		m_slot[0].setName("Slot 1");
+	}
+
 	void CBakeCooling::onTimer(UINT nTimerid)
 	{
 		CEquipment::onTimer(nTimerid);
@@ -56,16 +65,6 @@
 	int CBakeCooling::recvIntent(CPin* pPin, CIntent* pIntent)
 	{
 		return __super::recvIntent(pPin, pIntent);
-	}
-
-	BOOL CBakeCooling::glassWillArrive(CGlass* pGlass)
-	{
-		BOOL bRet = __super::glassWillArrive(pGlass);
-		if (!bRet) {
-			return FALSE;
-		}
-
-		return (m_glassList.size() < 4);
 	}
 
 	int CBakeCooling::getIndexerOperationModeBaseValue()
diff --git a/SourceCode/Bond/Servo/CBakeCooling.h b/SourceCode/Bond/Servo/CBakeCooling.h
index bea7a17..5af948a 100644
--- a/SourceCode/Bond/Servo/CBakeCooling.h
+++ b/SourceCode/Bond/Servo/CBakeCooling.h
@@ -15,11 +15,11 @@
         virtual void init();
         virtual void term();
         virtual void initPins();
+        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 BOOL glassWillArrive(CGlass* pGlass);
         virtual int getIndexerOperationModeBaseValue();
 	};
 }
diff --git a/SourceCode/Bond/Servo/CBonder.cpp b/SourceCode/Bond/Servo/CBonder.cpp
index f485a94..8be694e 100644
--- a/SourceCode/Bond/Servo/CBonder.cpp
+++ b/SourceCode/Bond/Servo/CBonder.cpp
@@ -336,6 +336,21 @@
 		}
 	}
 
+	// 必须要实现的虚函数,在此初始化Slot信息
+	void CBonder::initSlots()
+	{
+		m_slot[0].enable();
+		m_slot[0].setPosition(m_nID);
+		m_slot[0].setNo(1);
+		m_slot[0].setName("Slot 1(G1)");
+		m_slot[0].setType(MaterialsType::G1);
+		m_slot[1].enable();
+		m_slot[1].setPosition(m_nID);
+		m_slot[1].setNo(2);
+		m_slot[1].setName("Slot 2(G2)");
+		m_slot[1].setType(MaterialsType::G2);
+	}
+
 	void CBonder::onTimer(UINT nTimerid)
 	{
 		CEquipment::onTimer(nTimerid);
@@ -356,16 +371,6 @@
 		return __super::recvIntent(pPin, pIntent);
 	}
 
-	BOOL CBonder::glassWillArrive(CGlass* pGlass)
-	{
-		BOOL bRet = __super::glassWillArrive(pGlass);
-		if (!bRet) {
-			return FALSE;
-		}
-
-		return m_glassList.empty();
-	}
-
 	void CBonder::setIndex(unsigned int index)
 	{
 		m_nIndex = index;
@@ -376,39 +381,6 @@
 		return m_nIndex;
 	}
 
-	BOOL CBonder::onPreStoredJob(int port, CJobDataB* pJobDataB)
-	{
-		CJobDataS* pJobDataS = getJobDataS(pJobDataB->getCassetteSequenceNo(), pJobDataB->getJobSequenceNo());
-		if (pJobDataS == nullptr) {
-			LOGE("<CBonder-%s>onPreFetchedOutJob,找不到对应的JobDataS(CassetteSequenceNo:%d, JobSequenceNo:%d), 注意排查风险!", m_strName.c_str(),
-				pJobDataB->getCassetteSequenceNo(), pJobDataB->getJobSequenceNo());
-			return FALSE;
-		}
-
-		// 如果为空,可以进G1或G2
-		// 如果有一片玻璃,当前玻璃为G1则可进G2, 当前玻璃为G2则可进G1
-		BOOL bCheck = FALSE;
-		Lock();
-		size_t size = m_glassList.size();
-		if (size == 0) {
-			bCheck = TRUE;
-		}
-		else if (size == 1) {
-			CGlass* pGlass = m_glassList.front();
-			if ((pGlass->getType() == MaterialsType::G1 && pJobDataS->getMaterialsType() == (int)MaterialsType::G2)
-				|| (pGlass->getType() == MaterialsType::G2 && pJobDataS->getMaterialsType() == (int)MaterialsType::G1)) {
-				bCheck = TRUE;
-			}
-		}
-		Unlock();
-
-		if (!bCheck) {
-			LOGE("<CEquipment-%s>onPreFetchedOutJob,当前机器不满足进料条件,或已存在两片玻璃,或G2与G1不匹配,请注意风险!", m_strName.c_str());
-		}
-
-		return bCheck;
-	}
-
 	int CBonder::onProcessData(CProcessData* pProcessData)
 	{
 		CEquipment::onProcessData(pProcessData);
@@ -416,28 +388,23 @@
 
 		// 检查数据,当前两片玻璃,一片为G1, 一片为G2, 且pProcessData中的id能匹配G1或G2
 		Lock();
-		if (m_glassList.size() != 2) {
-			Unlock();
-			LOGE("<CBonder-%s>onProcessData,绑定失败,腔体内必须有且仅有两片玻璃!", m_strName.c_str());
-			return -1;
-		}
-
-		CGlass* pGlass1 = m_glassList.front();
-		CGlass* pGlass2 = m_glassList.back();
-		Unlock();
-
+		CGlass* pGlass1 = getGlassFromSlot(1);
+		CGlass* pGlass2 = getGlassFromSlot(2);
 		if (pGlass1->getBuddy() != nullptr || pGlass2->getBuddy() != nullptr) {
 			LOGE("<CBonder-%s>onProcessData,错误!玻璃较早前已被绑定,请检查数据是否正确!", m_strName.c_str());
+			Unlock();
 			return -1;
 		}
 
 		if (pGlass1->getBuddy() != nullptr || pGlass2->getBuddy() != nullptr) {
 			LOGE("<CBonder-%s>onProcessData,错误!玻璃较早前已被贴合,请检查数据是否正确!", m_strName.c_str());
+			Unlock();
 			return -1;
 		}
 
 		if (pGlass1->getType() == pGlass2->getType()) {
 			LOGE("<CBonder-%s>onProcessData,错误!两片玻璃未匹配,必须分别为G1和G2类型,请检查数据是否正确!", m_strName.c_str());
+			Unlock();
 			return -1;
 		}
 
@@ -445,6 +412,7 @@
 		pGlass2->setBuddy(pGlass1);
 		LOGE("<CBonder-%s>onProcessData,%s和%s已贴合!", m_strName.c_str(),
 			pGlass1->getID().c_str(), pGlass2->getID().c_str());
+		Unlock();
 
 		return 0;
 	}
diff --git a/SourceCode/Bond/Servo/CBonder.h b/SourceCode/Bond/Servo/CBonder.h
index f24e05b..28f557f 100644
--- a/SourceCode/Bond/Servo/CBonder.h
+++ b/SourceCode/Bond/Servo/CBonder.h
@@ -16,12 +16,11 @@
         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 BOOL glassWillArrive(CGlass* pGlass);
-        virtual BOOL onPreStoredJob(int port, CJobDataB* pJobDataB);
         virtual int onProcessData(CProcessData* pProcessData);
         virtual int getIndexerOperationModeBaseValue();
 
diff --git a/SourceCode/Bond/Servo/CEFEM.cpp b/SourceCode/Bond/Servo/CEFEM.cpp
index ddaba81..6cbb23b 100644
--- a/SourceCode/Bond/Servo/CEFEM.cpp
+++ b/SourceCode/Bond/Servo/CEFEM.cpp
@@ -126,15 +126,15 @@
 		return 0;
 	}
 
-	int CEFEM::SendHome(int seq)
+	int CEFEM::robotSendHome(int seq, ONWRITED onWritedBlock/* = nullptr*/)
 	{
 		SERVO::ROBOT_CMD_PARAM cmd = {};
 		cmd.sequenceNo = static_cast<short>(seq);
 		cmd.rcmd = static_cast<short>(SERVO::RCMD::Robot_home);
-		return robotCmd(cmd);
+		return robotCmd(cmd, onWritedBlock);
 	}
 
-	int CEFEM::SendTransfer(int seq, int armNo, int fromPos, int toPos, int fromSlot, int toSlot)
+	int CEFEM::robotSendTransfer(int seq, int armNo, int fromPos, int toPos, int fromSlot, int toSlot, ONWRITED onWritedBlock/* = nullptr*/)
 	{
 		SERVO::ROBOT_CMD_PARAM cmd = {};
 		cmd.sequenceNo = static_cast<short>(seq);
@@ -144,10 +144,10 @@
 		cmd.getSlotNo = static_cast<short>(fromSlot);
 		cmd.putPosition = static_cast<short>(toPos);
 		cmd.putSlotNo = static_cast<short>(toSlot);
-		return robotCmd(cmd);
+		return robotCmd(cmd, onWritedBlock);
 	}
 
-	int CEFEM::SendMoveToGet(int seq, int armNo, int pos, int slot)
+	int CEFEM::robotSendMoveToGet(int seq, int armNo, int pos, int slot, ONWRITED onWritedBlock/* = nullptr*/)
 	{
 		SERVO::ROBOT_CMD_PARAM cmd = {};
 		cmd.sequenceNo = static_cast<short>(seq);
@@ -156,10 +156,10 @@
 		cmd.getPosition = static_cast<short>(pos);
 		cmd.getSlotNo = static_cast<short>(slot);
 		cmd.subCmd = 1;
-		return robotCmd(cmd);
+		return robotCmd(cmd, onWritedBlock);
 	}
 
-	int CEFEM::SendMoveToPut(int seq, int armNo, int pos, int slot)
+	int CEFEM::robotSendMoveToPut(int seq, int armNo, int pos, int slot, ONWRITED onWritedBlock/* = nullptr*/)
 	{
 		SERVO::ROBOT_CMD_PARAM cmd = {};
 		cmd.sequenceNo = static_cast<short>(seq);
@@ -168,10 +168,10 @@
 		cmd.putPosition = static_cast<short>(pos);
 		cmd.putSlotNo = static_cast<short>(slot);
 		cmd.subCmd = 2;
-		return robotCmd(cmd);
+		return robotCmd(cmd, onWritedBlock);
 	}
 
-	int CEFEM::SendGet(int seq, int armNo, int pos, int slot)
+	int CEFEM::robotSendGet(int seq, int armNo, int pos, int slot, ONWRITED onWritedBlock/* = nullptr*/)
 	{
 		SERVO::ROBOT_CMD_PARAM cmd = {};
 		cmd.sequenceNo = static_cast<short>(seq);
@@ -179,10 +179,10 @@
 		cmd.armNo = static_cast<short>(armNo);
 		cmd.getPosition = static_cast<short>(pos);
 		cmd.getSlotNo = static_cast<short>(slot);
-		return robotCmd(cmd);
+		return robotCmd(cmd, onWritedBlock);
 	}
 
-	int CEFEM::SendPut(int seq, int armNo, int pos, int slot)
+	int CEFEM::robotSendPut(int seq, int armNo, int pos, int slot, ONWRITED onWritedBlock/* = nullptr*/)
 	{
 		SERVO::ROBOT_CMD_PARAM cmd = {};
 		cmd.sequenceNo = static_cast<short>(seq);
@@ -190,10 +190,10 @@
 		cmd.armNo = static_cast<short>(armNo);
 		cmd.putPosition = static_cast<short>(pos);
 		cmd.putSlotNo = static_cast<short>(slot);
-		return robotCmd(cmd);
+		return robotCmd(cmd, onWritedBlock);
 	}
 
-	int CEFEM::SendExchange(int seq, int armNo, int pos, int getSlot, int putSlot)
+	int CEFEM::robotSendExchange(int seq, int armNo, int pos, int getSlot, int putSlot, ONWRITED onWritedBlock/* = nullptr*/)
 	{
 		SERVO::ROBOT_CMD_PARAM cmd = {};
 		cmd.sequenceNo = static_cast<short>(seq);
@@ -203,18 +203,18 @@
 		cmd.putPosition = static_cast<short>(pos);
 		cmd.getSlotNo = static_cast<short>(getSlot);
 		cmd.putSlotNo = static_cast<short>(putSlot);
-		return robotCmd(cmd);
+		return robotCmd(cmd, onWritedBlock);
 	}
 
-	int CEFEM::SendCommandClear(int seq)
+	int CEFEM::robotSendCommandClear(int seq, ONWRITED onWritedBlock/* = nullptr*/)
 	{
 		SERVO::ROBOT_CMD_PARAM cmd = {};
 		cmd.sequenceNo = static_cast<short>(seq);
 		cmd.rcmd = static_cast<short>(SERVO::RCMD::Command_Clear);
-		return robotCmd(cmd);
+		return robotCmd(cmd, onWritedBlock);
 	}
 
-	int CEFEM::SendBatchGet(int seq, int getPos, int getSlot)
+	int CEFEM::robotSendBatchGet(int seq, int getPos, int getSlot, ONWRITED onWritedBlock/* = nullptr*/)
 	{
 		SERVO::ROBOT_CMD_PARAM cmd = {};
 		cmd.sequenceNo = static_cast<short>(seq);
@@ -222,10 +222,10 @@
 		cmd.armNo = ARM_ALL;
 		cmd.getPosition = static_cast<short>(getPos);
 		cmd.getSlotNo = static_cast<short>(getSlot);
-		return robotCmd(cmd);
+		return robotCmd(cmd, onWritedBlock);
 	}
 
-	int CEFEM::SendBatchPut(int seq, int putPos, int putSlot)
+	int CEFEM::robotSendBatchPut(int seq, int putPos, int putSlot, ONWRITED onWritedBlock/* = nullptr*/)
 	{
 		SERVO::ROBOT_CMD_PARAM cmd = {};
 		cmd.sequenceNo = static_cast<short>(seq);
@@ -233,10 +233,10 @@
 		cmd.armNo = ARM_ALL;
 		cmd.putPosition = static_cast<short>(putPos);
 		cmd.putSlotNo = static_cast<short>(putSlot);
-		return robotCmd(cmd);
+		return robotCmd(cmd, onWritedBlock);
 	}
 
-	int CEFEM::SendMoveToGetAndHome(int seq, int armNo, int getPos, int getSlot)
+	int CEFEM::robotSendMoveToGetAndHome(int seq, int armNo, int getPos, int getSlot, ONWRITED onWritedBlock/* = nullptr*/)
 	{
 		SERVO::ROBOT_CMD_PARAM cmds[2] = {};
 
@@ -252,10 +252,10 @@
 		cmds[1].sequenceNo = static_cast<short>(seq + 1);
 		cmds[1].rcmd = static_cast<short>(SERVO::RCMD::Robot_home);
 
-		return robotCmds(cmds, 2);
+		return robotCmds(cmds, 2, onWritedBlock);
 	}
 
-	int CEFEM::SendMoveToPutAndHome(int seq, int armNo, int putPos, int putSlot)
+	int CEFEM::robotSendMoveToPutAndHome(int seq, int armNo, int putPos, int putSlot, ONWRITED onWritedBlock/* = nullptr*/)
 	{
 		SERVO::ROBOT_CMD_PARAM cmds[2] = {};
 
@@ -271,10 +271,10 @@
 		cmds[1].sequenceNo = static_cast<short>(seq + 1);
 		cmds[1].rcmd = static_cast<short>(SERVO::RCMD::Robot_home);
 
-		return robotCmds(cmds, 2);
+		return robotCmds(cmds, 2, onWritedBlock);
 	}
 
-	int CEFEM::SendTransferAndHome(int seq, int armNo, int fromPos, int toPos, int fromSlot, int toSlot)
+	int CEFEM::robotSendTransferAndHome(int seq, int armNo, int fromPos, int toPos, int fromSlot, int toSlot, ONWRITED onWritedBlock/* = nullptr*/)
 	{
 		SERVO::ROBOT_CMD_PARAM cmds[2] = {};
 
@@ -291,10 +291,10 @@
 		cmds[1].sequenceNo = static_cast<short>(seq + 1);
 		cmds[1].rcmd = static_cast<short>(SERVO::RCMD::Robot_home);
 
-		return robotCmds(cmds, 2);
+		return robotCmds(cmds, 2, onWritedBlock);
 	}
 
-	int CEFEM::SendGetAndPut(int seq, int armNo, int getPos, int getSlot, int putPos, int putSlot)
+	int CEFEM::robotSendGetAndPut(int seq, int armNo, int getPos, int getSlot, int putPos, int putSlot, ONWRITED onWritedBlock/* = nullptr*/)
 	{
 		SERVO::ROBOT_CMD_PARAM cmds[2] = {};
 
@@ -310,10 +310,10 @@
 		cmds[1].putPosition = static_cast<short>(putPos);
 		cmds[1].putSlotNo = static_cast<short>(putSlot);
 
-		return robotCmds(cmds, 2);
+		return robotCmds(cmds, 2, onWritedBlock);
 	}
 
-	int CEFEM::SendPutAndHome(int seq, int armNo, int putPos, int putSlot)
+	int CEFEM::robotSendPutAndHome(int seq, int armNo, int putPos, int putSlot, ONWRITED onWritedBlock/* = nullptr*/)
 	{
 		SERVO::ROBOT_CMD_PARAM cmds[2] = {};
 
@@ -328,7 +328,7 @@
 		cmds[1].sequenceNo = static_cast<short>(seq + 1);
 		cmds[1].rcmd = static_cast<short>(SERVO::RCMD::Robot_home);
 
-		return robotCmds(cmds, 2);
+		return robotCmds(cmds, 2, onWritedBlock);
 	}
 
 	void CEFEM::init()
@@ -628,6 +628,12 @@
 		}
 	}
 
+	// 必须要实现的虚函数,在此初始化Slot信息
+	void CEFEM::initSlots()
+	{
+
+	}
+
 	void CEFEM::onTimer(UINT nTimerid)
 	{
 		CEquipment::onTimer(nTimerid);
@@ -646,16 +652,6 @@
 	int CEFEM::recvIntent(CPin* pPin, CIntent* pIntent)
 	{
 		return __super::recvIntent(pPin, pIntent);
-	}
-
-	BOOL CEFEM::glassWillArrive(CGlass* pGlass)
-	{
-		BOOL bRet = __super::glassWillArrive(pGlass);
-		if (!bRet) {
-			return FALSE;
-		}
-
-		return m_glassList.empty();
 	}
 
 	void CEFEM::onReceiveLBData(const char* pszData, size_t size)
diff --git a/SourceCode/Bond/Servo/CEFEM.h b/SourceCode/Bond/Servo/CEFEM.h
index d8a4e1b..b01036f 100644
--- a/SourceCode/Bond/Servo/CEFEM.h
+++ b/SourceCode/Bond/Servo/CEFEM.h
@@ -20,11 +20,11 @@
         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 BOOL glassWillArrive(CGlass* pGlass);
         virtual void onReceiveLBData(const char* pszData, size_t size);
         virtual int onReceivedJob(int port, CJobDataS* pJobDataS);
         virtual int onSentOutJob(int port, CJobDataS* pJobDataS);
@@ -41,21 +41,21 @@
         int robotCmds(ROBOT_CMD_PARAM* robotCmdParam, unsigned int count, ONWRITED onWritedBlock = nullptr);
 
         // 快捷封装
-        int SendHome(int seq);
-        int SendTransfer(int seq, int armNo, int fromPos, int toPos, int fromSlot, int toSlot);
-        int SendMoveToGet(int seq, int armNo, int pos, int slot);
-        int SendMoveToPut(int seq, int armNo, int pos, int slot);
-        int SendGet(int seq, int armNo, int pos, int slot);
-        int SendPut(int seq, int armNo, int pos, int slot);
-        int SendExchange(int seq, int armNo, int pos, int getSlot, int putSlot);
-        int SendCommandClear(int seq);
-        int SendBatchGet(int seq, int getPos, int getSlot);
-        int SendBatchPut(int seq, int putPos, int putSlot);
-        int SendMoveToGetAndHome(int seq, int armNo, int getPos, int getSlot);
-        int SendMoveToPutAndHome(int seq, int armNo, int putPos, int putSlot);
-        int SendTransferAndHome(int seq, int armNo, int fromPos, int toPos, int fromSlot, int toSlot);
-        int SendGetAndPut(int seq, int armNo, int getPos, int getSlot, int putPos, int putSlot);
-        int SendPutAndHome(int seq, int armNo, int putPos, int putSlot);
+        int robotSendHome(int seq, ONWRITED onWritedBlock = nullptr);
+        int robotSendTransfer(int seq, int armNo, int fromPos, int toPos, int fromSlot, int toSlot, ONWRITED onWritedBlock = nullptr);
+        int robotSendMoveToGet(int seq, int armNo, int pos, int slot, ONWRITED onWritedBlock = nullptr);
+        int robotSendMoveToPut(int seq, int armNo, int pos, int slot, ONWRITED onWritedBlock = nullptr);
+        int robotSendGet(int seq, int armNo, int pos, int slot, ONWRITED onWritedBlock = nullptr);
+        int robotSendPut(int seq, int armNo, int pos, int slot, ONWRITED onWritedBlock = nullptr);
+        int robotSendExchange(int seq, int armNo, int pos, int getSlot, int putSlot, ONWRITED onWritedBlock = nullptr);
+        int robotSendCommandClear(int seq, ONWRITED onWritedBlock = nullptr);
+        int robotSendBatchGet(int seq, int getPos, int getSlot, ONWRITED onWritedBlock = nullptr);
+        int robotSendBatchPut(int seq, int putPos, int putSlot, ONWRITED onWritedBlock = nullptr);
+        int robotSendMoveToGetAndHome(int seq, int armNo, int getPos, int getSlot, ONWRITED onWritedBlock = nullptr);
+        int robotSendMoveToPutAndHome(int seq, int armNo, int putPos, int putSlot, ONWRITED onWritedBlock = nullptr);
+        int robotSendTransferAndHome(int seq, int armNo, int fromPos, int toPos, int fromSlot, int toSlot, ONWRITED onWritedBlock = nullptr);
+        int robotSendGetAndPut(int seq, int armNo, int getPos, int getSlot, int putPos, int putSlot, ONWRITED onWritedBlock = nullptr);
+        int robotSendPutAndHome(int seq, int armNo, int putPos, int putSlot, ONWRITED onWritedBlock = nullptr);
 
     private:
         CLoadPort* m_pPort[4];
diff --git a/SourceCode/Bond/Servo/CEqAlarmStep.h b/SourceCode/Bond/Servo/CEqAlarmStep.h
index 7c33958..b00c538 100644
--- a/SourceCode/Bond/Servo/CEqAlarmStep.h
+++ b/SourceCode/Bond/Servo/CEqAlarmStep.h
@@ -7,7 +7,7 @@
 	{
 	public:
 		CEqAlarmStep();
-		~CEqAlarmStep();
+		virtual ~CEqAlarmStep();
 
 	public:
 		virtual void getAttributeVector(CAttributeVector& attrubutes);
diff --git a/SourceCode/Bond/Servo/CEqCassetteCtrlCmdStep.h b/SourceCode/Bond/Servo/CEqCassetteCtrlCmdStep.h
index e86ca92..97e2d62 100644
--- a/SourceCode/Bond/Servo/CEqCassetteCtrlCmdStep.h
+++ b/SourceCode/Bond/Servo/CEqCassetteCtrlCmdStep.h
@@ -8,7 +8,7 @@
 	{
 	public:
 		CEqCassetteCtrlCmdStep();
-		~CEqCassetteCtrlCmdStep();
+		virtual ~CEqCassetteCtrlCmdStep();
 
 	public:
 		void setCtrlCmdDev(int nDev);
diff --git a/SourceCode/Bond/Servo/CEqCassetteTransferStateStep.h b/SourceCode/Bond/Servo/CEqCassetteTransferStateStep.h
index a069226..c136522 100644
--- a/SourceCode/Bond/Servo/CEqCassetteTransferStateStep.h
+++ b/SourceCode/Bond/Servo/CEqCassetteTransferStateStep.h
@@ -7,7 +7,7 @@
 	{
 	public:
 		CEqCassetteTransferStateStep();
-		~CEqCassetteTransferStateStep();
+		virtual ~CEqCassetteTransferStateStep();
 
 	public:
 		virtual void getAttributeVector(CAttributeVector& attrubutes);
diff --git a/SourceCode/Bond/Servo/CEqCimMessageClearStep.h b/SourceCode/Bond/Servo/CEqCimMessageClearStep.h
index b4306f9..3f2f391 100644
--- a/SourceCode/Bond/Servo/CEqCimMessageClearStep.h
+++ b/SourceCode/Bond/Servo/CEqCimMessageClearStep.h
@@ -7,7 +7,7 @@
 	{
 	public:
 		CEqCimMessageClearStep();
-		~CEqCimMessageClearStep();
+		virtual ~CEqCimMessageClearStep();
 
 	public:
 		void setClearCimMessageDev(int nDev);
diff --git a/SourceCode/Bond/Servo/CEqCimMessageCmdStep.h b/SourceCode/Bond/Servo/CEqCimMessageCmdStep.h
index 61378ed..fb29f6c 100644
--- a/SourceCode/Bond/Servo/CEqCimMessageCmdStep.h
+++ b/SourceCode/Bond/Servo/CEqCimMessageCmdStep.h
@@ -7,7 +7,7 @@
 	{
 	public:
 		CEqCimMessageCmdStep();
-		~CEqCimMessageCmdStep();
+		virtual ~CEqCimMessageCmdStep();
 
 	public:
 		void setCimMessageDev(int nDev);
diff --git a/SourceCode/Bond/Servo/CEqCimModeChangeStep.h b/SourceCode/Bond/Servo/CEqCimModeChangeStep.h
index 22afc6a..c014de0 100644
--- a/SourceCode/Bond/Servo/CEqCimModeChangeStep.h
+++ b/SourceCode/Bond/Servo/CEqCimModeChangeStep.h
@@ -7,7 +7,7 @@
 	{
 	public:
 		CEqCimModeChangeStep();
-		~CEqCimModeChangeStep();
+		virtual ~CEqCimModeChangeStep();
 
 	public:
 		void setCimModeDev(int nDev);
diff --git a/SourceCode/Bond/Servo/CEqCurrentRecipeChangeStep.h b/SourceCode/Bond/Servo/CEqCurrentRecipeChangeStep.h
index 7e05701..54cd8e1 100644
--- a/SourceCode/Bond/Servo/CEqCurrentRecipeChangeStep.h
+++ b/SourceCode/Bond/Servo/CEqCurrentRecipeChangeStep.h
@@ -7,7 +7,7 @@
 	{
 	public:
 		CEqCurrentRecipeChangeStep();
-		~CEqCurrentRecipeChangeStep();
+		virtual ~CEqCurrentRecipeChangeStep();
 
 	public:
 		virtual void getAttributeVector(CAttributeVector& attrubutes);
diff --git a/SourceCode/Bond/Servo/CEqDateTimeSetCmdStep.h b/SourceCode/Bond/Servo/CEqDateTimeSetCmdStep.h
index b110a05..ea7a070 100644
--- a/SourceCode/Bond/Servo/CEqDateTimeSetCmdStep.h
+++ b/SourceCode/Bond/Servo/CEqDateTimeSetCmdStep.h
@@ -7,7 +7,7 @@
 	{
 	public:
 		CEqDateTimeSetCmdStep();
-		~CEqDateTimeSetCmdStep();
+		virtual ~CEqDateTimeSetCmdStep();
 
 	public:
 		void setDateTimeDev(int nDev);
diff --git a/SourceCode/Bond/Servo/CEqJobEventStep.h b/SourceCode/Bond/Servo/CEqJobEventStep.h
index 71eb425..c0cbace 100644
--- a/SourceCode/Bond/Servo/CEqJobEventStep.h
+++ b/SourceCode/Bond/Servo/CEqJobEventStep.h
@@ -8,7 +8,7 @@
 	{
 	public:
 		CEqJobEventStep();
-		~CEqJobEventStep();
+		virtual ~CEqJobEventStep();
 
 	public:
 		virtual void getAttributeVector(CAttributeVector& attrubutes);
diff --git a/SourceCode/Bond/Servo/CEqModeChangeStep.h b/SourceCode/Bond/Servo/CEqModeChangeStep.h
index 420014d..6531261 100644
--- a/SourceCode/Bond/Servo/CEqModeChangeStep.h
+++ b/SourceCode/Bond/Servo/CEqModeChangeStep.h
@@ -7,7 +7,7 @@
 	{
 	public:
 		CEqModeChangeStep();
-		~CEqModeChangeStep();
+		virtual ~CEqModeChangeStep();
 
 	public:
 		void setEqModeDev(int nDev);
diff --git a/SourceCode/Bond/Servo/CEqModeStep.h b/SourceCode/Bond/Servo/CEqModeStep.h
index 1bc611d..cfd461c 100644
--- a/SourceCode/Bond/Servo/CEqModeStep.h
+++ b/SourceCode/Bond/Servo/CEqModeStep.h
@@ -7,7 +7,7 @@
 	{
 	public:
 		CEqModeStep();
-		~CEqModeStep();
+		virtual ~CEqModeStep();
 
 	public:
 		virtual void getAttributeVector(CAttributeVector& attrubutes);
diff --git a/SourceCode/Bond/Servo/CEqPortChangeStep.h b/SourceCode/Bond/Servo/CEqPortChangeStep.h
index 27f7a99..b1b3598 100644
--- a/SourceCode/Bond/Servo/CEqPortChangeStep.h
+++ b/SourceCode/Bond/Servo/CEqPortChangeStep.h
@@ -6,7 +6,7 @@
 	{
 	public:
 		CEqPortChangeStep();
-		~CEqPortChangeStep();
+		virtual ~CEqPortChangeStep();
 
 	public:
 		virtual void getAttributeVector(CAttributeVector& attrubutes);
diff --git a/SourceCode/Bond/Servo/CEqProcessStep.h b/SourceCode/Bond/Servo/CEqProcessStep.h
index d16a5a0..972b6c2 100644
--- a/SourceCode/Bond/Servo/CEqProcessStep.h
+++ b/SourceCode/Bond/Servo/CEqProcessStep.h
@@ -8,7 +8,7 @@
 	{
 	public:
 		CEqProcessStep();
-		~CEqProcessStep();
+		virtual ~CEqProcessStep();
 
 	public:
 		void getAttributeVector(CAttributeVector& attrubutes);
diff --git a/SourceCode/Bond/Servo/CEqReadIntStep.h b/SourceCode/Bond/Servo/CEqReadIntStep.h
index b3206c0..6c6589a 100644
--- a/SourceCode/Bond/Servo/CEqReadIntStep.h
+++ b/SourceCode/Bond/Servo/CEqReadIntStep.h
@@ -11,7 +11,7 @@
 	public:
 		CEqReadIntStep();
 		CEqReadIntStep(int dataType, int dev);
-		~CEqReadIntStep();
+		virtual ~CEqReadIntStep();
 
 	public:
 		virtual void getAttributeVector(CAttributeVector& attrubutes);
diff --git a/SourceCode/Bond/Servo/CEqReadStep.h b/SourceCode/Bond/Servo/CEqReadStep.h
index 567f1cf..bab69cd 100644
--- a/SourceCode/Bond/Servo/CEqReadStep.h
+++ b/SourceCode/Bond/Servo/CEqReadStep.h
@@ -18,7 +18,7 @@
 	public:
 		CEqReadStep();
 		CEqReadStep(int dev, size_t readSize, ONREAD onReadBlock);
-		~CEqReadStep();
+		virtual ~CEqReadStep();
 
 	public:
 		virtual void getAttributeVector(CAttributeVector& attrubutes);
diff --git a/SourceCode/Bond/Servo/CEqStatusStep.h b/SourceCode/Bond/Servo/CEqStatusStep.h
index f99e813..3423e84 100644
--- a/SourceCode/Bond/Servo/CEqStatusStep.h
+++ b/SourceCode/Bond/Servo/CEqStatusStep.h
@@ -10,7 +10,7 @@
 	{
 	public:
 		CEqStatusStep();
-		~CEqStatusStep();
+		virtual ~CEqStatusStep();
 
 	public:
 		virtual void getAttributeVector(CAttributeVector& attrubutes);
diff --git a/SourceCode/Bond/Servo/CEqVCREnableStep.h b/SourceCode/Bond/Servo/CEqVCREnableStep.h
index ebd605d..c4065eb 100644
--- a/SourceCode/Bond/Servo/CEqVCREnableStep.h
+++ b/SourceCode/Bond/Servo/CEqVCREnableStep.h
@@ -7,7 +7,7 @@
 	{
 	public:
 		CEqVCREnableStep();
-		~CEqVCREnableStep();
+		virtual ~CEqVCREnableStep();
 
 	public:
 		void setEqVCRModeDev(int nDev);
diff --git a/SourceCode/Bond/Servo/CEqVcrEventStep.h b/SourceCode/Bond/Servo/CEqVcrEventStep.h
index b7b64a4..6e510a0 100644
--- a/SourceCode/Bond/Servo/CEqVcrEventStep.h
+++ b/SourceCode/Bond/Servo/CEqVcrEventStep.h
@@ -8,7 +8,7 @@
 	{
 	public:
 		CEqVcrEventStep();
-		~CEqVcrEventStep();
+		virtual ~CEqVcrEventStep();
 
 	public:
 		virtual void getAttributeVector(CAttributeVector& attrubutes);
diff --git a/SourceCode/Bond/Servo/CEqWriteStep.h b/SourceCode/Bond/Servo/CEqWriteStep.h
index 602408b..2ec74ba 100644
--- a/SourceCode/Bond/Servo/CEqWriteStep.h
+++ b/SourceCode/Bond/Servo/CEqWriteStep.h
@@ -13,7 +13,7 @@
 	{
 	public:
 		CEqWriteStep();
-		~CEqWriteStep();
+		virtual ~CEqWriteStep();
 
 	public:
 		void setDataDev(int nDev);
diff --git a/SourceCode/Bond/Servo/CEquipment.cpp b/SourceCode/Bond/Servo/CEquipment.cpp
index e4d8c07..7cb8a5b 100644
--- a/SourceCode/Bond/Servo/CEquipment.cpp
+++ b/SourceCode/Bond/Servo/CEquipment.cpp
@@ -27,7 +27,7 @@
 
 	CEquipment::CEquipment() : m_nID(0), m_strName(""), m_strDescription(""), m_station(0, 255)
 	{
-		m_listener = { nullptr, nullptr, nullptr, nullptr, nullptr };
+		m_listener = { };
 		m_alive = { FALSE, 0, FALSE };
 		m_bCimState = FALSE;
 		m_bUpstreamInline = FALSE;
@@ -43,10 +43,13 @@
 
 	CEquipment::~CEquipment()
 	{
-		for (auto item : m_glassList) {
-			item->release();
+		for (int i = 0; i < SLOT_MAX; i++) {
+			CContext* pContext = m_slot[i].getContext();
+			if (pContext != nullptr) {
+				pContext->release();
+				m_slot[i].setContext(nullptr);
+			}
 		}
-		m_glassList.clear();
 
 		for (auto item : m_mapStep) {
 			delete item.second;
@@ -68,11 +71,7 @@
 
 	void CEquipment::setListener(EquipmentListener listener)
 	{
-		m_listener.onAlive = listener.onAlive;
-		m_listener.onCimStateChanged = listener.onCimStateChanged;
-		m_listener.onAlarm = listener.onAlarm;
-		m_listener.onDataChanged = listener.onDataChanged;
-		m_listener.onVcrEventReport = listener.onVcrEventReport;
+		m_listener = listener;
 	}
 
 	void CEquipment::setCcLink(CCCLinkIEControl* pCcLink)
@@ -149,6 +148,7 @@
 	{
 		initPins();
 		initSteps();
+		initSlots();
 		for (auto item : m_mapStep) {
 			item.second->init();
 		}
@@ -251,9 +251,19 @@
 				std::to_string((int)item->getType()).c_str(), "", weight++));
 		}
 
-		for (auto item : m_glassList) {
-			attrubutes.addAttribute(new CAttribute("Glass",
-				item->getID().c_str(), "", weight++));
+		for (int i = 0; i < SLOT_MAX; i++) {
+			if (!m_slot[i].isEnable()) continue;
+
+			CGlass* pGlass = (CGlass*)m_slot[i].getContext();
+			if (pGlass == nullptr) {
+				attrubutes.addAttribute(new CAttribute(m_slot[i].getName().c_str(),
+					"", "", weight++));
+			}
+			else {
+				attrubutes.addAttribute(new CAttribute(m_slot[i].getName().c_str(),
+					pGlass->getID().c_str(), "", weight++));
+			}
+
 		}
 	}
 
@@ -305,24 +315,26 @@
 	{
 		if (ar.IsStoring()) {
 			Lock();
-			int count = (int)m_glassList.size();
-			ar << count;
-			for (auto item : m_glassList) {
-				item->serialize(ar);
+			for (int i = 0; i < SLOT_MAX; i++) {
+				m_slot[i].serialize(ar);
+				if (m_slot[i].getContext() != nullptr) {
+					((CGlass*)m_slot[i].getContext())->serialize(ar);
+				}
 			}
 			Unlock();
 		}
 		else {
-			// addGlassToList前不需要上锁,因其内部有锁
-			int count;
-			ar >> count;
-			for (int i = 0; i < count; i++) {
-				CGlass* pGlass = theApp.m_model.m_glassPool.allocaGlass();
-				pGlass->serialize(ar);
-				addGlassToList(pGlass);
+			for (int i = 0; i < SLOT_MAX; i++) {
+				m_slot[i].serialize(ar);
+				if (m_slot[i].getContext() != nullptr) {
+					CGlass* pGlass = theApp.m_model.m_glassPool.allocaGlass();
+					pGlass->serialize(ar);
+					m_slot[i].setContext(pGlass);
+				}
 			}
 			
 			// 梳理各玻璃之间的绑定关系
+			/*
 			Lock();
 			std::list<CGlass*> list = m_glassList;
 			for (auto item : list) {
@@ -337,6 +349,7 @@
 				}
 			}
 			Unlock();
+			*/
 		}
 	}
 
@@ -690,175 +703,10 @@
 		// 测试
 		if (code == FLOW_TEST) {
 			AfxMessageBox(pIntent->getMsg());
-			return FLOW_ACCEPT;
 		}
 
-
-		// 信号
-		if (code == FLOW_SIGNAL) {
-			return FLOW_ACCEPT;
-		}
-
-
-		// 数据
-		if (code == FLOW_SIGNAL) {
-			return FLOW_ACCEPT;
-		}
-
-
-		// 物料
-		if (code == FLOW_MOVE_MATERIAL) {
-			CGlass* pGlass = (CGlass*)pIntent->getContext();
-			ASSERT(pGlass);
-			if (!glassWillArrive(pGlass)) {
-				return FLOW_REJECT;
-			}
-			return glassArrived(pGlass);
-		}
-
-
-
-		return FLOW_ACCEPT;
-	}
-
-	int CEquipment::outputGlass(int port)
-	{
-		CPin* pOutPin = nullptr;
-		if (port == 0) {
-			pOutPin = getPin("Out");
-			if (pOutPin == nullptr) {
-				pOutPin = getPin("Out1");
-			}
-		}
-		else if (port == 1) {
-			pOutPin = getPin("Out2");
-		}
-		if (pOutPin == nullptr) {
-			return -1;
-		}
-
-
-		// 模拟取出第一张Panel,传送到下一环节
-		ULONGLONG time = CToolUnits::getTimestamp();
-		Lock();
-		if (m_glassList.empty()) {
-			Unlock();
-			return -2;
-		}
-		CGlass* pContext = m_glassList.front();
-		pContext->addRef();
-
-		CIntent intent(FLOW_MOVE_MATERIAL, "", pContext);
-		int nRet = pOutPin->sendIntent(&intent);
-		if (nRet == FLOW_REJECT) {
-			LOGE("<CEquipment>对方拒绝接收Intent.");
-		}
-		else if (nRet == FLOW_ACCEPT) {
-			CPath* pPath = pContext->getPathWithSiteID(m_nID);
-			if (pPath != nullptr) {
-				pPath->setOutTime(time);
-			}
-			m_glassList.pop_front();
-			pContext->release();		// 添加到列队时addRef, 取出时release
-			if (m_listener.onDataChanged != nullptr) {
-				m_listener.onDataChanged(this, 0);
-			}
-		}
-
-		pContext->release();
-		Unlock();
 
 		return 0;
-	}
-
-	BOOL CEquipment::glassWillArrive(CGlass* pGlass)
-	{
-		return TRUE;
-	}
-
-	int CEquipment::glassArrived(CGlass* pGlass)
-	{
-		Lock();
-		pGlass->addPath(m_nID);
-		pGlass->addRef();
-		m_glassList.push_back(pGlass);
-		Unlock();
-
-		if (m_listener.onDataChanged != nullptr) {
-			m_listener.onDataChanged(this, 0);
-		}
-
-		return FLOW_ACCEPT;
-	}
-
-	void CEquipment::addGlassToList(CGlass* pGlass)
-	{
-		ASSERT(pGlass);
-
-		Lock();
-		pGlass->addRef();
-		m_glassList.push_back(pGlass);
-		Unlock();
-
-		if (m_listener.onDataChanged != nullptr) {
-			m_listener.onDataChanged(this, 0);
-		}
-	}
-
-	CGlass* CEquipment::getGlassFromList(const char* pszId)
-	{
-		CGlass* pGlass = nullptr;
-		Lock();
-		for (auto item : m_glassList) {
-			if (item->getID().compare(pszId) == 0) {
-				pGlass = item;
-				break;
-			}
-		}
-		Unlock();
-
-		return pGlass;
-	}
-
-	BOOL CEquipment::removeClass(CGlass* pGlass)
-	{
-		Lock();
-		bool bExist = std::find(m_glassList.begin(), m_glassList.end(), pGlass) != m_glassList.end();
-		if (bExist) {
-			pGlass->addPath(EQ_ID_OPERATOR_REMOVE);
-			pGlass->release();
-			m_glassList.remove(pGlass);
-		}
-		Unlock();
-
-		if (bExist && m_listener.onDataChanged != nullptr) {
-			m_listener.onDataChanged(this, 0);
-		}
-
-		return bExist;
-	}
-
-	void CEquipment::getGlassList(std::list<CGlass*>& list)
-	{
-		Lock();
-		for (auto item : m_glassList) {
-			item->addRef();
-			list.push_back(item);
-		}
-		Unlock();
-	}
-
-	CGlass* CEquipment::getFrontGlass()
-	{
-		CGlass* pGlass = nullptr;
-
-		Lock();
-		if (!m_glassList.empty()) {
-			pGlass = m_glassList.front();
-		}
-		Unlock();
-
-		return pGlass;
 	}
 
 	int CEquipment::fetchedOutJob(CJobDataB* pJobDataB)
@@ -869,16 +717,12 @@
 
 		// 找到指定的glass id, 
 		Lock();
-		if (m_glassList.empty()) {
-			Unlock();
-			return -2;
-		}
-
 		CGlass* pContext = nullptr;
-		for (auto iter = m_glassList.begin(); iter != m_glassList.end(); iter++) {
-			if ((*iter)->getID().compare(pJobDataB->getGlassId()) == 0) {
-				pContext = (*iter);
-				m_glassList.erase(iter);
+		for (int i = 0; i < SLOT_MAX; i++) {
+			CGlass* pGlass = (CGlass*)m_slot[i].getContext();
+			if (pGlass != nullptr && compareJobDataB(pJobDataB, pGlass->getJobDataB())) {
+				pContext = pGlass;
+				m_slot[i].setContext(nullptr);
 				break;
 			}
 		}
@@ -890,10 +734,11 @@
 		// 如果此玻璃已经贴合,贴合的玻璃也要从列表中移除
 		CGlass* pBuddy = pContext->getBuddy();
 		if (pBuddy != nullptr) {
-			for (auto iter = m_glassList.begin(); iter != m_glassList.end(); iter++) {
-				if ((*iter)->getID().compare(pBuddy->getID()) == 0) {
-					(*iter)->release();
-					m_glassList.erase(iter);
+			for (int i = 0; i < SLOT_MAX; i++) {
+				CGlass* pGlass = (CGlass*)m_slot[i].getContext();
+				if (pGlass != nullptr && compareJobDataB(pBuddy->getJobDataB(), pGlass->getJobDataB())) {
+					pContext->release();
+					m_slot[i].setContext(nullptr);
 					break;
 				}
 			}
@@ -905,13 +750,13 @@
 		Unlock();
 
 		if (m_listener.onDataChanged != nullptr) {
-			m_listener.onDataChanged(this, 0);
+			m_listener.onDataChanged(this, EDCC_FETCHOUT_JOB);
 		}
 
 		return 0;
 	}
 
-	int CEquipment::storedJob(CJobDataB* pJobDataB)
+	int CEquipment::storedJob(CJobDataB* pJobDataB, short& putSlot)
 	{
 		if (m_pArm == nullptr) {
 			return -1;
@@ -926,13 +771,13 @@
 		ASSERT(pGlass);
 		Lock();
 		pGlass->addPath(m_nID);
-		pGlass->addRef();					// 加入list,addRef
-		m_glassList.push_back(pGlass);
+		m_slot[putSlot - 1].setContext(pGlass);
 		pGlass->release();				// tempFetchOut需要调用一次release
 		Unlock();
 
 
 		// 如果此玻璃已经贴合,贴合的玻璃也要从加入到列表中
+		/*
 		CGlass* pBuddy = pGlass->getBuddy();
 		if (pBuddy != nullptr) {
 			Lock();
@@ -941,18 +786,24 @@
 			m_glassList.push_back(pBuddy);
 			Unlock();
 		}
-
+		*/
 
 		if (m_listener.onDataChanged != nullptr) {
-			m_listener.onDataChanged(this, 0);
+			m_listener.onDataChanged(this, EDCC_STORED_JOB);
 		}
-
+		
 		return 0;
 	}
 
-	BOOL CEquipment::isGlassListEmpty()
+	BOOL CEquipment::hasGlass()
 	{
-		return m_glassList.empty();
+		for (int i = 0; i < SLOT_MAX; i++) {
+			if (m_slot[i].isEnable() && !m_slot[i].isEmpty()) {
+				return TRUE;
+			}
+		}
+
+		return FALSE;
 	}
 
 	bool CEquipment::isAlarmStep(SERVO::CStep* pStep)
@@ -1099,7 +950,7 @@
 			return -1;
 		}
 
-		unsigned short operationMode = (unsigned short)(mode + getIndexerOperationModeBaseValue());
+		unsigned short operationMode = (unsigned short)((unsigned short)mode + getIndexerOperationModeBaseValue());
 		LOGI("<CEquipment-%s>准备设置indexerOperationMode<%d>", m_strName.c_str(), (int)mode);
 		if (onWritedBlock != nullptr) {
 			pStep->writeShort(operationMode, onWritedBlock);
@@ -1168,6 +1019,93 @@
 			return 0;
 			});
 		return 0;
+	}
+
+	CSlot* CEquipment::getAvailableSlot()
+	{
+		for (int i = 0; i < SLOT_MAX; i++) {
+			if (!m_slot[i].isEnable()) continue;
+			if (m_slot[i].isLock()) continue;
+			if (!m_slot[i].isEmpty()) continue;
+
+			return &m_slot[i];
+		}
+
+		return nullptr;
+	}
+
+	CSlot* CEquipment::getAvailableSlotForGlass(MaterialsType type)
+	{
+		for (int i = 0; i < SLOT_MAX; i++) {
+			if (!m_slot[i].isEnable()) continue;
+			if (m_slot[i].isLock()) continue;
+			if (!m_slot[i].isEmpty()) continue;
+
+			MaterialsType slotType = m_slot[i].getType();
+			if (type == MaterialsType::G1 && slotType == MaterialsType::G2) continue;
+			if (type == MaterialsType::G2 && slotType == MaterialsType::G1) continue;
+
+			return &m_slot[i];
+		}
+
+		return nullptr;
+	}
+
+	CSlot* CEquipment::getNonEmptySlot(MaterialsType putSlotType)
+	{
+		for (int i = 0; i < SLOT_MAX; i++) {
+			if (!m_slot[i].isEnable()) continue;
+			if (m_slot[i].isLock()) continue;
+			CGlass* pGlass = (CGlass*)m_slot[i].getContext();
+			if (pGlass == nullptr) continue;
+
+			MaterialsType glassType = pGlass->getType();
+			if (glassType == MaterialsType::G1 && putSlotType == MaterialsType::G2) continue;
+			if (glassType == MaterialsType::G2 && putSlotType == MaterialsType::G1) continue;
+
+			return &m_slot[i];
+		}
+
+		return nullptr;
+	}
+
+	CGlass* CEquipment::getGlassFromSlot(int slotNo)
+	{
+		CSlot* pSlot = nullptr;
+		for (int i = 0; i < SLOT_MAX; i++) {
+			if (!m_slot[i].isEnable()) continue;
+			if (m_slot[i].getNo() != slotNo) continue;
+			pSlot = &m_slot[i];
+			break;
+		}
+
+		if (pSlot != nullptr) {
+			return (CGlass*)pSlot->getContext();
+		}
+
+		return nullptr;
+	}
+
+	CGlass* CEquipment::getAnyGlass()
+	{
+		CSlot* pSlot = nullptr;
+		for (int i = 0; i < SLOT_MAX; i++) {
+			if (!m_slot[i].isEnable()) continue;
+			CGlass* pGlass = (CGlass*)m_slot[i].getContext();
+			if (pGlass == nullptr) continue;
+			return pGlass;
+		}
+
+		return nullptr;
+	}
+
+	BOOL CEquipment::canPlaceGlassInSlot(const short slotIndex)
+	{
+		if (slotIndex >= SLOT_MAX) return FALSE;
+		if (!m_slot[slotIndex].isEnable()) return FALSE;
+		if (m_slot[slotIndex].getContext() != nullptr) return FALSE;
+
+		return TRUE;
 	}
 
 	short CEquipment::decodeRecipeListReport(const char* pszData, size_t size)
@@ -1299,10 +1237,14 @@
 		return index;
 	}
 
-	int CEquipment::onPreFetchedOutJob(int port, CJobDataB* pJobDataB)
+	BOOL CEquipment::onPreFetchedOutJob(int port, CJobDataB* pJobDataB)
 	{
 		LOGI("<CEquipment-%s>onPreFetchedOutJob:port:%d|GlassId:%s",
 			m_strName.c_str(), port, pJobDataB->getGlassId().c_str());
+		if (m_listener.onPreFethedOutJob != nullptr) {
+			return m_listener.onPreFethedOutJob(this, pJobDataB);
+		}
+
 		return TRUE;
 	}
 
@@ -1385,10 +1327,39 @@
 		return 0;
 	}
 
-	int CEquipment::onPreStoredJob(int port, CJobDataB* pJobDataB)
+	int CEquipment::onPreStoredJob(int port, CJobDataB* pJobDataB, short& putSlot)
 	{
 		LOGI("<CEquipment-%s>onPreStoredJob:port:%d|GlassId:%s",
 			m_strName.c_str(), port, pJobDataB->getGlassId().c_str());
+
+		CJobDataS* pJobDataS = getJobDataS(pJobDataB->getCassetteSequenceNo(), pJobDataB->getJobSequenceNo());
+		if (pJobDataS == nullptr) {
+			LOGE("<CFliper-%s>onPreFetchedOutJob,找不到对应的JobDataS(CassetteSequenceNo:%d, JobSequenceNo:%d), 注意排查风险!", m_strName.c_str(),
+				pJobDataB->getCassetteSequenceNo(), pJobDataB->getJobSequenceNo());
+			return FALSE;
+		}
+
+		// 如果没有可用位置,报错
+		Lock();
+		CSlot* pSlot = getAvailableSlotForGlass((MaterialsType)pJobDataS->getMaterialsType());
+		if (pSlot == nullptr) {
+			Unlock();
+			LOGE("<CFliper-%s>onPreFetchedOutJob,找不到匹配的Slot,不能进料,请注意风险!", m_strName.c_str());
+			return FALSE;
+		}
+		Unlock();
+
+
+		if (m_listener.onPreStoredJob != nullptr) {
+			if (!m_listener.onPreStoredJob(this, pJobDataB, putSlot)) {
+				return FALSE;
+			}
+
+			if(!canPlaceGlassInSlot(putSlot - 1)) {
+				return FALSE;
+			}
+		}
+
 		return TRUE;
 	}
 
@@ -1397,10 +1368,11 @@
 		LOGI("<CEquipment-%s>onStore:port:%d|GlassId:%s",
 			m_strName.c_str(), port, pJobDataB->getGlassId().c_str());
 
-		BOOL bCheck = onPreStoredJob(port, pJobDataB);
+		short putSlot = 0;
+		BOOL bCheck = onPreStoredJob(port, pJobDataB, putSlot);
 		if (bCheck) {
 			addJobDataB(pJobDataB);
-			return storedJob(pJobDataB);
+			return storedJob(pJobDataB, putSlot);
 		}
 
 		// 数据异常,处理或显示
@@ -1509,4 +1481,17 @@
 
 		return nullptr;
 	}
+
+	BOOL CEquipment::compareJobDataB(CJobDataB* pJobDataB1, CJobDataB* pJobDataB2)
+	{
+		ASSERT(pJobDataB1);
+		ASSERT(pJobDataB2);
+
+		if (pJobDataB1->getCassetteSequenceNo() != pJobDataB2->getCassetteSequenceNo())
+			return FALSE;
+		if (pJobDataB1->getJobSequenceNo() != pJobDataB2->getJobSequenceNo())
+			return FALSE;
+
+		return TRUE;
+	}
 }
\ No newline at end of file
diff --git a/SourceCode/Bond/Servo/CEquipment.h b/SourceCode/Bond/Servo/CEquipment.h
index 6357114..df7e015 100644
--- a/SourceCode/Bond/Servo/CEquipment.h
+++ b/SourceCode/Bond/Servo/CEquipment.h
@@ -1,5 +1,6 @@
 #pragma once
 #include "Log.h"
+#include "ServoCommo.h"
 #include "CCLinkIEControl.h"
 #include "CSample.h"
 #include "CPin.h"
@@ -33,18 +34,18 @@
 #include "CJobDataS.h"
 #include "CProcessData.h"
 #include "CPortStatusReport.h"
+#include "CSlot.h"
 
 
 namespace SERVO {
-#define BLOCK_BUFFER_MAX			1024
-#define ALIVE_TIMEOUT				15
-#define VCR_MAX						1
-#define ARM_ALL						99
+#define SLOT_MAX		12
 
 	typedef std::function<void(void* pEiuipment, BOOL bAlive)> ONALIVE;
 	typedef std::function<void(void* pEiuipment, int code)> ONDATACHANGED;
 	typedef std::function<void(void* pEiuipment, int state, int alarmId, int unitId, int level)> ONALARM;
 	typedef std::function<void(void* pEiuipment, void* pReport)> ONVCREVENTREPORT;
+	typedef std::function<BOOL(void* pEiuipment, CJobDataB* pJobDataB)> ONPREFETCHEDOUTJOB;
+	typedef std::function<BOOL(void* pEiuipment, CJobDataB* pJobDataB, short& putSlot)> ONPRESTOREDJOB;
 	typedef struct _EquipmentListener
 	{
 		ONALIVE				onAlive;
@@ -52,80 +53,16 @@
 		ONALARM				onAlarm;
 		ONDATACHANGED		onDataChanged;
 		ONVCREVENTREPORT	onVcrEventReport;
+		ONPREFETCHEDOUTJOB	onPreFethedOutJob;
+		ONPRESTOREDJOB		onPreStoredJob;
 	} EquipmentListener;
 
-	// Memory Block 结构体定义
-	typedef struct _MemoryBlock {
-		unsigned int type;
-		unsigned int start;
-		unsigned int end;
-		unsigned int size;
-		char buffer[BLOCK_BUFFER_MAX];
-	} MemoryBlock;
-
-	// ALIVE
-	typedef struct _ALIVE {
-		BOOL flag;
-		int count;
-		BOOL alive;
-	} ALIVE;
-
-	enum DISPATCHING_MODE {
-		EAS = 1,
-		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, 
-		Move,
-		Get,
-		Put,
-		One_Action_Exchange,
-		Two_Action_Exchange,
-		Command_Clear,
-		Batch_get,
-		Batch_put
-	};
-
-	enum VCR_Reply_Code {
-		OK = 1,
-		NG,
-		Job_Data_Request,
-		VCR_Mismatch
-	};
-
-	// Robot cmd param
-#define ROBOT_CMD_PARAM_SIZE		16			/* 防止以后修改ROBOT_CMD_PARAM为不是4的整数倍 */
-	typedef struct _ROBOT_CMD_PARAM {
-		short sequenceNo;
-		short rcmd;
-		short armNo;
-		short getPosition;
-		short putPosition;
-		short getSlotNo;
-		short putSlotNo;
-		short subCmd;
-	} ROBOT_CMD_PARAM;
 
 	class CEquipment
 	{
 	public:
 		CEquipment();
 		virtual ~CEquipment();
-
 
 	public:
 		virtual const char* getClassName() = 0;
@@ -158,6 +95,7 @@
 		virtual void term();
 		virtual void initPins() = 0;
 		virtual void initSteps();
+		virtual void initSlots() = 0;
 		virtual void onTimer(UINT nTimerid);
 		virtual void serialize(CArchive& ar);
 		virtual void onReceiveLBData(const char* pszData, size_t size);
@@ -167,23 +105,16 @@
 		std::vector<CPin*>& CEquipment::getInputPins();
 		std::vector<CPin*>& CEquipment::getOutputPins();
 		virtual int recvIntent(CPin* pPin, CIntent* pIntent);
-		virtual BOOL glassWillArrive(CGlass* pGlass);
-		virtual int outputGlass(int port);
-		virtual int glassArrived(CGlass* pGlass);
 		virtual int fetchedOutJob(CJobDataB* pJobDataB);
-		virtual int storedJob(CJobDataB* pJobDataB);
+		virtual int storedJob(CJobDataB* pJobDataB, short& putSlot);
 		virtual int onReceivedJob(int port, CJobDataS* pJobDataS);
 		virtual int onSentOutJob(int port, CJobDataS* pJobDataS);
 		virtual BOOL onPreFetchedOutJob(int port, CJobDataB* pJobDataB);
 		virtual int onFetchedOutJob(int port, CJobDataB* pJobDataB);
-		virtual BOOL onPreStoredJob(int port, CJobDataB* pJobDataB);
+		virtual BOOL onPreStoredJob(int port, CJobDataB* pJobDataB, short& putSlot);
 		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();
-		BOOL removeClass(CGlass* pGlass);
 		bool isAlarmStep(SERVO::CStep* pStep);
 		bool isVcrEventStep(SERVO::CStep* pStep);
 		bool isCassetteTransferStateStep(SERVO::CStep* pStep);
@@ -214,8 +145,27 @@
 		// unitNo: 0:local; Others:unit No
 		int recipeParameterRequest(short masterRecipeId, short localRecipeId, short unitNo);
 
-	public:
-		BOOL isGlassListEmpty();
+		// 获取一个可用的槽位
+		CSlot* getAvailableSlot();
+
+		// 获取一个指定物料类型(G1,G2,G1&G2)的空槽位
+		CSlot* getAvailableSlotForGlass(MaterialsType type);
+
+		// 获取一个指定物料类型(G1,G2,G1&G2)的非空槽位
+		CSlot* getNonEmptySlot(MaterialsType type);
+
+		// 获取玻璃物料
+		CGlass* getGlassFromSlot(int slotNo);
+		CGlass* getAnyGlass();
+
+		// 验证玻璃和槽是否匹配
+		BOOL ValidateGlassSlotMatch();
+
+		// 是否有玻璃
+		BOOL hasGlass();
+
+		// 指定槽位是否可以放置玻璃
+		BOOL canPlaceGlassInSlot(const short slotIndex);
 
 
 	// 以下为从CC-Link读取到的Bit标志位检测函数
@@ -233,7 +183,6 @@
 		inline void Unlock() { LeaveCriticalSection(&m_criticalSection); }
 		BOOL isBitOn(const char* pszData, size_t size, int index);
 		inline BOOL equalBool(BOOL b1, BOOL b2);
-		void addGlassToList(CGlass* pGlass);
 		short decodeRecipeListReport(const char* pszData, size_t size);
 		short decodeRecipeParameterReport(const char* pszData, size_t size);
 		int decodeProcessDataReport(CStep* pStep, const char* pszData, size_t size);
@@ -248,6 +197,7 @@
 		int addJobDataS(CJobDataS* pJobDataS);
 		int removeJobDataS(int nCassetteSequenceNo, int nJobSequenceNo);
 		CJobDataS* getJobDataS(int nCassetteSequenceNo, int nJobSequenceNo);
+		BOOL compareJobDataB(CJobDataB* pJobDataB1, CJobDataB* pJobDataB2);
 
 	protected:
 		EquipmentListener m_listener;
@@ -260,7 +210,6 @@
 		MemoryBlock m_blockWriteBit;
 		std::vector<CPin*> m_inputPins;
 		std::vector<CPin*> m_outputPins;
-		std::list<CGlass*> m_glassList;
 
 
 		// 以下为从CC-Link读取到的Bit标志位
@@ -278,6 +227,7 @@
 		std::map<unsigned int, CStep*> m_mapStep;
 		int m_nBaseAlarmId;
 		CRecipesManager m_recipesManager;
+		CSlot m_slot[SLOT_MAX];
 
 	private:
 		CEquipment* m_pArm;
diff --git a/SourceCode/Bond/Servo/CEquipmentPage2.cpp b/SourceCode/Bond/Servo/CEquipmentPage2.cpp
index 3bffbe7..e28bc78 100644
--- a/SourceCode/Bond/Servo/CEquipmentPage2.cpp
+++ b/SourceCode/Bond/Servo/CEquipmentPage2.cpp
@@ -80,16 +80,14 @@
 
 
 	ASSERT(m_pEquipment);
-	std::list<SERVO::CGlass*> list;
-	m_pEquipment->getGlassList(list);
-	for (auto item : list) {
-		item->addRef();				
-		item->release();		// 閲婃斁list涓殑寮曠敤
+	for (int i = 0; i < SLOT_MAX; i++) {
+		SERVO::CGlass* pGlass = m_pEquipment->getGlassFromSlot(i+1);
+		pGlass->addRef();
 
-		SERVO::CGlass* pBuddy = item->getBuddy();
+		SERVO::CGlass* pBuddy = pGlass->getBuddy();
 		int index = m_listCtrl.InsertItem(m_listCtrl.GetItemCount(), _T(""));
-		m_listCtrl.SetItemData(index, (DWORD_PTR)item);
-		m_listCtrl.SetItemText(index, 1, item->getID().c_str());
+		m_listCtrl.SetItemData(index, (DWORD_PTR)pGlass);
+		m_listCtrl.SetItemText(index, 1, pGlass->getID().c_str());
 		if (pBuddy != nullptr) {
 			m_listCtrl.SetItemText(index, 2, pBuddy->getID().c_str());
 		}
@@ -172,6 +170,7 @@
 
 void CEquipmentPage2::OnBnClickedButtonRemove()
 {
+	/*
 	int index = GetSelectedItemIndex();
 	if (index >= 0) {
 		SERVO::CGlass* pGlass = (SERVO::CGlass*)m_listCtrl.GetItemData(index);
@@ -182,4 +181,5 @@
 			m_listCtrl.DeleteItem(index);
 		}
 	}
+	*/
 }
diff --git a/SourceCode/Bond/Servo/CFliper.cpp b/SourceCode/Bond/Servo/CFliper.cpp
index 891aac4..4065835 100644
--- a/SourceCode/Bond/Servo/CFliper.cpp
+++ b/SourceCode/Bond/Servo/CFliper.cpp
@@ -38,6 +38,16 @@
 		addPin(SERVO::PinType::OUTPUT, _T("Out"));
 	}
 
+	// 必须要实现的虚函数,在此初始化Slot信息
+	void CFliper::initSlots()
+	{
+		m_slot[0].enable();
+		m_slot[0].setPosition(m_nID);
+		m_slot[0].setNo(1);
+		m_slot[0].setName("Slot 1(G2)");
+		m_slot[0].setType(MaterialsType::G2);
+	}
+
 	void CFliper::onTimer(UINT nTimerid)
 	{
 		CEquipment::onTimer(nTimerid);
@@ -56,40 +66,5 @@
 	int CFliper::recvIntent(CPin* pPin, CIntent* pIntent)
 	{
 		return __super::recvIntent(pPin, pIntent);
-	}
-
-	BOOL CFliper::glassWillArrive(CGlass* pGlass)
-	{
-		BOOL bRet = __super::glassWillArrive(pGlass);
-		if (!bRet) {
-			return FALSE;
-		}
-
-		return m_glassList.empty();
-	}
-
-	BOOL CFliper::onPreStoredJob(int port, CJobDataB* pJobDataB)
-	{
-		CJobDataS* pJobDataS = getJobDataS(pJobDataB->getCassetteSequenceNo(), pJobDataB->getJobSequenceNo());
-		if (pJobDataS == nullptr) {
-			LOGE("<CFliper-%s>onPreFetchedOutJob,找不到对应的JobDataS(CassetteSequenceNo:%d, JobSequenceNo:%d), 注意排查风险!", m_strName.c_str(), 
-				pJobDataB->getCassetteSequenceNo(), pJobDataB->getJobSequenceNo());
-			return FALSE;
-		}
-
-		// 当前不能有任何玻璃,且当前准备进的片是G2
-		Lock();
-		if (!m_glassList.empty()) {
-			Unlock();
-			LOGE("<CFliper-%s>onPreFetchedOutJob,当前机器或单元存在玻璃片,不能进料,请注意风险!", m_strName.c_str());
-			return FALSE;
-		}
-
-		if (pJobDataS->getMaterialsType() != (int)MaterialsType::G2) {
-			LOGE("<CFliper-%s>onPreFetchedOutJob,当前机器或单元只能进G2玻璃片,请注意风险!", m_strName.c_str());
-			return FALSE;
-		}
-
-		return TRUE;
 	}
 }
diff --git a/SourceCode/Bond/Servo/CFliper.h b/SourceCode/Bond/Servo/CFliper.h
index 4d3c859..9e7b404 100644
--- a/SourceCode/Bond/Servo/CFliper.h
+++ b/SourceCode/Bond/Servo/CFliper.h
@@ -15,12 +15,11 @@
         virtual void init();
         virtual void term();
         virtual void initPins();
+        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 BOOL glassWillArrive(CGlass* pGlass);
-        virtual BOOL onPreStoredJob(int port, CJobDataB* pJobDataB);
 	};
 }
 
diff --git a/SourceCode/Bond/Servo/CGlassPool.h b/SourceCode/Bond/Servo/CGlassPool.h
index c6e53a9..79cfda6 100644
--- a/SourceCode/Bond/Servo/CGlassPool.h
+++ b/SourceCode/Bond/Servo/CGlassPool.h
@@ -9,7 +9,7 @@
 	{
 	public:
 		CGlassPool();
-		~CGlassPool();
+		virtual ~CGlassPool();
 
 	public:
 		void initPool();
diff --git a/SourceCode/Bond/Servo/CJobDataA.cpp b/SourceCode/Bond/Servo/CJobDataA.cpp
index cf33400..4a1e3f3 100644
--- a/SourceCode/Bond/Servo/CJobDataA.cpp
+++ b/SourceCode/Bond/Servo/CJobDataA.cpp
@@ -6,7 +6,7 @@
 namespace SERVO {
 	CJobDataA::CJobDataA()
 	{
-
+		m_pOwner = nullptr;
 	}
 
 	CJobDataA::~CJobDataA()
@@ -14,6 +14,16 @@
 
 	}
 
+	void* CJobDataA::getOwner()
+	{
+		return m_pOwner;
+	}
+
+	void CJobDataA::setOwner(void* pOwner)
+	{
+		m_pOwner = pOwner;
+	}
+
 	short CJobDataA::getPortNo()
 	{
 		return m_nPortNo;
diff --git a/SourceCode/Bond/Servo/CJobDataA.h b/SourceCode/Bond/Servo/CJobDataA.h
index c3879d4..49c2071 100644
--- a/SourceCode/Bond/Servo/CJobDataA.h
+++ b/SourceCode/Bond/Servo/CJobDataA.h
@@ -8,9 +8,11 @@
 	{
 	public:
 		CJobDataA();
-		~CJobDataA();
+		virtual ~CJobDataA();
 
 	public:
+		void* getOwner();
+		void setOwner(void* pOwner);
 		short getPortNo();
 		std::string& getCarrierId();
 		std::string& getPruductId();
@@ -23,6 +25,7 @@
 		int unserialize(const char* pszBuffer, int nBufferSize);
 
 	private:
+		void* m_pOwner;
 		short m_nPortNo;
 		std::string m_strCarrierId;
 		std::string m_pruductId;
diff --git a/SourceCode/Bond/Servo/CJobDataB.cpp b/SourceCode/Bond/Servo/CJobDataB.cpp
index 596259a..7622790 100644
--- a/SourceCode/Bond/Servo/CJobDataB.cpp
+++ b/SourceCode/Bond/Servo/CJobDataB.cpp
@@ -8,6 +8,7 @@
 	{
 		m_nCassetteSequenceNo = 0;
 		m_nJobSequenceNo = 0;
+		m_pOwner = nullptr;
 	}
 
 	CJobDataB::CJobDataB(CJobDataB&& other) noexcept
@@ -25,6 +26,17 @@
 		m_nCassetteSequenceNo = pScr->m_nCassetteSequenceNo;
 		m_nJobSequenceNo = pScr->m_nJobSequenceNo;
 		m_strGlassId = pScr->m_strGlassId;
+		m_pOwner = pScr->m_pOwner;
+	}
+
+	void* CJobDataB::getOwner()
+	{
+		return m_pOwner;
+	}
+
+	void CJobDataB::setOwner(void* pOwner)
+	{
+		m_pOwner = pOwner;
 	}
 
 	int CJobDataB::getCassetteSequenceNo()
diff --git a/SourceCode/Bond/Servo/CJobDataB.h b/SourceCode/Bond/Servo/CJobDataB.h
index 34945c5..b609376 100644
--- a/SourceCode/Bond/Servo/CJobDataB.h
+++ b/SourceCode/Bond/Servo/CJobDataB.h
@@ -8,9 +8,11 @@
 	public:
 		CJobDataB();
 		CJobDataB::CJobDataB(CJobDataB&& other) noexcept;
-		~CJobDataB();
+		virtual ~CJobDataB();
 
 	public:
+		void* getOwner();
+		void setOwner(void* pOwner);
 		void copy(CJobDataB* pScr);
 		int getCassetteSequenceNo();
 		void setCassetteSequenceNo(int no);
@@ -22,6 +24,7 @@
 		int unserialize(const char* pszBuffer, int nBufferSize);
 
 	private:
+		void* m_pOwner;
 		int m_nCassetteSequenceNo;
 		int m_nJobSequenceNo;
 		std::string m_strGlassId;
diff --git a/SourceCode/Bond/Servo/CJobDataC.cpp b/SourceCode/Bond/Servo/CJobDataC.cpp
index 4781964..54913e7 100644
--- a/SourceCode/Bond/Servo/CJobDataC.cpp
+++ b/SourceCode/Bond/Servo/CJobDataC.cpp
@@ -6,6 +6,7 @@
 	CJobDataC::CJobDataC()
 	{
 		m_nCassetteSequenceNo = 0;
+		m_pOwner = nullptr;
 	}
 
 	CJobDataC::~CJobDataC()
@@ -13,6 +14,16 @@
 		m_nCassetteProcessFlag = 0;
 	}
 
+	void* CJobDataC::getOwner()
+	{
+		return m_pOwner;
+	}
+
+	void CJobDataC::setOwner(void* pOwner)
+	{
+		m_pOwner = pOwner;
+	}
+
 	int CJobDataC::getCassetteSequenceNo()
 	{
 		return m_nCassetteSequenceNo;
diff --git a/SourceCode/Bond/Servo/CJobDataC.h b/SourceCode/Bond/Servo/CJobDataC.h
index 6b8189f..ecb8d4c 100644
--- a/SourceCode/Bond/Servo/CJobDataC.h
+++ b/SourceCode/Bond/Servo/CJobDataC.h
@@ -6,9 +6,11 @@
 	{
 	public:
 		CJobDataC();
-		~CJobDataC();
+		virtual ~CJobDataC();
 
 	public:
+		void* getOwner();
+		void setOwner(void* pOwner);
 		int getCassetteSequenceNo();
 		void setCassetteSequenceNo(int no);
 		std::string& getCassetteId();
@@ -21,6 +23,7 @@
 		void setMasterRecipe(const char* pszRecipe);
 
 	private:
+		void* m_pOwner;
 		int m_nCassetteSequenceNo;
 		std::string m_strCassetteId;
 		std::string m_strCassetteJudge;
diff --git a/SourceCode/Bond/Servo/CJobDataS.cpp b/SourceCode/Bond/Servo/CJobDataS.cpp
index 9351215..18f1b0e 100644
--- a/SourceCode/Bond/Servo/CJobDataS.cpp
+++ b/SourceCode/Bond/Servo/CJobDataS.cpp
@@ -30,6 +30,7 @@
 		m_nTargetPortNo = 0;
 		m_nTargetSlotNo = 0;
 		m_pRawData = nullptr;
+		m_pOwner = nullptr;
 		if (ENABLE_JOBDATAS_RAWDATA) {
 			m_pRawData = new char[JOBDATAS_SIZE];
 			serialize(m_pRawData, JOBDATAS_SIZE);
@@ -84,6 +85,17 @@
 		m_nSourceSlotNo = pScr->m_nSourceSlotNo;
 		m_nTargetPortNo = pScr->m_nTargetPortNo;
 		m_nTargetSlotNo = pScr->m_nTargetSlotNo;
+		m_pOwner = pScr->m_pOwner;
+	}
+
+	void* CJobDataS::getOwner()
+	{
+		return m_pOwner;
+	}
+
+	void CJobDataS::setOwner(void* pOwner)
+	{
+		m_pOwner = pOwner;
 	}
 
 	int CJobDataS::getCassetteSequenceNo()
diff --git a/SourceCode/Bond/Servo/CJobDataS.h b/SourceCode/Bond/Servo/CJobDataS.h
index 8f5bae6..87b1cde 100644
--- a/SourceCode/Bond/Servo/CJobDataS.h
+++ b/SourceCode/Bond/Servo/CJobDataS.h
@@ -9,9 +9,11 @@
 	public:
 		CJobDataS();
 		CJobDataS::CJobDataS(CJobDataS&& other) noexcept;
-		~CJobDataS();
+		virtual ~CJobDataS();
 
 	public:
+		void* getOwner();
+		void setOwner(void* pOwner);
 		void copy(CJobDataS* pScr);
 		int getCassetteSequenceNo();
 		void setCassetteSequenceNo(int no);
@@ -77,6 +79,7 @@
 
 
 	private:
+		void* m_pOwner;
 		int m_nCassetteSequenceNo;
 		int m_nJobSequenceNo;
 		std::string m_strLotId;
diff --git a/SourceCode/Bond/Servo/CLoadPort.cpp b/SourceCode/Bond/Servo/CLoadPort.cpp
index 1c7becf..6e689a9 100644
--- a/SourceCode/Bond/Servo/CLoadPort.cpp
+++ b/SourceCode/Bond/Servo/CLoadPort.cpp
@@ -16,10 +16,10 @@
 	CLoadPort::CLoadPort() : CEquipment()
 	{
 		m_nIndex = 0;
-		m_nType = 1;
-		m_nMode = 1;
-		m_nCassetteType = 1;
-		m_nTransferMode = 1;
+		m_portType = PortType::Loading;
+		m_portMode = PortMode::InService;
+		m_cassetteType = CassetteType::G1;
+		m_transferMode = TransferMode::AGVMode;
 		m_bEnable = FALSE;
 		m_bAutoChangeEnable = FALSE;
 	}
@@ -55,6 +55,35 @@
 		addPin(SERVO::PinType::OUTPUT, _T("Out2"));
 	}
 
+	// 必须要实现的虚函数,在此初始化Slot信息
+	void CLoadPort::initSlots()
+	{
+		m_slot[0].enable();
+		m_slot[0].setPosition(m_nID);
+		m_slot[0].setNo(1);
+		m_slot[0].setName("Slot 1");
+		m_slot[1].enable();
+		m_slot[1].setPosition(m_nID);
+		m_slot[1].setNo(2);
+		m_slot[1].setName("Slot 2");
+		m_slot[2].setPosition(m_nID);
+		m_slot[2].enable();
+		m_slot[2].setNo(3);
+		m_slot[2].setName("Slot 3");
+		m_slot[3].setPosition(m_nID);
+		m_slot[3].enable();
+		m_slot[3].setNo(4);
+		m_slot[3].setName("Slot 4");
+		m_slot[4].setPosition(m_nID);
+		m_slot[4].enable();
+		m_slot[4].setNo(5);
+		m_slot[4].setName("Slot 5");
+		m_slot[5].setPosition(m_nID);
+		m_slot[5].enable();
+		m_slot[5].setNo(6);
+		m_slot[5].setName("Slot 6");
+	}
+
 	void CLoadPort::initSteps()
 	{
 		CEquipment::initSteps();
@@ -88,7 +117,7 @@
 			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);
+						m_portType = (PortType)CToolUnits::toInt16(pszData);
 					}
 					return 0;
 				});
@@ -109,7 +138,7 @@
 			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);
+						m_portMode = (PortMode)CToolUnits::toInt16(pszData);
 					}
 					return 0;
 				});
@@ -130,7 +159,7 @@
 			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);
+						m_cassetteType = (CassetteType)CToolUnits::toInt16(pszData);
 					}
 					return 0;
 				});
@@ -151,7 +180,7 @@
 			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);
+						m_transferMode = (TransferMode)CToolUnits::toInt16(pszData);
 					}
 					return 0;
 				});
@@ -358,13 +387,13 @@
 		attrubutes.addAttribute(new CAttribute("Index",
 			std::to_string(m_nIndex).c_str(), "", weight++));
 		attrubutes.addAttribute(new CAttribute("Type",
-			getPortTypeDescription(m_nType, strTemp).c_str(), "", weight++));
+			getPortTypeDescription(m_portType, strTemp).c_str(), "", weight++));
 		attrubutes.addAttribute(new CAttribute("Mode",
-			getPortModeDescription(m_nMode, strTemp).c_str(), "", weight++));
+			getPortModeDescription(m_portMode, strTemp).c_str(), "", weight++));
 		attrubutes.addAttribute(new CAttribute("CassetteType",
-			getPortCassetteTypeDescription(m_nCassetteType, strTemp).c_str(), "", weight++));
+			getPortCassetteTypeDescription(m_cassetteType, strTemp).c_str(), "", weight++));
 		attrubutes.addAttribute(new CAttribute("TransferMode",
-			getPortTransferModeDescription(m_nTransferMode, strTemp).c_str(), "", weight++));
+			getPortTransferModeDescription(m_transferMode, strTemp).c_str(), "", weight++));
 		attrubutes.addAttribute(new CAttribute("Enable",
 			m_bEnable ? "Eanble" : "Disable", "", weight++));
 		attrubutes.addAttribute(new CAttribute("Auto Change",
@@ -374,21 +403,6 @@
 	int CLoadPort::recvIntent(CPin* pPin, CIntent* pIntent)
 	{
 		return __super::recvIntent(pPin, pIntent);
-	}
-
-	int CLoadPort::outputGlass(int port)
-	{
-		return __super::outputGlass(port);
-	}
-
-	BOOL CLoadPort::glassWillArrive(CGlass* pGlass)
-	{
-		BOOL bRet = __super::glassWillArrive(pGlass);
-		if (!bRet) {
-			return FALSE;
-		}
-
-		return (m_glassList.size() < 8);
 	}
 
 	int CLoadPort::sendCassetteCtrlCmd(short cmd,
@@ -441,24 +455,24 @@
 		return m_bEnable;
 	}
 
-	int CLoadPort::getPortType()
+	PortType CLoadPort::getPortType()
 	{
-		return m_nType;
+		return m_portType;
 	}
 
-	int CLoadPort::getPortMode()
+	PortMode CLoadPort::getPortMode()
 	{
-		return m_nMode;
+		return m_portMode;
 	}
 
-	int CLoadPort::getCessetteType()
+	CassetteType CLoadPort::getCessetteType()
 	{
-		return m_nCassetteType;
+		return m_cassetteType;
 	}
 
-	int CLoadPort::getTransferMode()
+	TransferMode CLoadPort::getTransferMode()
 	{
-		return m_nTransferMode;
+		return m_transferMode;
 	}
 
 	BOOL CLoadPort::isAutoChange()
@@ -510,9 +524,9 @@
 	 6: Buffer Port-Un-loader in Buffer Type
 	 7: Unloading Partial Port
 	 */
-	std::string& CLoadPort::getPortTypeDescription(int portType, std::string& strDescription)
+	std::string& CLoadPort::getPortTypeDescription(PortType portType, std::string& strDescription)
 	{
-		switch (portType) {
+		switch ((int)portType) {
 		case 1:
 			strDescription = _T("Loading Port");
 			break;
@@ -550,9 +564,9 @@
 	 4: InService
 	 5: TransferReady
 	 */
-	std::string& CLoadPort::getPortModeDescription(int portMode, std::string& strDescription)
+	std::string& CLoadPort::getPortModeDescription(PortMode portMode, std::string& strDescription)
 	{
-		switch (portMode) {
+		switch ((int)portMode) {
 		case 0:
 			strDescription = _T("OutOfService");
 			break;
@@ -584,9 +598,9 @@
 	 2: G2
 	 3: G1&G2
 	 */
-	std::string& CLoadPort::getPortCassetteTypeDescription(int casseteType, std::string& strDescription)
+	std::string& CLoadPort::getPortCassetteTypeDescription(CassetteType casseteType, std::string& strDescription)
 	{
-		switch (casseteType) {
+		switch ((int)casseteType) {
 		case 1:
 			strDescription = _T("G1");
 			break;
@@ -609,9 +623,9 @@
 	 2: AGV Mode
 	 3: Stocker Inline Mode
 	 */
-	std::string& CLoadPort::getPortTransferModeDescription(int mode, std::string& strDescription)
+	std::string& CLoadPort::getPortTransferModeDescription(TransferMode mode, std::string& strDescription)
 	{
-		switch (mode) {
+		switch ((int)mode) {
 		case 1:
 			strDescription = _T("MGV Mode");
 			break;
@@ -1044,11 +1058,16 @@
 	/*
 	 * 生成测试用的玻璃列表
 	 */
-	int CLoadPort::testGenerateGlassList(MaterialsType type, int count, const char* pszPrefix, int startSuffix)
+	int CLoadPort::testGenerateGlassList(MaterialsType type, const char* pszPrefix, int startSuffix)
 	{
+		static unsigned short nJobSequenceNo = 0;
+		static unsigned short nCassetteSequenceNo = 0;
+		nCassetteSequenceNo++;
+
+
 		// 如果非空就不生成了
 		Lock();
-		if (!m_glassList.empty()) {
+		if (hasGlass()) {
 			Unlock();
 			return -1;
 		}
@@ -1057,13 +1076,19 @@
 
 		char szBuffer[64];
 		int suffix = startSuffix;
-		for (int i = 0; i < count; i++) {
+		for (int i = 0; i < SLOT_MAX; i++) {
+			if (!m_slot[i].isEnable()) continue;
+
 			CJobDataB jb;
 			CJobDataS js;
 
 			sprintf_s(szBuffer, "%s%d", pszPrefix, suffix++);
 			jb.setGlassId(szBuffer);
+			jb.setCassetteSequenceNo(nCassetteSequenceNo);
+			jb.setJobSequenceNo(++nJobSequenceNo);
 			js.setMaterialsType((int)type);
+			js.setCassetteSequenceNo(nCassetteSequenceNo);
+			js.setJobSequenceNo(nJobSequenceNo);
 			if (type == MaterialsType::G1) {
 				js.setGlass1Id(szBuffer);
 			}
@@ -1076,7 +1101,8 @@
 			pGlass->setJobDataB(&jb);
 			pGlass->setType(type);
 			pGlass->setJobDataS(&js);
-			addGlassToList(pGlass);
+			pGlass->addRef();
+			m_slot[i].setContext(pGlass);
 		}
 
 		return 0;
diff --git a/SourceCode/Bond/Servo/CLoadPort.h b/SourceCode/Bond/Servo/CLoadPort.h
index 3e011fc..7bc8702 100644
--- a/SourceCode/Bond/Servo/CLoadPort.h
+++ b/SourceCode/Bond/Servo/CLoadPort.h
@@ -17,11 +17,11 @@
 		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 BOOL glassWillArrive(CGlass* pGlass);
 		virtual void onReceiveLBData(const char* pszData, size_t size);
 
 	public:
@@ -36,10 +36,10 @@
 		void setIndex(unsigned int index);
 		unsigned int getIndex();
 		BOOL isEnable();
-		int getPortType();
-		int getPortMode();
-		int getCessetteType();
-		int getTransferMode();
+		PortType getPortType();
+		PortMode getPortMode();
+		CassetteType getCessetteType();
+		TransferMode getTransferMode();
 		BOOL isAutoChange();
 		int getPortStatus();
 		int getCassetteSequenceNo();
@@ -48,13 +48,13 @@
 		int getQTimeFlag();
 		int getCassetteMappingState();
 		int getCassetteStatus();
-		int testGenerateGlassList(MaterialsType type, int count, const char* pszPrefix, int startSuffix);
+		int testGenerateGlassList(MaterialsType type, const char* pszPrefix, int startSuffix);
 
 	public:
-		static std::string& getPortTypeDescription(int portType, std::string& strDescription);
-		static std::string& getPortModeDescription(int portMode, std::string& strDescription);
-		static std::string& getPortCassetteTypeDescription(int casseteType, std::string& strDescription);
-		static std::string& getPortTransferModeDescription(int mode, std::string& strDescription);
+		static std::string& getPortTypeDescription(PortType portType, std::string& strDescription);
+		static std::string& getPortModeDescription(PortMode portMode, std::string& strDescription);
+		static std::string& getPortCassetteTypeDescription(CassetteType casseteType, std::string& strDescription);
+		static std::string& getPortTransferModeDescription(TransferMode 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);
@@ -63,7 +63,6 @@
 		static std::string& getCassetteStatusDescription(int state, std::string& strDescription);
 
 	public:
-		virtual int outputGlass(int port);
 		int sendCassetteCtrlCmd(short cmd,
 			short* jobExistence,
 			int jobExistenceSize,
@@ -77,10 +76,10 @@
 
 	private:
 		unsigned int m_nIndex;
-		int m_nType;
-		int m_nMode;
-		int m_nCassetteType;
-		int m_nTransferMode;
+		PortType m_portType;
+		PortMode m_portMode;
+		CassetteType m_cassetteType;
+		TransferMode m_transferMode;
 		BOOL m_bEnable;
 		BOOL m_bAutoChangeEnable;
 		CPortStatusReport m_portStatusReport;
diff --git a/SourceCode/Bond/Servo/CMaster.cpp b/SourceCode/Bond/Servo/CMaster.cpp
index e148025..d536f7c 100644
--- a/SourceCode/Bond/Servo/CMaster.cpp
+++ b/SourceCode/Bond/Servo/CMaster.cpp
@@ -6,6 +6,15 @@
 namespace SERVO {
 	CMaster* g_pMaster = NULL;
 
+	unsigned __stdcall DispatchThreadFunction(LPVOID lpParam)
+	{
+		if (g_pMaster != NULL) {
+			return g_pMaster->DispatchProc();
+		}
+
+		return 0;
+	}
+
 	unsigned __stdcall ReadBitsThreadFunction(LPVOID lpParam)
 	{
 		if (g_pMaster != NULL) {
@@ -24,12 +33,22 @@
 
 	CMaster::CMaster()
 	{
-		m_listener = {nullptr, nullptr, nullptr, nullptr, nullptr};
+		m_listener = {};
 		m_bDataModify = FALSE;
 		m_hEventReadBitsThreadExit[0] = ::CreateEvent(NULL, TRUE, FALSE, NULL);
 		m_hEventReadBitsThreadExit[1] = ::CreateEvent(NULL, TRUE, FALSE, NULL);
 		m_hReadBitsThreadHandle = nullptr;
 		m_nReadBitsThreadAddr = 0;
+		m_hDispatchEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
+		m_hEventDispatchThreadExit[0] = ::CreateEvent(NULL, TRUE, FALSE, NULL);
+		m_hEventDispatchThreadExit[1] = ::CreateEvent(NULL, TRUE, FALSE, NULL);
+		m_hDispatchThreadHandle = nullptr;
+		m_nDispatchThreadAddr = 0;
+		m_ullStartTime = 0;
+		m_ullRunTime = 0;
+		m_state = MASTERSTATE::READY;
+		m_pActiveRobotTask = nullptr;
+		InitializeCriticalSection(&m_criticalSection);
 	}
 
 	CMaster::~CMaster()
@@ -43,15 +62,33 @@
 			::CloseHandle(m_hEventReadBitsThreadExit[1]);
 			m_hEventReadBitsThreadExit[1] = nullptr;
 		}
+
+		if (m_hDispatchEvent != nullptr) {
+			::CloseHandle(m_hDispatchEvent);
+			m_hDispatchEvent = nullptr;
+		}
+
+		if (m_hEventDispatchThreadExit[0] != nullptr) {
+			::CloseHandle(m_hEventDispatchThreadExit[0]);
+			m_hEventDispatchThreadExit[0] = nullptr;
+		}
+
+		if (m_hEventDispatchThreadExit[1] != nullptr) {
+			::CloseHandle(m_hEventDispatchThreadExit[1]);
+			m_hEventDispatchThreadExit[1] = nullptr;
+		}
+
+		DeleteCriticalSection(&m_criticalSection);
 	}
 
 	void CMaster::setListener(MasterListener listener)
 	{
-		m_listener.onEqAlive = listener.onEqAlive;
-		m_listener.onEqCimStateChanged = listener.onEqCimStateChanged;
-		m_listener.onEqAlarm = listener.onEqAlarm;
-		m_listener.onEqVcrEventReport = listener.onEqVcrEventReport;
-		m_listener.onEqDataChanged = listener.onEqDataChanged;
+		m_listener = listener;
+	}
+
+	CRobotTask* CMaster::getActiveRobotTask()
+	{
+		return m_pActiveRobotTask;
 	}
 
 	int CMaster::init()
@@ -159,6 +196,12 @@
 		SetTimer(NULL, 1, 250, (TIMERPROC)MasterTimerProc);
 
 
+		// 调度线程
+		m_hDispatchThreadHandle = (HANDLE)_beginthreadex(NULL, 0, SERVO::DispatchThreadFunction, this,
+			0, &m_nDispatchThreadAddr);
+
+
+		// 监控bit线程
 		m_hReadBitsThreadHandle = (HANDLE)_beginthreadex(NULL, 0, SERVO::ReadBitsThreadFunction, this,
 			0, &m_nReadBitsThreadAddr);
 
@@ -170,7 +213,9 @@
 	int CMaster::term()
 	{
 		SetEvent(m_hEventReadBitsThreadExit[0]);
+		SetEvent(m_hEventDispatchThreadExit[0]);
 		::WaitForSingleObject(m_hEventReadBitsThreadExit[1], INFINITE);
+		::WaitForSingleObject(m_hEventDispatchThreadExit[1], INFINITE);
 
 		LOGI("<Master>正在结束程序.");
 		for (auto item : m_listEquipment) {
@@ -178,6 +223,12 @@
 		}
 		saveCache();
 
+		lock();
+		if (m_pActiveRobotTask != nullptr) {
+			delete m_pActiveRobotTask;
+			m_pActiveRobotTask = nullptr;
+		}
+		unlock();
 
 		for (auto item : m_listEquipment) {
 			delete item;
@@ -185,6 +236,167 @@
 		m_listEquipment.clear();
 
 
+		return 0;
+	}
+
+	int CMaster::start()
+	{
+		if (m_state != MASTERSTATE::READY) {
+			return -1;
+		}
+
+		setState(MASTERSTATE::STARTING);
+		m_ullStartTime = GetTickCount64();
+
+		return 0;
+	}
+
+	int CMaster::stop()
+	{
+		// 运行时间为累加结果,本次停止时刷新;
+		if (m_state != MASTERSTATE::RUNNING) {
+			return -1;
+		}
+
+		m_ullRunTime += (GetTickCount64() - m_ullStartTime);
+		setState(MASTERSTATE::STOPPING);
+
+		return 0;
+	}
+
+	ULONGLONG CMaster::getRunTime()
+	{
+		if (m_state == MASTERSTATE::RUNNING)
+			return m_ullRunTime + (GetTickCount64() - m_ullStartTime);
+		else
+			return m_ullRunTime;
+	}
+
+	MASTERSTATE CMaster::getState()
+	{
+		return m_state;
+	}
+
+	unsigned CMaster::DispatchProc()
+	{
+		while (1) {
+			// 待退出信号或时间到
+			HANDLE hEvents[] = { m_hEventDispatchThreadExit[0], m_hDispatchEvent };
+			int nRet = WaitForMultipleObjects(2, hEvents, FALSE, 1000);
+			if (nRet == WAIT_OBJECT_0) {
+				break;
+			}
+			
+
+			// 如果状态为STARTING,开始工作并切换到RUNNING状态
+			lock();
+			if (m_state == MASTERSTATE::STARTING) {
+				unlock();
+				Sleep(1000);
+				setState(MASTERSTATE::RUNNING);
+				continue;
+			}
+
+
+			// 处理完成当前事务后,切换到停止或就绪状态
+			else if (m_state == MASTERSTATE::STOPPING) {
+				unlock();
+				Sleep(1000);
+				setState(MASTERSTATE::READY);
+				continue;
+			}
+
+
+			// 调度逻辑处理
+			else if (m_state == MASTERSTATE::RUNNING) {
+				unlock();
+				LOGI("调度处理中...");
+
+				lock();
+				if (m_pActiveRobotTask != nullptr) {
+					unlock();
+					// 检测到当前有正在下午的任务,确保当前任务完成或中止后继续
+					LOGI("检测到当前有正在下午的任务,确保当前任务完成或中止后继续...");
+					continue;
+				}
+
+				// LoadPort -> Fliper(G2)
+				CLoadPort* pLoadPort1 = (CLoadPort*)getEquipment(EQ_ID_LOADPORT1);
+				CLoadPort* pLoadPort2 = (CLoadPort*)getEquipment(EQ_ID_LOADPORT2);
+				CFliper* pFliper = (CFliper*)getEquipment(EQ_ID_FLIPER);
+				CVacuumBake* pVacuumBack = (CVacuumBake*)getEquipment(EQ_ID_VACUUMBAKE);
+				ASSERT(pLoadPort1);
+				ASSERT(pLoadPort2);
+				ASSERT(pFliper);
+				ASSERT(pVacuumBack);
+
+				m_pActiveRobotTask = createTransferTask(pLoadPort1, pFliper);
+				if (m_pActiveRobotTask != nullptr) {
+					std::string strDescription = m_pActiveRobotTask->getDescription();
+					unlock();
+					LOGI("创建新任务<%s>...", strDescription.c_str());
+					continue;
+				}
+
+				m_pActiveRobotTask = createTransferTask(pLoadPort2, pFliper);
+				if (m_pActiveRobotTask != nullptr) {
+					std::string strDescription = m_pActiveRobotTask->getDescription();
+					unlock();
+					LOGI("创建新任务<%s>...", strDescription.c_str());
+					continue;
+				}
+
+
+
+				// LoadPort -> VacuumBake(G1)
+				m_pActiveRobotTask = createTransferTask(pLoadPort1, pVacuumBack);
+				if (m_pActiveRobotTask != nullptr) {
+					std::string strDescription = m_pActiveRobotTask->getDescription();
+					unlock();
+					LOGI("创建新任务1<%s>...", strDescription.c_str());
+					continue;
+				}
+
+				m_pActiveRobotTask = createTransferTask(pLoadPort2, pVacuumBack);
+				if (m_pActiveRobotTask != nullptr) {
+					std::string strDescription = m_pActiveRobotTask->getDescription();
+					unlock();
+					LOGI("创建新任务2<%s>...", strDescription.c_str());
+					continue;
+				}
+
+
+
+				// Fliper(G2) -> Aligner
+
+
+				// VacuumBake(G1) -> Aligner
+
+
+				// Aligner -> Bonder
+
+
+				// Bonder -> BakeCooling
+
+
+				// BakeCooling ->Measurement
+
+
+				// Measurement -> LoadPort
+
+
+
+				unlock();
+
+			}
+			unlock();
+		}
+
+		SetEvent(m_hEventDispatchThreadExit[1]);
+
+
+		// _endthreadex(0);
+		TRACE("CMaster::DispatchProc 线程退出\n");
 		return 0;
 	}
 
@@ -248,11 +460,102 @@
 				m_listener.onEqVcrEventReport(this, p, p2);
 			}
 		};
+		listener.onPreFethedOutJob = [&](void* pEquipment, CJobDataB* pJobDataB) -> BOOL {
+			CEquipment* p = (CEquipment*)pEquipment;
+
+
+			// 取片,更新当前搬送任务
+			BOOL bOk = FALSE;
+			lock();
+			if (m_pActiveRobotTask != nullptr) {
+				if (m_pActiveRobotTask->getSrcPosition() == p->getID()) {
+					CGlass* pGlass = p->getGlassFromSlot(m_pActiveRobotTask->getSrcSlot());
+					if (pGlass != nullptr) {
+						CJobDataB* pJobDataBSrc = pGlass->getJobDataB();
+						if (pJobDataBSrc != nullptr
+							&& pJobDataBSrc->getCassetteSequenceNo() == pJobDataB->getCassetteSequenceNo()
+							&& pJobDataBSrc->getJobSequenceNo() == pJobDataB->getJobSequenceNo()) {
+							bOk = TRUE;
+							LOGI("<CMaster>onPreFethedOutJob, 已校验数据一致性.");
+						}
+					}
+				}
+				else if (p->getID() == EQ_ID_ARM_TRAY1 || p->getID() == EQ_ID_ARM_TRAY2) {
+					bOk = TRUE;
+				}
+			}
+			unlock();
+
+			if (!bOk) {
+				LOGE("<CMaster>onPreFethedOutJob, 数据校验失败.");
+			}
+
+			return bOk;
+
+		};
+		listener.onPreStoredJob = [&](void* pEquipment, CJobDataB* pJobDataB, short& slot) -> BOOL {
+			CEquipment* p = (CEquipment*)pEquipment;
+
+
+			// 放片,更新当前搬送任务
+			BOOL bOk = FALSE;
+			lock();
+			if (m_pActiveRobotTask != nullptr) {
+				if (m_pActiveRobotTask->getTarPosition() == p->getID()) {
+					CGlass* pGlass = p->getGlassFromSlot(m_pActiveRobotTask->getTarSlot());
+					if (pGlass == nullptr) {
+						bOk = TRUE;
+						slot = m_pActiveRobotTask->getTarSlot();
+						LOGI("<CMaster>onPreFethedOutJob, 已校验数据一致性.");
+					}
+				}
+				else if (p->getID() == EQ_ID_ARM_TRAY1 || p->getID() == EQ_ID_ARM_TRAY2) {
+					slot = 1;
+					bOk = TRUE;
+				}
+			}
+			unlock();
+
+			if (!bOk) {
+				LOGE("<CMaster>onPreFethedOutJob, 数据校验失败.");
+			}
+
+			return bOk;
+
+		};
 		listener.onDataChanged = [&](void* pEquipment, int code) -> void {
 			m_bDataModify = TRUE;
 			CEquipment* p = (CEquipment*)pEquipment;
 			if (m_listener.onEqDataChanged != nullptr) {
 				m_listener.onEqDataChanged(this, p, 0);
+			}
+
+			// 取放片,更新当前搬送任务
+			if (code == EDCC_FETCHOUT_JOB) {
+				lock();
+				if (m_pActiveRobotTask != nullptr && m_pActiveRobotTask->getSrcPosition() == p->getID()) {
+					m_pActiveRobotTask->fetchOut();
+					LOGI("开始取片...");
+				}
+				unlock();
+			}
+			else if (code == EDCC_STORED_JOB) {
+				lock();
+				if (m_pActiveRobotTask != nullptr && m_pActiveRobotTask->getTarPosition() == p->getID()) {
+					m_pActiveRobotTask->stored();
+					m_pActiveRobotTask->completed();
+					LOGI("放片完成...");
+
+					// 完成此条搬送任务,但要把数据和消息上抛应用层
+					unlock();
+
+
+
+					lock();
+					delete m_pActiveRobotTask;
+					m_pActiveRobotTask = nullptr;
+				}
+				unlock();
 			}
 		};
 
@@ -656,4 +959,36 @@
 			item->serialize(ar);
 		}
 	}
+
+	void CMaster::setState(MASTERSTATE state)
+	{
+		m_state = state;
+		if (m_listener.onMasterStateChanged != nullptr) {
+			m_listener.onMasterStateChanged(this, m_state);
+		}
+	}
+
+	static int taskSeqNo = 0;
+	CRobotTask* CMaster::createTransferTask(CEquipment* pSrcEq, CEquipment* pTarEq)
+	{
+		CRobotTask* pTask = nullptr;
+		CSlot* pSrcSlot, * pTarSlot;
+		pTarSlot = pTarEq->getAvailableSlotForGlass(MaterialsType::G1);
+		pSrcSlot = pSrcEq->getNonEmptySlot(MaterialsType::G1);
+		if (pSrcSlot == nullptr || nullptr == pTarSlot) {
+			pTarSlot = pTarEq->getAvailableSlotForGlass(MaterialsType::G2);
+			pSrcSlot = pSrcEq->getNonEmptySlot(MaterialsType::G2);
+		}
+
+
+		if (pSrcSlot != nullptr && nullptr != pTarSlot) {
+			pTask = new CRobotTask();
+			pTask->setContext(pSrcSlot->getContext());
+			pTask->setRobotTransferParam(++taskSeqNo, 1, pSrcSlot->getPosition(),
+				pTarSlot->getPosition(), pSrcSlot->getNo(), pTarSlot->getNo());
+		}
+
+
+		return pTask;
+	}
 }
diff --git a/SourceCode/Bond/Servo/CMaster.h b/SourceCode/Bond/Servo/CMaster.h
index fbd76cf..93ff6cc 100644
--- a/SourceCode/Bond/Servo/CMaster.h
+++ b/SourceCode/Bond/Servo/CMaster.h
@@ -12,9 +12,18 @@
 #include "CArm.h"
 #include "CArmTray.h"
 #include "CCLinkIEControl.h"
+#include "CRobotTask.h"
 
 
 namespace SERVO {
+    enum MASTERSTATE {
+        READY = 0,
+        STARTING,
+        RUNNING,
+        STOPPING
+    };
+
+    typedef std::function<void(void* pMaster, MASTERSTATE state)> ONMASTERSTATECHANGED;
     typedef std::function<void(void* pMaster, CEquipment* pEiuipment, BOOL bAlive)> ONEQALIVE;
     typedef std::function<void(CStep* pStep, int code, void* pData)> ONEQSTEPEVENT;
     typedef std::function<void(void* pMaster, CEquipment* pEquipment, int state, int alarmId, int unitId, int level)> ONEQALARM;
@@ -22,6 +31,7 @@
     typedef std::function<void(void* pMaster, CEquipment* pEquipment, int code)> ONEQDATACHANGED;
     typedef struct _MasterListener
     {
+        ONMASTERSTATECHANGED    onMasterStateChanged;
         ONEQALIVE				onEqAlive;
         ONEQALIVE		        onEqCimStateChanged;
         ONEQALARM               onEqAlarm;
@@ -33,13 +43,19 @@
     {
     public:
         CMaster();
-        ~CMaster();
+        virtual ~CMaster();
 
 
     public:
         void setListener(MasterListener listener);
+        CRobotTask* getActiveRobotTask();
         int init();
         int term();
+        int start();
+        int stop();
+        ULONGLONG getRunTime();
+        MASTERSTATE getState();
+        unsigned DispatchProc();
         unsigned ReadBitsProc();
         void onTimer(UINT nTimerid);
         std::list<CEquipment*>& getEquipmentList();
@@ -47,6 +63,8 @@
         void setCacheFilepath(const char* pszFilepath);
 
     private:
+        inline void lock() { EnterCriticalSection(&m_criticalSection); }
+        inline void unlock() { LeaveCriticalSection(&m_criticalSection); }
         int addToEquipmentList(CEquipment* pEquipment);
         CLoadPort* addLoadPort(int index);
         CFliper* addFliper();
@@ -63,8 +81,11 @@
         int saveCacheAndBackups();
         int readCache();
         void serialize(CArchive& ar);
+        void setState(MASTERSTATE state);
+        CRobotTask* createTransferTask(CEquipment* pSrcEq, CEquipment* pTarEq);
 
     private:
+        CRITICAL_SECTION m_criticalSection;
         MasterListener m_listener;
         CCCLinkIEControl m_cclink;
         std::list<CEquipment*> m_listEquipment;
@@ -72,9 +93,25 @@
         BOOL m_bDataModify;
 
     private:
+        /* 监控比特位的线程*/
         HANDLE m_hEventReadBitsThreadExit[2];
         HANDLE m_hReadBitsThreadHandle;
         unsigned m_nReadBitsThreadAddr;
+
+        // 调度线程
+        HANDLE m_hDispatchEvent;
+        HANDLE m_hEventDispatchThreadExit[2];
+        HANDLE m_hDispatchThreadHandle;
+        unsigned m_nDispatchThreadAddr;
+
+        // 启动时间,运行时间,状态
+        ULONGLONG m_ullStartTime;
+        ULONGLONG m_ullRunTime;
+        MASTERSTATE m_state;
+
+        // 当前任务和已完成任务列表
+        CRobotTask* m_pActiveRobotTask;
+        std::list< CRobotTask* > m_listTask;
     };
 }
 
diff --git a/SourceCode/Bond/Servo/CMeasurement.cpp b/SourceCode/Bond/Servo/CMeasurement.cpp
index f659453..4821891 100644
--- a/SourceCode/Bond/Servo/CMeasurement.cpp
+++ b/SourceCode/Bond/Servo/CMeasurement.cpp
@@ -38,6 +38,15 @@
 		addPin(SERVO::PinType::OUTPUT, _T("Out2"));
 	}
 
+	// 必须要实现的虚函数,在此初始化Slot信息
+	void CMeasurement::initSlots()
+	{
+		m_slot[0].enable();
+		m_slot[0].setPosition(m_nID);
+		m_slot[0].setNo(1);
+		m_slot[0].setName("Slot 1");
+	}
+
 	void CMeasurement::onTimer(UINT nTimerid)
 	{
 		CEquipment::onTimer(nTimerid);
@@ -56,16 +65,6 @@
 	int CMeasurement::recvIntent(CPin* pPin, CIntent* pIntent)
 	{
 		return __super::recvIntent(pPin, pIntent);
-	}
-
-	BOOL CMeasurement::glassWillArrive(CGlass* pGlass)
-	{
-		BOOL bRet = __super::glassWillArrive(pGlass);
-		if (!bRet) {
-			return FALSE;
-		}
-
-		return m_glassList.empty();
 	}
 
 	int CMeasurement::getIndexerOperationModeBaseValue()
diff --git a/SourceCode/Bond/Servo/CMeasurement.h b/SourceCode/Bond/Servo/CMeasurement.h
index b6d87bb..a1d8bac 100644
--- a/SourceCode/Bond/Servo/CMeasurement.h
+++ b/SourceCode/Bond/Servo/CMeasurement.h
@@ -15,11 +15,11 @@
         virtual void init();
         virtual void term();
         virtual void initPins();
+        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 BOOL glassWillArrive(CGlass* pGlass);
         virtual int getIndexerOperationModeBaseValue();
 
 	};
diff --git a/SourceCode/Bond/Servo/CMyStatusbar.cpp b/SourceCode/Bond/Servo/CMyStatusbar.cpp
new file mode 100644
index 0000000..d85b341
--- /dev/null
+++ b/SourceCode/Bond/Servo/CMyStatusbar.cpp
@@ -0,0 +1,117 @@
+锘�// CMyStatusbar.cpp: 瀹炵幇鏂囦欢
+//
+
+#include "stdafx.h"
+#include "Servo.h"
+#include "CMyStatusbar.h"
+#include "afxdialogex.h"
+
+
+// CMyStatusbar 瀵硅瘽妗�
+
+IMPLEMENT_DYNAMIC(CMyStatusbar, CDialogEx)
+
+CMyStatusbar::CMyStatusbar(CWnd* pParent /*=nullptr*/)
+	: CDialogEx(IDD_STATUSBAR, pParent)
+{
+	m_crBkgnd = STATUSBAR_BK_NORMAL;
+}
+
+CMyStatusbar::~CMyStatusbar()
+{
+}
+
+void CMyStatusbar::DoDataExchange(CDataExchange* pDX)
+{
+	CDialogEx::DoDataExchange(pDX);
+}
+
+
+BEGIN_MESSAGE_MAP(CMyStatusbar, CDialogEx)
+	ON_WM_CTLCOLOR()
+	ON_WM_DESTROY()
+	ON_WM_SIZE()
+END_MESSAGE_MAP()
+
+
+// CMyStatusbar 娑堟伅澶勭悊绋嬪簭
+
+
+void CMyStatusbar::setBackgroundColor(COLORREF color)
+{
+	if (m_brBkgnd.GetSafeHandle() != nullptr) {
+		m_brBkgnd.DeleteObject();
+	}
+
+	m_brBkgnd.CreateSolidBrush(color);
+	Invalidate(); 
+	UpdateWindow();
+}
+
+void CMyStatusbar::setForegroundColor(COLORREF cr)
+{
+	m_crForeground = cr;
+	Invalidate();
+	UpdateWindow();
+}
+
+void CMyStatusbar::setRunTimeText(const char* pszText)
+{
+	SetDlgItemText(IDC_LABEL_RUNTIME, pszText);
+}
+
+BOOL CMyStatusbar::OnInitDialog()
+{
+	CDialogEx::OnInitDialog();
+
+	// TODO:  鍦ㄦ娣诲姞棰濆鐨勫垵濮嬪寲
+
+	return TRUE;  // return TRUE unless you set the focus to a control
+				  // 寮傚父: OCX 灞炴�ч〉搴旇繑鍥� FALSE
+}
+
+HBRUSH CMyStatusbar::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
+{
+	HBRUSH hbr = CDialogEx::OnCtlColor(pDC, pWnd, nCtlColor);
+
+	// TODO:  鍦ㄦ鏇存敼 DC 鐨勪换浣曠壒鎬�
+
+	if (nCtlColor == CTLCOLOR_STATIC) {
+		pDC->SetBkMode(TRANSPARENT);
+		pDC->SetBkColor(m_crBkgnd);
+		pDC->SetTextColor(m_crForeground);
+	}
+
+	if (m_brBkgnd.GetSafeHandle() == nullptr) {
+		m_brBkgnd.CreateSolidBrush(m_crBkgnd);
+	}
+
+	return (HBRUSH)m_brBkgnd;
+}
+
+void CMyStatusbar::OnDestroy()
+{
+	CDialogEx::OnDestroy();
+
+	// TODO: 鍦ㄦ澶勬坊鍔犳秷鎭鐞嗙▼搴忎唬鐮�
+}
+
+void CMyStatusbar::OnSize(UINT nType, int cx, int cy)
+{
+	CDialogEx::OnSize(nType, cx, cy);
+	if (nullptr == GetDlgItem(IDC_LABEL_RUNTIME)) return;
+	Resize();
+}
+
+void CMyStatusbar::Resize()
+{
+	CRect rcClient, rcItem;
+	CWnd* pItem = nullptr;
+	int x;
+	GetClientRect(&rcClient);
+
+	x = 120;
+	pItem = GetDlgItem(IDC_LABEL_RUNTIME);
+	pItem->GetClientRect(rcItem);
+	pItem->MoveWindow(x, (rcClient.Height() - rcItem.Height()) / 2, rcItem.Width(), rcItem.Height());
+}
diff --git a/SourceCode/Bond/Servo/CMyStatusbar.h b/SourceCode/Bond/Servo/CMyStatusbar.h
new file mode 100644
index 0000000..3ac6fee
--- /dev/null
+++ b/SourceCode/Bond/Servo/CMyStatusbar.h
@@ -0,0 +1,43 @@
+锘�#pragma once
+
+
+// CMyStatusbar 瀵硅瘽妗�
+
+class CMyStatusbar : public CDialogEx
+{
+	DECLARE_DYNAMIC(CMyStatusbar)
+
+public:
+	CMyStatusbar(CWnd* pParent = nullptr);   // 鏍囧噯鏋勯�犲嚱鏁�
+	virtual ~CMyStatusbar();
+
+
+public:
+	void setBackgroundColor(COLORREF color);
+	void setForegroundColor(COLORREF cr);
+	void setRunTimeText(const char* pszText);
+
+private:
+	void Resize();
+
+private:
+	COLORREF m_crForeground;
+	COLORREF m_crBkgnd;
+	CBrush m_brBkgnd;
+
+
+// 瀵硅瘽妗嗘暟鎹�
+#ifdef AFX_DESIGN_TIME
+	enum { IDD = IDD_STATUSBAR };
+#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/CPageGraph2.cpp b/SourceCode/Bond/Servo/CPageGraph2.cpp
index 7e4811e..6f06274 100644
--- a/SourceCode/Bond/Servo/CPageGraph2.cpp
+++ b/SourceCode/Bond/Servo/CPageGraph2.cpp
@@ -13,8 +13,6 @@
 #include "CPagePortStatus.h"
 #include "CPageCassetteCtrlCmd.h"
 #include "CJobDataB.h"
-#include "CRobotCmdContainerDlg.h"
-#include "CRobotCmdTestDlg.h"
 
 
 // CPageGraph2 瀵硅瘽妗�
@@ -67,7 +65,7 @@
 				SERVO::CEquipment* pEquipment = nullptr;
 				if (pAny->getPtrValue("ptr", (void*&)pEquipment)) {
 					if (pEquipment != nullptr) {
-						m_pEqsGraphWnd->ShowItemIndicator((DWORD_PTR)pEquipment, !pEquipment->isGlassListEmpty());
+						m_pEqsGraphWnd->ShowItemIndicator((DWORD_PTR)pEquipment, pEquipment->hasGlass());
 					}
 				}
 			}
@@ -206,22 +204,29 @@
 
 		// 娴嬭瘯
 		else if (nCmd == ID_EQSGRAPHITEM_TEST1) {
+			BOOL bTestGenerate = FALSE;
 			SERVO::CEquipment* pEquipment = (SERVO::CEquipment*)pItem->pData;
-			if (pEquipment->getID() == EQ_ID_LOADPORT1) {
-				((SERVO::CLoadPort*)pEquipment)->testGenerateGlassList(SERVO::MaterialsType::G1, 10, 
+			if (pEquipment->getID() == EQ_ID_LOADPORT1 && !pEquipment->hasGlass()) {
+				((SERVO::CLoadPort*)pEquipment)->testGenerateGlassList(SERVO::MaterialsType::G1, 
 					"P20250320G1X", 1);
+				bTestGenerate = TRUE;
 			}
-			else if (pEquipment->getID() == EQ_ID_LOADPORT2) {
-				((SERVO::CLoadPort*)pEquipment)->testGenerateGlassList(SERVO::MaterialsType::G2, 10,
+			else if (pEquipment->getID() == EQ_ID_LOADPORT2 && !pEquipment->hasGlass()) {
+				((SERVO::CLoadPort*)pEquipment)->testGenerateGlassList(SERVO::MaterialsType::G2,
 					"P20250320G2X", 1);
+				bTestGenerate = TRUE;
 			}
-			SERVO::CGlass* pGlass = pEquipment->getFrontGlass();
-			if (pGlass != nullptr) {
-				SERVO::CJobDataB* pJobDataB = pGlass->getJobDataB();
-				SERVO::CJobDataS* pJobDataS = pGlass->getJobDataS();
-				if (pJobDataB != nullptr && pJobDataS != nullptr) {
-					pEquipment->fetchedOutJob(pJobDataB);
-					pEquipment->onSentOutJob(0, pJobDataS);
+			
+			if (!bTestGenerate) {
+				SERVO::CRobotTask* pTask = theApp.m_model.getMaster().getActiveRobotTask();
+				if (pTask != nullptr) {
+					SERVO::CGlass* pGlass = (SERVO::CGlass*)pTask->getContext();
+					SERVO::CJobDataB* pJobDataB = pGlass->getJobDataB();
+					SERVO::CJobDataS* pJobDataS = pGlass->getJobDataS();
+					if (pJobDataB != nullptr && pJobDataS != nullptr) {
+						pEquipment->onFetchedOutJob(0, pJobDataB);
+						pEquipment->onSentOutJob(0, pJobDataS);
+					}
 				}
 			}
 		}
@@ -229,7 +234,7 @@
 			SERVO::CEquipment* pEquipment = (SERVO::CEquipment*)pItem->pData;
 			SERVO::CArm* pArm = (SERVO::CArm*)pEquipment->getArm();
 			if (pArm != nullptr) {
-				SERVO::CGlass* pGlass = pArm->getFrontGlass();
+				SERVO::CGlass* pGlass = pArm->getAnyGlass();
 				if (pGlass != nullptr) {
 					SERVO::CJobDataB* pJobDataB = pGlass->getJobDataB();
 					SERVO::CJobDataS* pJobDataS = pGlass->getJobDataS();
@@ -244,7 +249,7 @@
 		else if (nCmd == ID_EQSGRAPHITEM_TEST3) {
 			SERVO::CEquipment* pEquipment = (SERVO::CEquipment*)pItem->pData;
 			if (pEquipment != nullptr) {
-				SERVO::CGlass* pGlass = pEquipment->getFrontGlass();
+				SERVO::CGlass* pGlass = pEquipment->getAnyGlass();
 				if (pGlass != nullptr) {
 					SERVO::CProcessData pd;
 					pd.setGlassId(pGlass->getID().c_str());
@@ -254,44 +259,6 @@
 		}
 		else if (nCmd == ID_EQSGRAPHITEM_TEST4) {
 			SERVO::CEquipment* pEquipment = (SERVO::CEquipment*)pItem->pData;
-
-			/* 娴嬭瘯 RobotCMD */
-			if (pEquipment->getID() == EQ_ID_EFEM) {
-				SERVO::CEFEM* pEFEM = (SERVO::CEFEM*)pEquipment;
-
-				//SERVO::ROBOT_CMD_PARAM cmds[4];
-				//cmds[0].sequenceNo = 1;
-				//cmds[0].rcmd = (short)SERVO::RCMD::Move;
-				//cmds[0].armNo = 1;
-				//cmds[0].getPosition = 1;
-				//cmds[0].putPosition = 2;
-				//cmds[0].getSlotNo = 3;
-				//cmds[0].putSlotNo = 4;
-				//cmds[0].subCmd = 5;
-				//cmds[1].sequenceNo = 2;
-				//cmds[1].rcmd = (short)SERVO::RCMD::Transfer;
-				//cmds[1].armNo = 2;
-				//cmds[1].getPosition = 6;
-				//cmds[1].putPosition = 7;
-				//cmds[1].getSlotNo = 8;
-				//cmds[1].putSlotNo = 9;
-				//cmds[1].subCmd = 10;
-				//pEFEM->robotCmds(cmds, 2);
-
-				//CRobotCmdContainerDlg dlg;
-				//if (dlg.DoModal() == IDOK) {
-				//	std::vector<SERVO::ROBOT_CMD_PARAM>& cmds = dlg.GetResultCmds();
-				//	if (!cmds.empty()) {
-				//		pEFEM->robotCmds(cmds.data(), (int)cmds.size());
-				//	}
-				//}
-
-				CRobotCmdTestDlg dlg;
-				dlg.SetEFEM(pEFEM);
-				dlg.DoModal();
-			}
-
-
 
 
 			// 娴嬭瘯涓嬪彂Cim Message
@@ -356,7 +323,7 @@
 			
 
 			/*
-			SERVO::CGlass* pGlass = pEquipment->getFrontGlass();
+			SERVO::CGlass* pGlass = pEquipment->getAnyGlass();
 			if (pGlass != nullptr) {
 				std::string strDescription;
 				SERVO::CPath* pPath = pGlass->getPath();
@@ -462,7 +429,7 @@
 		m_pEqsGraphWnd->AddPin(pItem, OUTPIN, outPin->getName().c_str(), (DWORD_PTR)outPin);
 	}
 
-	m_pEqsGraphWnd->ShowItemIndicator((DWORD_PTR)pEquipment, !pEquipment->isGlassListEmpty());
+	m_pEqsGraphWnd->ShowItemIndicator((DWORD_PTR)pEquipment, pEquipment->hasGlass());
 }
 
 void CPageGraph2::OnTimer(UINT_PTR nIDEvent)
diff --git a/SourceCode/Bond/Servo/CPagePortProperty.cpp b/SourceCode/Bond/Servo/CPagePortProperty.cpp
index b163d01..2ce463e 100644
--- a/SourceCode/Bond/Servo/CPagePortProperty.cpp
+++ b/SourceCode/Bond/Servo/CPagePortProperty.cpp
@@ -60,36 +60,36 @@
 	
 	pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_PORT_TYPE);
 	for (int i = 1; i <= 7; i++) {
-		pComboBox->InsertString(i - 1, SERVO::CLoadPort::getPortTypeDescription(i, strTemp).c_str());
+		pComboBox->InsertString(i - 1, SERVO::CLoadPort::getPortTypeDescription((SERVO::PortType)i, strTemp).c_str());
 	}
-	int portType = m_pPort->getPortType();
+	int portType = (int)m_pPort->getPortType();
 	if (1 <= portType && portType <= 7) {
 		pComboBox->SetCurSel(portType - 1);
 	}
 
 	pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_PORT_MODE);
 	for (int i = 0; i <= 5; i++) {
-		pComboBox->InsertString(i - 1, SERVO::CLoadPort::getPortModeDescription(i, strTemp).c_str());
+		pComboBox->InsertString(i - 1, SERVO::CLoadPort::getPortModeDescription((SERVO::PortMode)i, strTemp).c_str());
 	}
-	int portMode = m_pPort->getPortMode();
+	int portMode = (int)m_pPort->getPortMode();
 	if (0 <= portMode && portMode <= 5) {
 		pComboBox->SetCurSel(portMode);
 	}
 
 	pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_PORT_CASSERT_TYPE);
 	for (int i = 1; i <= 3; i++) {
-		pComboBox->InsertString(i - 1, SERVO::CLoadPort::getPortCassetteTypeDescription(i, strTemp).c_str());
+		pComboBox->InsertString(i - 1, SERVO::CLoadPort::getPortCassetteTypeDescription((SERVO::CassetteType)i, strTemp).c_str());
 	}
-	int cessetteType = m_pPort->getCessetteType();
+	int cessetteType = (int)m_pPort->getCessetteType();
 	if (1 <= cessetteType && cessetteType <= 3) {
 		pComboBox->SetCurSel(cessetteType - 1);
 	}
 
 	pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_PORT_TRANSFER_MODE);
 	for (int i = 1; i <= 3; i++) {
-		pComboBox->InsertString(i - 1, SERVO::CLoadPort::getPortTransferModeDescription(i, strTemp).c_str());
+		pComboBox->InsertString(i - 1, SERVO::CLoadPort::getPortTransferModeDescription((SERVO::TransferMode)i, strTemp).c_str());
 	}
-	int transferMode = m_pPort->getTransferMode();
+	int transferMode = (int)m_pPort->getTransferMode();
 	if (1 <= transferMode && transferMode <= 3) {
 		pComboBox->SetCurSel(transferMode - 1);
 	}
diff --git a/SourceCode/Bond/Servo/CPath.h b/SourceCode/Bond/Servo/CPath.h
index b9dcf5f..f61c4c3 100644
--- a/SourceCode/Bond/Servo/CPath.h
+++ b/SourceCode/Bond/Servo/CPath.h
@@ -7,7 +7,7 @@
 	public:
 		CPath();
 		CPath(unsigned int nSiteId);
-		~CPath();
+		virtual ~CPath();
 
 	public:
 		void getDescription(std::string& strOut);
diff --git a/SourceCode/Bond/Servo/CPin.cpp b/SourceCode/Bond/Servo/CPin.cpp
index f005a61..832e74a 100644
--- a/SourceCode/Bond/Servo/CPin.cpp
+++ b/SourceCode/Bond/Servo/CPin.cpp
@@ -118,7 +118,7 @@
 			return m_pConnectedPin->recvIntent(pIntent);
 		}
 
-		return FLOW_REJECT;
+		return 0;
 	}
 
 	int CPin::recvIntent(CIntent* pIntent)
diff --git a/SourceCode/Bond/Servo/CPortStatusReport.h b/SourceCode/Bond/Servo/CPortStatusReport.h
index 4aede52..21d5048 100644
--- a/SourceCode/Bond/Servo/CPortStatusReport.h
+++ b/SourceCode/Bond/Servo/CPortStatusReport.h
@@ -9,7 +9,7 @@
 	{
 	public:
 		CPortStatusReport();
-		~CPortStatusReport();
+		virtual ~CPortStatusReport();
 
 	public:
 		void copyEx(CPortStatusReport& other);
diff --git a/SourceCode/Bond/Servo/CProcessData.h b/SourceCode/Bond/Servo/CProcessData.h
index 37b0866..2bae1aa 100644
--- a/SourceCode/Bond/Servo/CProcessData.h
+++ b/SourceCode/Bond/Servo/CProcessData.h
@@ -8,7 +8,7 @@
 	{
 	public:
 		CProcessData();
-		~CProcessData();
+		virtual ~CProcessData();
 
 	public:
 		std::string& getGlassId();
diff --git a/SourceCode/Bond/Servo/CRobotCmdTestDlg.cpp b/SourceCode/Bond/Servo/CRobotCmdTestDlg.cpp
index 0a41147..ea62463 100644
--- a/SourceCode/Bond/Servo/CRobotCmdTestDlg.cpp
+++ b/SourceCode/Bond/Servo/CRobotCmdTestDlg.cpp
@@ -127,64 +127,64 @@
 
 	// 蹇嵎鍛戒护鎵ц鏄犲皠琛�
 	m_mapCmdExec = {
-		{_T("SendHome"), [this](int seq, int, int, int, int, int) {
-			return m_pEFEM->SendHome(seq);
+		{_T("SendHome"), [this](int seq, int, int, int, int, int, SERVO::ONWRITED onWritedBlock) {
+			return m_pEFEM->robotSendHome(seq, onWritedBlock);
 		}},
 
-		{_T("SendTransfer"), [this](int seq, int armNo, int getPos, int putPos, int getSlot, int putSlot) {
-			return m_pEFEM->SendTransfer(seq, armNo, getPos, putPos, getSlot, putSlot);
+		{_T("SendTransfer"), [this](int seq, int armNo, int getPos, int putPos, int getSlot, int putSlot, SERVO::ONWRITED onWritedBlock) {
+			return m_pEFEM->robotSendTransfer(seq, armNo, getPos, putPos, getSlot, putSlot, onWritedBlock);
 		}},
 
-		{_T("SendMoveToGet"), [this](int seq, int armNo, int pos, int, int slot, int) {
-			return m_pEFEM->SendMoveToGet(seq, armNo, pos, slot);
+		{_T("SendMoveToGet"), [this](int seq, int armNo, int pos, int, int slot, int, SERVO::ONWRITED onWritedBlock) {
+			return m_pEFEM->robotSendMoveToGet(seq, armNo, pos, slot, onWritedBlock);
 		}},
 
-		{_T("SendMoveToPut"), [this](int seq, int armNo, int, int pos, int, int slot) {
-			return m_pEFEM->SendMoveToPut(seq, armNo, pos, slot);
+		{_T("SendMoveToPut"), [this](int seq, int armNo, int, int pos, int, int slot, SERVO::ONWRITED onWritedBlock) {
+			return m_pEFEM->robotSendMoveToPut(seq, armNo, pos, slot, onWritedBlock);
 		}},
 
-		{_T("SendGet"), [this](int seq, int armNo, int pos, int, int slot, int) {
-			return m_pEFEM->SendGet(seq, armNo, pos, slot);
+		{_T("SendGet"), [this](int seq, int armNo, int pos, int, int slot, int, SERVO::ONWRITED onWritedBlock) {
+			return m_pEFEM->robotSendGet(seq, armNo, pos, slot, onWritedBlock);
 		}},
 
-		{_T("SendPut"), [this](int seq, int armNo, int, int pos, int, int slot) {
-			return m_pEFEM->SendPut(seq, armNo, pos, slot);
+		{_T("SendPut"), [this](int seq, int armNo, int, int pos, int, int slot, SERVO::ONWRITED onWritedBlock) {
+			return m_pEFEM->robotSendPut(seq, armNo, pos, slot, onWritedBlock);
 		}},
 
-		{_T("SendExchange"), [this](int seq, int armNo, int pos, int, int getSlot, int putSlot) {
-			return m_pEFEM->SendExchange(seq, armNo, pos, getSlot, putSlot);
+		{_T("SendExchange"), [this](int seq, int armNo, int pos, int, int getSlot, int putSlot, SERVO::ONWRITED onWritedBlock) {
+			return m_pEFEM->robotSendExchange(seq, armNo, pos, getSlot, putSlot, onWritedBlock);
 		}},
 
-		{_T("SendCommandClear"), [this](int seq, int, int, int, int, int) {
-			return m_pEFEM->SendCommandClear(seq);
+		{_T("SendCommandClear"), [this](int seq, int, int, int, int, int, SERVO::ONWRITED onWritedBlock) {
+			return m_pEFEM->robotSendCommandClear(seq, onWritedBlock);
 		}},
 
-		{_T("SendBatchGet"), [this](int seq, int armNo, int pos, int, int slot, int) {
-			return m_pEFEM->SendBatchGet(seq, pos, slot);
+		{_T("SendBatchGet"), [this](int seq, int armNo, int pos, int, int slot, int, SERVO::ONWRITED onWritedBlock) {
+			return m_pEFEM->robotSendBatchGet(seq, pos, slot, onWritedBlock);
 		}},
 
-		{_T("SendBatchPut"), [this](int seq, int armNo, int, int pos, int, int slot) {
-			return m_pEFEM->SendBatchPut(seq, pos, slot);
+		{_T("SendBatchPut"), [this](int seq, int armNo, int, int pos, int, int slot, SERVO::ONWRITED onWritedBlock) {
+			return m_pEFEM->robotSendBatchPut(seq, pos, slot, onWritedBlock);
 		}},
 
-		{_T("SendMoveToGetAndHome"), [this](int seq, int armNo, int pos, int, int slot, int) {
-			return m_pEFEM->SendMoveToGetAndHome(seq, armNo, pos, slot);
+		{_T("SendMoveToGetAndHome"), [this](int seq, int armNo, int pos, int, int slot, int, SERVO::ONWRITED onWritedBlock) {
+			return m_pEFEM->robotSendMoveToGetAndHome(seq, armNo, pos, slot, onWritedBlock);
 		}},
 
-		{_T("SendMoveToPutAndHome"), [this](int seq, int armNo, int, int pos, int, int slot) {
-			return m_pEFEM->SendMoveToPutAndHome(seq, armNo, pos, slot);
+		{_T("SendMoveToPutAndHome"), [this](int seq, int armNo, int, int pos, int, int slot, SERVO::ONWRITED onWritedBlock) {
+			return m_pEFEM->robotSendMoveToPutAndHome(seq, armNo, pos, slot, onWritedBlock);
 		}},
 
-		{_T("SendTransferAndHome"), [this](int seq, int armNo, int getPos, int putPos, int getSlot, int putSlot) {
-			return m_pEFEM->SendTransferAndHome(seq, armNo, getPos, putPos, getSlot, putSlot);
+		{_T("SendTransferAndHome"), [this](int seq, int armNo, int getPos, int putPos, int getSlot, int putSlot, SERVO::ONWRITED onWritedBlock) {
+			return m_pEFEM->robotSendTransferAndHome(seq, armNo, getPos, putPos, getSlot, putSlot, onWritedBlock);
 		}},
 
-		{_T("SendGetAndPut"), [this](int seq, int armNo, int getPos, int putPos, int getSlot, int putSlot) {
-			return m_pEFEM->SendGetAndPut(seq, armNo, getPos, putPos, getSlot, putSlot);
+		{_T("SendGetAndPut"), [this](int seq, int armNo, int getPos, int putPos, int getSlot, int putSlot, SERVO::ONWRITED onWritedBlock) {
+			return m_pEFEM->robotSendGetAndPut(seq, armNo, getPos, putPos, getSlot, putSlot, onWritedBlock);
 		}},
 
-		{_T("SendPutAndHome"), [this](int seq, int armNo, int, int pos, int, int slot) {
-			return m_pEFEM->SendPutAndHome(seq, armNo, pos, slot);
+		{_T("SendPutAndHome"), [this](int seq, int armNo, int, int pos, int, int slot, SERVO::ONWRITED onWritedBlock) {
+			return m_pEFEM->robotSendPutAndHome(seq, armNo, pos, slot, onWritedBlock);
 		}}
 	};
 
@@ -333,7 +333,16 @@
 	// 鏌ユ壘鍑芥暟骞舵墽琛�
 	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 ret = it->second(1, armNo, getPos, getSlot, putPos, putSlot, [&](int code) -> int {
+			if (code == WOK) {
+				AppendLogLineRichStyled(_T("宸叉敹鍒癛obot鍥炲簲锛�"), LOG_COLOR_SUCCESS);
+			}
+			else {
+				AppendLogLineRichStyled(_T("鏈敹鍒癛obot鍥炲簲锛�"), LOG_COLOR_ERROR);
+			}
+
+			return 0;
+			});
 
 		CString log;
 		if (ret == 0) {
diff --git a/SourceCode/Bond/Servo/CRobotCmdTestDlg.h b/SourceCode/Bond/Servo/CRobotCmdTestDlg.h
index 065ee0a..c605e58 100644
--- a/SourceCode/Bond/Servo/CRobotCmdTestDlg.h
+++ b/SourceCode/Bond/Servo/CRobotCmdTestDlg.h
@@ -3,7 +3,7 @@
 #include <afxrich.h>
 
 // 瀹氫箟鍛戒护鍑芥暟鎸囬拡绫诲瀷锛坰eq, armNo, getPos, getSlot, putPos, putSlot锛�
-using CmdFunc = std::function<int(int, int, int, int, int, int)>;
+using CmdFunc = std::function<int(int, int, int, int, int, int, SERVO::ONWRITED onWritedBlock)>;
 
 // 杈撳叆鎺т欢鐘舵��
 struct QuickCmdFieldMask {
diff --git a/SourceCode/Bond/Servo/CRobotTask.cpp b/SourceCode/Bond/Servo/CRobotTask.cpp
new file mode 100644
index 0000000..3b19a24
--- /dev/null
+++ b/SourceCode/Bond/Servo/CRobotTask.cpp
@@ -0,0 +1,167 @@
+#include "stdafx.h"
+#include "CRobotTask.h"
+#include "ToolUnits.h"
+
+
+namespace SERVO {
+	CRobotTask::CRobotTask()
+	{
+		generateId(m_strId);
+		m_state = ROBOT_TASK_STATE::Ready;
+		m_timeCreate = CToolUnits::getTimestamp();
+		m_timeFetchOut = 0;
+		m_timeStored = 0;
+		m_timeFinish = 0;
+		m_pContext = nullptr;
+	}
+
+	CRobotTask::~CRobotTask()
+	{
+		if (m_pContext != nullptr) {
+			m_pContext->release();
+			m_pContext = nullptr;
+		}
+	}
+
+	std::string CRobotTask::getDescription() const
+	{
+		std::string strOut = "CRobotTask<ID:";
+		strOut = strOut + std::to_string(m_robotCmdParam.sequenceNo);
+		strOut = strOut + ",Arm:";
+		strOut = strOut + std::to_string(m_robotCmdParam.armNo);
+		strOut = strOut + ",GetPossion:";
+		strOut = strOut + std::to_string(m_robotCmdParam.getPosition);
+		strOut = strOut + ",GetSlot:";
+		strOut = strOut + std::to_string(m_robotCmdParam.getSlotNo);
+		strOut = strOut + ",PutPossion:";
+		strOut = strOut + std::to_string(m_robotCmdParam.putPosition);
+		strOut = strOut + ",PutSlot:";
+		strOut = strOut + std::to_string(m_robotCmdParam.putSlotNo);
+		strOut = strOut + ">";
+
+		return strOut;
+	}
+
+	void CRobotTask::setContext(CContext* pContext)
+	{
+		if (pContext != nullptr) {
+			pContext->release();
+		}
+
+		m_pContext = pContext;
+		if (m_pContext != nullptr) {
+			m_pContext->addRef();
+		}
+	}
+
+	CContext* CRobotTask::getContext()
+	{
+		return m_pContext;
+	}
+
+	std::string& CRobotTask::generateId(std::string& out)
+	{
+		char szBuffer[256];
+		CTime time = CTime::GetCurrentTime();
+		__int64 nTick = 0;
+		QueryPerformanceCounter((LARGE_INTEGER*)&nTick);
+		sprintf_s(szBuffer, 256, "%d%02d%02d%02d%02d%02d%010llu", time.GetYear(),
+			time.GetMonth(), time.GetDay(), time.GetHour(), time.GetMinute(), time.GetSecond(),
+			nTick % 10000000000);
+		out = szBuffer;
+
+		return out;
+	}
+
+	std::string& CRobotTask::getId()
+	{
+		return m_strId;
+	}
+
+	void CRobotTask::setRobotTransferParam(int seq, int armNo, int fromPos, int toPos, int fromSlot, int toSlot)
+	{
+		m_robotCmdParam = {};
+		m_robotCmdParam.sequenceNo = static_cast<short>(seq);
+		m_robotCmdParam.rcmd = static_cast<short>(SERVO::RCMD::Transfer);
+		m_robotCmdParam.armNo = static_cast<short>(armNo);
+		m_robotCmdParam.getPosition = static_cast<short>(fromPos);
+		m_robotCmdParam.getSlotNo = static_cast<short>(fromSlot);
+		m_robotCmdParam.putPosition = static_cast<short>(toPos);
+		m_robotCmdParam.putSlotNo = static_cast<short>(toSlot);
+	}
+
+	ROBOT_CMD_PARAM& CRobotTask::getRobotCmdParam()
+	{
+		return m_robotCmdParam;
+	}
+
+	time_t CRobotTask::getCreateTime()
+	{
+		return m_timeCreate;
+	}
+
+	time_t CRobotTask::getFetchoutTime()
+	{
+		return m_timeFetchOut;
+	}
+
+	time_t CRobotTask::getStoredTime()
+	{
+		return m_timeStored;
+	}
+
+	time_t CRobotTask::getFinishTime()
+	{
+		return m_timeFinish;
+	}
+
+	ROBOT_TASK_STATE CRobotTask::getState()
+	{
+		return m_state;
+	}
+
+	void CRobotTask::completed()
+	{
+		m_state = ROBOT_TASK_STATE::Completed;
+	}
+
+	void CRobotTask::error()
+	{
+		m_state = ROBOT_TASK_STATE::Error;
+	}
+
+	void CRobotTask::abort()
+	{
+		m_state = ROBOT_TASK_STATE::Abort;
+	}
+
+	int CRobotTask::getSrcPosition()
+	{
+		return m_robotCmdParam.getPosition;
+	}
+
+	int CRobotTask::getTarPosition()
+	{
+		return m_robotCmdParam.putPosition;
+	}
+
+	int CRobotTask::getSrcSlot()
+	{
+		return m_robotCmdParam.getSlotNo;
+	}
+
+	int CRobotTask::getTarSlot()
+	{
+		return m_robotCmdParam.putSlotNo;
+	}
+
+	void CRobotTask::fetchOut()
+	{
+		m_timeFetchOut = CToolUnits::getTimestamp();;
+	}
+
+	void CRobotTask::stored()
+	{
+		m_timeStored = CToolUnits::getTimestamp();;
+	}
+}
diff --git a/SourceCode/Bond/Servo/CRobotTask.h b/SourceCode/Bond/Servo/CRobotTask.h
new file mode 100644
index 0000000..1fee5f2
--- /dev/null
+++ b/SourceCode/Bond/Servo/CRobotTask.h
@@ -0,0 +1,52 @@
+#pragma once
+#include "ServoCommo.h"
+#include "Context.h"
+
+
+namespace SERVO {
+	class CRobotTask
+	{
+	public:
+		CRobotTask();
+		virtual ~CRobotTask();
+
+	public:
+		std::string& getId();
+		std::string getDescription() const;
+		void setContext(CContext* pContext);
+		CContext* getContext();
+		void setRobotTransferParam(int seq, int armNo, int fromPos, int toPos, int fromSlot, int toSlot);
+		ROBOT_CMD_PARAM& getRobotCmdParam();
+		time_t getCreateTime();
+		time_t getFetchoutTime();
+		time_t getStoredTime();
+		time_t getFinishTime();
+		ROBOT_TASK_STATE getState();
+		void completed();
+		void error();
+		void abort();
+		int getSrcPosition();
+		int getSrcSlot();
+		int getTarPosition();
+		int getTarSlot();
+
+		// 从源地拔片
+		void fetchOut();
+
+		// 在目的地放片
+		void stored();
+
+	private:
+		static std::string& generateId(std::string& out);
+
+	private:
+		ROBOT_TASK_STATE m_state;					/* 任务状态 */
+		std::string m_strId;
+		time_t m_timeCreate;						/* 创建时间 */
+		time_t m_timeFetchOut;						/* 取片时间*/
+		time_t m_timeStored;						/* 放片时间 */
+		time_t m_timeFinish;						/* 结束时间 */
+		ROBOT_CMD_PARAM m_robotCmdParam;			/* 参数 */
+		CContext* m_pContext;
+	};
+}
diff --git a/SourceCode/Bond/Servo/CSlot.cpp b/SourceCode/Bond/Servo/CSlot.cpp
new file mode 100644
index 0000000..8972986
--- /dev/null
+++ b/SourceCode/Bond/Servo/CSlot.cpp
@@ -0,0 +1,152 @@
+#include "stdafx.h"
+#include "CSlot.h"
+
+
+namespace SERVO {
+	CSlot::CSlot()
+	{
+		m_nNo = 0;
+		m_materialsType = MaterialsType::G1G2;
+		m_pContext = nullptr;
+		m_bEnable = FALSE;
+		m_bLock = FALSE;
+		m_pContext = nullptr;
+	}
+
+	CSlot::~CSlot()
+	{
+		if (m_pContext != nullptr) {
+			m_pContext->release();
+			m_pContext = nullptr;
+		}
+	}
+
+	BOOL CSlot::isEnable()
+	{
+		return m_bEnable;
+	}
+
+	void CSlot::enable()
+	{
+		m_bEnable = TRUE;
+	}
+
+	void CSlot::disable()
+	{
+		m_bEnable = FALSE;
+	}
+
+	BOOL CSlot::isLock()
+	{
+		return m_bLock;
+	}
+
+	void CSlot::lock()
+	{
+		m_bLock = TRUE;
+	}
+
+	void CSlot::unlock()
+	{
+		m_bLock = FALSE;
+	}
+
+	int CSlot::getPosition()
+	{
+		return m_nPosition;
+	}
+
+	void CSlot::setPosition(int position)
+	{
+		m_nPosition = position;
+	}
+
+	int CSlot::getNo()
+	{
+		return m_nNo;
+	}
+
+	void CSlot::setNo(int no)
+	{
+		m_nNo = no;
+	}
+
+	MaterialsType CSlot::getType()
+	{
+		return m_materialsType;
+	}
+
+	void CSlot::setType(MaterialsType type)
+	{
+		m_materialsType = type;
+	}
+
+	std::string& CSlot::getName()
+	{
+		return m_strName;
+	}
+
+	void CSlot::setName(const char* pszName)
+	{
+		m_strName = pszName;
+	}
+
+	BOOL CSlot::isEmpty()
+	{
+		return m_pContext == nullptr;
+	}
+
+	void CSlot::setContext(CContext* pContext)
+	{
+		if (pContext != nullptr) {
+			pContext->release();
+		}
+
+		m_pContext = pContext;
+		if (m_pContext != nullptr) {
+			m_pContext->addRef();
+		}
+	}
+
+	CContext* CSlot::getContext()
+	{
+		return m_pContext;
+	}
+
+	void CSlot::serialize(CArchive& ar)
+	{
+		if (ar.IsStoring()) {
+			ar << m_nPosition;
+			ar << m_nNo;
+			ar << (int)m_materialsType;
+			WriteString(ar, m_strName);
+			ar << (__int64)m_pContext;
+			ar << m_bEnable;
+			ar << m_bLock;
+		}
+		else {
+			int i32;
+			__int64 i64;
+			ar >> m_nPosition;
+			ar >> m_nNo;
+			ar >> i32; m_materialsType = (MaterialsType)i32;
+			ReadString(ar, m_strName);
+			ar >> i64; m_pContext = (CContext*)i64;
+			ar >> m_bEnable;
+			ar >> m_bLock;
+		}
+	}
+
+	void CSlot::WriteString(CArchive& ar, std::string& string)
+	{
+		CString strTemp = string.c_str();
+		ar << strTemp;
+	}
+
+	void CSlot::ReadString(CArchive& ar, std::string& string)
+	{
+		CString strTemp;
+		ar >> strTemp;
+		string = (LPTSTR)(LPCTSTR)strTemp;
+	}
+}
diff --git a/SourceCode/Bond/Servo/CSlot.h b/SourceCode/Bond/Servo/CSlot.h
new file mode 100644
index 0000000..1d783d2
--- /dev/null
+++ b/SourceCode/Bond/Servo/CSlot.h
@@ -0,0 +1,47 @@
+#pragma once
+#include "Context.h"
+#include "ServoCommo.h"
+
+
+namespace SERVO {
+	class CSlot
+	{
+	public:
+		CSlot();
+		virtual ~CSlot();
+
+	public:
+		BOOL isEnable();
+		void enable();
+		void disable();
+		BOOL isLock();
+		void lock();
+		void unlock();
+		int getPosition();
+		void setPosition(int position);
+		int getNo();
+		void setNo(int no);
+		MaterialsType getType();
+		void setType(MaterialsType type);
+		std::string& getName();
+		void setName(const char* pszName);
+		BOOL isEmpty();
+		CContext* getContext();
+		void setContext(CContext* pContext);
+		void serialize(CArchive& ar);
+
+	private:
+		void WriteString(CArchive& ar, std::string& string);
+		void ReadString(CArchive& ar, std::string& string);
+
+	private:
+		int m_nPosition;
+		int m_nNo;
+		MaterialsType m_materialsType;
+		std::string m_strName;
+		CContext* m_pContext;
+		BOOL m_bEnable;
+		BOOL m_bLock;
+	};
+}
+
diff --git a/SourceCode/Bond/Servo/CVacuumBake.cpp b/SourceCode/Bond/Servo/CVacuumBake.cpp
index 790e3e3..290035f 100644
--- a/SourceCode/Bond/Servo/CVacuumBake.cpp
+++ b/SourceCode/Bond/Servo/CVacuumBake.cpp
@@ -38,6 +38,16 @@
 		addPin(SERVO::PinType::OUTPUT, _T("Out"));
 	}
 
+	// 必须要实现的虚函数,在此初始化Slot信息
+	void CVacuumBake::initSlots()
+	{
+		m_slot[0].enable();
+		m_slot[0].setPosition(m_nID);
+		m_slot[0].setNo(1);
+		m_slot[0].setName("Slot 1(G1)");
+		m_slot[0].setType(MaterialsType::G1);
+	}
+
 	void CVacuumBake::onTimer(UINT nTimerid)
 	{
 		CEquipment::onTimer(nTimerid);
@@ -56,41 +66,6 @@
 	int CVacuumBake::recvIntent(CPin* pPin, CIntent* pIntent)
 	{
 		return __super::recvIntent(pPin, pIntent);
-	}
-
-	BOOL CVacuumBake::glassWillArrive(CGlass* pGlass)
-	{
-		BOOL bRet = __super::glassWillArrive(pGlass);
-		if (!bRet) {
-			return FALSE;
-		}
-
-		return m_glassList.empty();
-	}
-
-	BOOL CVacuumBake::onPreStoredJob(int port, CJobDataB* pJobDataB)
-	{
-		CJobDataS* pJobDataS = getJobDataS(pJobDataB->getCassetteSequenceNo(), pJobDataB->getJobSequenceNo());
-		if (pJobDataS == nullptr) {
-			LOGE("<CVacuumBake-%s>onPreFetchedOutJob,找不到对应的JobDataS(CassetteSequenceNo:%d, JobSequenceNo:%d), 注意排查风险!", m_strName.c_str(),
-				pJobDataB->getCassetteSequenceNo(), pJobDataB->getJobSequenceNo());
-			return FALSE;
-		}
-
-		// 当前不能有任何玻璃,且当前准备进的片是G1
-		Lock();
-		if (!m_glassList.empty()) {
-			Unlock();
-			LOGE("<CVacuumBake-%s>onPreFetchedOutJob,当前机器或单元存在玻璃片,不能进料,请注意风险!", m_strName.c_str());
-			return FALSE;
-		}
-
-		if (pJobDataS->getMaterialsType() != (int)MaterialsType::G1) {
-			LOGE("<CVacuumBake-%s>onPreFetchedOutJob,当前机器或单元只能进G2玻璃片,请注意风险!", m_strName.c_str());
-			return FALSE;
-		}
-
-		return TRUE;
 	}
 
 	int CVacuumBake::getIndexerOperationModeBaseValue()
diff --git a/SourceCode/Bond/Servo/CVacuumBake.h b/SourceCode/Bond/Servo/CVacuumBake.h
index ef0e1ea..8619b43 100644
--- a/SourceCode/Bond/Servo/CVacuumBake.h
+++ b/SourceCode/Bond/Servo/CVacuumBake.h
@@ -15,12 +15,11 @@
         virtual void init();
         virtual void term();
         virtual void initPins();
+        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 BOOL glassWillArrive(CGlass* pGlass);
-        virtual BOOL onPreStoredJob(int port, CJobDataB* pJobDataB);
         virtual int getIndexerOperationModeBaseValue();
 
 	};
diff --git a/SourceCode/Bond/Servo/CVcrEventReport.h b/SourceCode/Bond/Servo/CVcrEventReport.h
index 8ff3992..409a1f4 100644
--- a/SourceCode/Bond/Servo/CVcrEventReport.h
+++ b/SourceCode/Bond/Servo/CVcrEventReport.h
@@ -8,7 +8,7 @@
 	{
 	public:
 		CVcrEventReport();
-		~CVcrEventReport();
+		virtual ~CVcrEventReport();
 
 	public:
 		std::string& getGlassId();
diff --git a/SourceCode/Bond/Servo/Common.h b/SourceCode/Bond/Servo/Common.h
index 7d09612..f0e5917 100644
--- a/SourceCode/Bond/Servo/Common.h
+++ b/SourceCode/Bond/Servo/Common.h
@@ -16,6 +16,7 @@
 #define RX_CODE_ALARM_SET				1008
 #define RX_CODE_ALARM_CLEAR				1009
 #define RX_CODE_EQ_DATA_CHANGED			1010
+#define RX_CODE_MASTER_STATE_CHANGED	1011
 
 
 /* Channel Name */
@@ -37,7 +38,10 @@
 #define CR_MSGBOX_BKGND						RGB(7, 71, 166)
 #define CR_MSGBOX_TITLE						RGB(200, 216, 246)
 #define CR_MSGBOX_MESSAGE					RGB(200, 216, 246)
-
+#define TOP_TOOLBAR_BACKGROUND				RGB(240, 240, 240)	
+#define STATUSBAR_BK_NORMAL					RGB(195, 195, 195)
+#define STATUSBAR_BK_RUNNING				RGB(34, 177, 76)
+#define STATUSBAR_BK_ALARM					RGB(255, 127, 39)
 
 /* LOG BTN */
 #define BTN_LOG_FRAME_NORMAL			RGB(88, 88, 88)
@@ -56,22 +60,22 @@
 #define BTN_ALARM_BKGND_PRESS			RGB(133, 203, 225)
 
 /* Equipment ID */
-#define EQ_ID_EFEM				1
-#define EQ_ID_Bonder1			2
-#define EQ_ID_Bonder2			3
-#define EQ_ID_LOADPORT1			4
-#define EQ_ID_LOADPORT2			5
-#define EQ_ID_LOADPORT3			6
-#define EQ_ID_LOADPORT4			7
+#define EQ_ID_LOADPORT1			1
+#define EQ_ID_LOADPORT2			2
+#define EQ_ID_LOADPORT3			3
+#define EQ_ID_LOADPORT4			4
+#define EQ_ID_ARM_TRAY1			5
+#define EQ_ID_ARM_TRAY2			6
+#define EQ_ID_ALIGNER			7
 #define EQ_ID_FLIPER			8
 #define EQ_ID_VACUUMBAKE		9
-#define EQ_ID_ALIGNER			10
-#define EQ_ID_BAKE_COOLING		11
-#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
+#define EQ_ID_Bonder1			10
+#define EQ_ID_Bonder2			11
+#define EQ_ID_BAKE_COOLING		12
+#define EQ_ID_MEASUREMENT		13
+#define EQ_ID_EFEM				100
+#define EQ_ID_ARM				101
+#define EQ_ID_OPERATOR_REMOVE	102
 
 
 /* step name */
@@ -405,12 +409,7 @@
 
 
 /* 流程控制相关代码 */
-#define FLOW_REJECT					0x0
-#define FLOW_ACCEPT					0x1
 #define FLOW_TEST					0x1000
-#define FLOW_SIGNAL					0x1001
-#define FLOW_DATA					0x1002
-#define FLOW_MOVE_MATERIAL			0x1003
 
 
 /* Port Status */
diff --git a/SourceCode/Bond/Servo/Model.cpp b/SourceCode/Bond/Servo/Model.cpp
index 14e2af9..c991c64 100644
--- a/SourceCode/Bond/Servo/Model.cpp
+++ b/SourceCode/Bond/Servo/Model.cpp
@@ -29,6 +29,11 @@
 	return m_pObservable;
 }
 
+SERVO::CMaster& CModel::getMaster()
+{
+	return m_master;
+}
+
 void CModel::setWorkDir(const char* pszWorkDir)
 {
 	m_strWorkDir = pszWorkDir;
@@ -98,6 +103,10 @@
 
 
 	SERVO::MasterListener masterListener;
+	masterListener.onMasterStateChanged = [&](void* pMaster, SERVO::MASTERSTATE state) -> void {
+		LOGI("<CModel>Master state changed(%d)", (int)state);
+		notify(RX_CODE_MASTER_STATE_CHANGED);
+	};
 	masterListener.onEqAlive = [&](void* pMaster, SERVO::CEquipment* pEquipment, BOOL bAlive) -> void {
 		LOGI("<CModel>Equipment onAlive:%s(%s).\n", pEquipment->getName().c_str(),
 			bAlive ? _T("ON") : _T("OFF"));
diff --git a/SourceCode/Bond/Servo/Model.h b/SourceCode/Bond/Servo/Model.h
index a4985ed..a9e5369 100644
--- a/SourceCode/Bond/Servo/Model.h
+++ b/SourceCode/Bond/Servo/Model.h
@@ -12,6 +12,7 @@
 
 public:
 	IObservable* getObservable();
+	SERVO::CMaster& getMaster();
 	void setWorkDir(const char* pszWorkDir);
 	int init();
 	int term();
diff --git a/SourceCode/Bond/Servo/Servo.cpp b/SourceCode/Bond/Servo/Servo.cpp
index 18a95a1..657947a 100644
--- a/SourceCode/Bond/Servo/Servo.cpp
+++ b/SourceCode/Bond/Servo/Servo.cpp
@@ -10,6 +10,7 @@
 #include "SECSRuntimeManager.h"
 #include "TransferManager.h"
 #include "VerticalLine.h"
+#include "HorizontalLine.h"
 #include "EqsGraphWnd.h"
 #include "MapPosWnd.h"
 #include "HmTab.h"
@@ -99,6 +100,7 @@
 	// 注册控件
 	CServoGraph::RegisterWndClass();
 	CVerticalLine::RegisterWndClass();
+	CHorizontalLine::RegisterWndClass();
 	CEqsGraphWnd::RegisterWndClass();
 	CMapPosWnd::RegisterWndClass();
 	CHmTab::RegisterWndClass();
diff --git a/SourceCode/Bond/Servo/Servo.rc b/SourceCode/Bond/Servo/Servo.rc
index 140d51f..5a24a9f 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 11eb375..4ef99c5 100644
--- a/SourceCode/Bond/Servo/Servo.vcxproj
+++ b/SourceCode/Bond/Servo/Servo.vcxproj
@@ -200,6 +200,7 @@
   <ItemGroup>
     <ClInclude Include="CEquipmentPage3.h" />
     <ClInclude Include="CGlassPool.h" />
+    <ClInclude Include="CMyStatusbar.h" />
     <ClInclude Include="CRobotCmdContainerDlg.h" />
     <ClInclude Include="CRobotCmdTestDlg.h" />
     <ClInclude Include="CPagePortStatus.h" />
@@ -218,6 +219,9 @@
     <ClInclude Include="GridControl\NewCellTypes\GridCellNumeric.h" />
     <ClInclude Include="GridControl\NewCellTypes\GridURLCell.h" />
     <ClInclude Include="GridControl\TitleTip.h" />
+    <ClInclude Include="CRobotTask.h" />
+    <ClInclude Include="CSlot.h" />
+    <ClInclude Include="HorizontalLine.h" />
     <ClInclude Include="JobSlotGrid.h" />
     <ClInclude Include="MsgDlg.h" />
     <ClInclude Include="PageRecipe.h" />
@@ -318,11 +322,13 @@
     <ClInclude Include="TerminalDisplayDlg.h" />
     <ClInclude Include="ToolUnits.h" />
     <ClInclude Include="TransferManager.h" />
+    <ClInclude Include="TopToolbar.h" />
     <ClInclude Include="VerticalLine.h" />
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="CEquipmentPage3.cpp" />
     <ClCompile Include="CGlassPool.cpp" />
+    <ClCompile Include="CMyStatusbar.cpp" />
     <ClCompile Include="CRobotCmdContainerDlg.cpp" />
     <ClCompile Include="CRobotCmdTestDlg.cpp" />
     <ClCompile Include="CPagePortStatus.cpp" />
@@ -339,6 +345,9 @@
     <ClCompile Include="GridControl\NewCellTypes\GridCellNumeric.cpp" />
     <ClCompile Include="GridControl\NewCellTypes\GridURLCell.cpp" />
     <ClCompile Include="GridControl\TitleTip.cpp" />
+    <ClCompile Include="CRobotTask.cpp" />
+    <ClCompile Include="CSlot.cpp" />
+    <ClCompile Include="HorizontalLine.cpp" />
     <ClCompile Include="JobSlotGrid.cpp" />
     <ClCompile Include="MsgDlg.cpp" />
     <ClCompile Include="PageRecipe.cpp" />
@@ -440,6 +449,7 @@
     <ClCompile Include="TerminalDisplayDlg.cpp" />
     <ClCompile Include="ToolUnits.cpp" />
     <ClCompile Include="TransferManager.cpp" />
+    <ClCompile Include="TopToolbar.cpp" />
     <ClCompile Include="VerticalLine.cpp" />
   </ItemGroup>
   <ItemGroup>
diff --git a/SourceCode/Bond/Servo/Servo.vcxproj.filters b/SourceCode/Bond/Servo/Servo.vcxproj.filters
index 1a8bb3f..f81b1d2 100644
--- a/SourceCode/Bond/Servo/Servo.vcxproj.filters
+++ b/SourceCode/Bond/Servo/Servo.vcxproj.filters
@@ -150,6 +150,11 @@
     </ClCompile>
     <ClCompile Include="PortConfigurationDlg.cpp" />
     <ClCompile Include="TransferManager.cpp" />
+    <ClCompile Include="TopToolbar.cpp" />
+    <ClCompile Include="HorizontalLine.cpp" />
+    <ClCompile Include="CMyStatusbar.cpp" />
+    <ClCompile Include="CRobotTask.cpp" />
+    <ClCompile Include="CSlot.cpp" />
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="AlarmManager.h" />
@@ -305,6 +310,11 @@
     </ClInclude>
     <ClInclude Include="PortConfigurationDlg.h" />
     <ClInclude Include="TransferManager.h" />
+    <ClInclude Include="TopToolbar.h" />
+    <ClInclude Include="HorizontalLine.h" />
+    <ClInclude Include="CMyStatusbar.h" />
+    <ClInclude Include="CRobotTask.h" />
+    <ClInclude Include="CSlot.h" />
   </ItemGroup>
   <ItemGroup>
     <ResourceCompile Include="Servo.rc" />
diff --git a/SourceCode/Bond/Servo/ServoCommo.h b/SourceCode/Bond/Servo/ServoCommo.h
index 959a8a1..acfd20a 100644
--- a/SourceCode/Bond/Servo/ServoCommo.h
+++ b/SourceCode/Bond/Servo/ServoCommo.h
@@ -2,7 +2,12 @@
 
 
 namespace SERVO {
-	enum PortType {
+#define BLOCK_BUFFER_MAX			1024
+#define ALIVE_TIMEOUT				15
+#define VCR_MAX						1
+#define ARM_ALL						99
+
+	enum class PortType {
 		Loading = 1,
 		Unloading,
 		Both,
@@ -12,7 +17,7 @@
 		UnloadingPartial
 	};
 
-	enum PortMode {
+	enum class PortMode {
 		OutOfService = 0,
 		TransferBlocked,
 		ReadyToLoad,
@@ -21,17 +26,95 @@
 		TransferReady
 	};
 
-	enum MaterialsType {
-		G1 = 0,
-		G2 = 1,
-		G1G2 = 2
+	enum class MaterialsType {
+		G1 = 1,
+		G2 = 2,
+		G1G2 = 3
 	};
 	typedef MaterialsType CassetteType;
 
-	enum TransferMode {
+	enum class TransferMode {
 		MGVMode = 1,
 		AGVMode,
 		StockerInlineMode
 	};
+
+	// Memory Block 结构体定义
+	typedef struct _MemoryBlock {
+		unsigned int type;
+		unsigned int start;
+		unsigned int end;
+		unsigned int size;
+		char buffer[BLOCK_BUFFER_MAX];
+	} MemoryBlock;
+
+	// ALIVE
+	typedef struct _ALIVE {
+		BOOL flag;
+		int count;
+		BOOL alive;
+	} ALIVE;
+
+	enum class DISPATCHING_MODE {
+		EAS = 1,
+		Local = 2
+	};
+
+	enum class IDNEXER_OPERATION_MODE {
+		Normal = 1,
+		Clear_Out = 2,
+		Cold_Run = 2,
+		Start = 10,
+		Stop = 11,
+		Pause = 12,
+		Resume = 13,
+		Abort = 14,
+		Cancel = 15,
+	};
+
+	enum class VCR_Reply_Code {
+		OK = 1,
+		NG,
+		Job_Data_Request,
+		VCR_Mismatch
+	};
+
+	// Robot cmd param
+#define ROBOT_CMD_PARAM_SIZE		16			/* 防止以后修改ROBOT_CMD_PARAM为不是4的整数倍 */
+	typedef struct _ROBOT_CMD_PARAM {
+		short sequenceNo;
+		short rcmd;
+		short armNo;
+		short getPosition;
+		short putPosition;
+		short getSlotNo;
+		short putSlotNo;
+		short subCmd;
+	} ROBOT_CMD_PARAM;
+
+	enum class RCMD {
+		Robot_home = 1,
+		Transfer,
+		Move,
+		Get,
+		Put,
+		One_Action_Exchange,
+		Two_Action_Exchange,
+		Command_Clear,
+		Batch_get,
+		Batch_put
+	};
+
+	enum class ROBOT_TASK_STATE {
+		Ready = 0,
+		Running,
+		Error,
+		Abort,
+		Completed
+	};
+
+	/* EQ Data changed code */
+#define EDCC_FETCHOUT_JOB				1000	/* 取片 */
+#define EDCC_STORED_JOB					1001	/* 放片 */
 }
 
diff --git a/SourceCode/Bond/Servo/ServoDlg.cpp b/SourceCode/Bond/Servo/ServoDlg.cpp
index af02e73..6ce2bf0 100644
--- a/SourceCode/Bond/Servo/ServoDlg.cpp
+++ b/SourceCode/Bond/Servo/ServoDlg.cpp
@@ -13,6 +13,8 @@
 #include <thread>
 #include <cmath>
 #include "HmTab.h"
+#include "CRobotCmdContainerDlg.h"
+#include "CRobotCmdTestDlg.h"
 
 
 #ifdef _DEBUG
@@ -22,6 +24,10 @@
 
 /* 创建终端的定时器 */
 #define TIMER_ID_CREATE_TERMINAL		1
+
+/* 运行时间定时器 */
+#define TIMER_ID_UPDATE_RUMTIME			2
+
 
 
 // 用于应用程序“关于”菜单项的 CAboutDlg 对话框
@@ -76,6 +82,8 @@
 	m_pPageAlarm = nullptr;
 	m_pPageLog = nullptr;
 	m_pPageRecipe = nullptr;
+	m_pTopToolbar = nullptr;
+	m_pMyStatusbar = nullptr;
 }
 
 void CServoDlg::DoDataExchange(CDataExchange* pDX)
@@ -110,6 +118,7 @@
 	ON_WM_TIMER()
 	ON_MESSAGE(ID_MSG_PANEL_RESIZE, OnPanelResize)
 	ON_NOTIFY(BYHMTAB_SEL_CHANGED, IDC_TAB1, &CServoDlg::OnTabSelChanged)
+	ON_MESSAGE(ID_MSG_TOOLBAR_BTN_CLICKED, &CServoDlg::OnToolbarBtnClicked)
 END_MESSAGE_MAP()
 
 
@@ -158,6 +167,22 @@
 						m_pPanelAttributes->ShowWindow(SW_SHOW);
 						Resize();
 					}
+				}
+			}
+			else if (RX_CODE_MASTER_STATE_CHANGED == code) {
+				SERVO::MASTERSTATE state = theApp.m_model.getMaster().getState();
+				if (state == SERVO::MASTERSTATE::READY) {
+					m_pMyStatusbar->setBackgroundColor(STATUSBAR_BK_NORMAL);
+					m_pMyStatusbar->setForegroundColor(RGB(0, 0, 0));
+					KillTimer(TIMER_ID_UPDATE_RUMTIME);
+					CString strText;
+					GetRuntimeFormatText(strText, "");
+					m_pMyStatusbar->setRunTimeText((LPTSTR)(LPCTSTR)strText);
+				}
+				else if (state == SERVO::MASTERSTATE::RUNNING) {
+					m_pMyStatusbar->setBackgroundColor(STATUSBAR_BK_RUNNING);
+					m_pMyStatusbar->setForegroundColor(RGB(255, 255, 255));
+					SetTimer(TIMER_ID_UPDATE_RUMTIME, 500, nullptr);
 				}
 			}
 
@@ -210,6 +235,17 @@
 	SetMenu(&menu);
 
 
+	// toolbar
+	m_pTopToolbar = new CTopToolbar();
+	m_pTopToolbar->Create(IDD_TOP_TOOLBAR, this);
+	m_pTopToolbar->ShowWindow(SW_SHOW);
+	m_pTopToolbar->GetBtn(IDC_BUTTON_STOP)->EnableWindow(FALSE);
+	m_pTopToolbar->GetBtn(IDC_BUTTON_ALARM)->EnableWindow(FALSE);
+	HMENU hMenu = m_pTopToolbar->GetOperatorMenu();
+	ASSERT(hMenu);
+	::EnableMenuItem(hMenu, ID_OPEATOR_SWITCH, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
+	
+
 	// Tab
 	m_pPageGraph1 = new CPageGraph1();
 	m_pPageGraph1->Create(IDD_PAGE_GRAPH1, this);
@@ -243,6 +279,13 @@
 	m_pPanelAttributes = new CPanelAttributes();
 	m_pPanelAttributes->Create(IDD_PANEL_ATTRIBUTES, this);
 	
+
+	// statusbar
+	m_pMyStatusbar = new CMyStatusbar();
+	m_pMyStatusbar->Create(IDD_STATUSBAR, this);
+	m_pMyStatusbar->ShowWindow(SW_SHOW);
+
+
 
 	// 调整初始窗口位置
 	CRect rcWnd;
@@ -491,6 +534,18 @@
 	CDialogEx::OnDestroy();
 
 
+	if (m_pTopToolbar != nullptr) {
+		m_pTopToolbar->DestroyWindow();
+		delete m_pTopToolbar;
+		m_pTopToolbar = nullptr;
+	}
+
+	if (m_pMyStatusbar != nullptr) {
+		m_pMyStatusbar->DestroyWindow();
+		delete m_pMyStatusbar;
+		m_pMyStatusbar = nullptr;
+	}
+
 	if (m_pTerminalDisplayDlg != nullptr) {
 		m_pTerminalDisplayDlg->DestroyWindow();
 		delete m_pTerminalDisplayDlg;
@@ -570,31 +625,40 @@
 	Invalidate();
 }
 
+#define TOOLBAR_HEIGHT		78
+#define STATUSBAR_HEIGHT	38
 void CServoDlg::Resize()
 {
 	CRect rcClient, rcItem;
 	CWnd* pItem = nullptr;
-	int x, y;
+	int x, y, y2;
 	GetClientRect(&rcClient);
 
 	x = 0;
 	y = 0;
+	y2 = rcClient.bottom - STATUSBAR_HEIGHT;
+	m_pTopToolbar->MoveWindow(0, 0, rcClient.Width(), TOOLBAR_HEIGHT);
+	y += TOOLBAR_HEIGHT;
+
+
+	
+
 	int nPanelWidth = 0;
 	if (m_pPanelMaster != nullptr) {
 		nPanelWidth = m_pPanelMaster->getPanelWidth();
-		m_pPanelMaster->MoveWindow(x, y, nPanelWidth, rcClient.Height());
+		m_pPanelMaster->MoveWindow(x, y, nPanelWidth, y2 - y);
 		x += nPanelWidth;
 	}
 
 	if (m_pPanelEquipment != nullptr && m_pPanelEquipment->IsWindowVisible()) {
 		nPanelWidth = m_pPanelEquipment->getPanelWidth();
-		m_pPanelEquipment->MoveWindow(x, y, nPanelWidth, rcClient.Height());
+		m_pPanelEquipment->MoveWindow(x, y, nPanelWidth, y2 - y);
 		x += nPanelWidth;
 	}
 
 	if (m_pPanelAttributes != nullptr && m_pPanelAttributes->IsWindowVisible()) {
 		nPanelWidth = m_pPanelAttributes->getPanelWidth();
-		m_pPanelAttributes->MoveWindow(x, y, nPanelWidth, rcClient.Height());
+		m_pPanelAttributes->MoveWindow(x, y, nPanelWidth, y2 - y);
 		x += nPanelWidth;
 	}
 
@@ -605,11 +669,14 @@
 	y += rcItem.Height();
 
 
-	m_pPageGraph1->MoveWindow(x, y, rcClient.Width() - x, rcClient.Height() - y);
-	m_pPageGraph2->MoveWindow(x, y, rcClient.Width() - x, rcClient.Height() - y);
-	m_pPageRecipe->MoveWindow(x, y, rcClient.Width() - x, rcClient.Height() - y);
-	m_pPageAlarm->MoveWindow(x, y, rcClient.Width() - x, rcClient.Height() - y);
-	m_pPageLog->MoveWindow(x, y, rcClient.Width() - x, rcClient.Height() - y);
+	m_pPageGraph1->MoveWindow(x, y, rcClient.Width() - x, y2 - y);
+	m_pPageGraph2->MoveWindow(x, y, rcClient.Width() - x, y2 - y);
+	m_pPageRecipe->MoveWindow(x, y, rcClient.Width() - x, y2 - y);
+	m_pPageAlarm->MoveWindow(x, y, rcClient.Width() - x, y2 - y);
+	m_pPageLog->MoveWindow(x, y, rcClient.Width() - x, y2 - y);
+
+
+	m_pMyStatusbar->MoveWindow(0, y2, rcClient.Width(), STATUSBAR_HEIGHT);
 }
 
 void CServoDlg::OnClose()
@@ -648,6 +715,17 @@
 		m_pTerminalDisplayDlg->Create(IDD_DIALOG_TERMINAL_DISPLAY, this);
 	}
 
+	if (TIMER_ID_UPDATE_RUMTIME == nIDEvent) {
+		static int index = 0; index++;
+		if (index >= 4) index = 0;
+		static char* status[] = {"|", "/", "--", "\\"};
+
+		CString strText;
+		GetRuntimeFormatText(strText, status[index]);
+		m_pMyStatusbar->setRunTimeText((LPTSTR)(LPCTSTR)strText);
+	}
+
+
 	CDialogEx::OnTimer(nIDEvent);
 }
 
@@ -675,4 +753,45 @@
 	for (int i = 0; i < 5; i++) {
 		pPages[i]->ShowWindow(i == index ? SW_SHOW : SW_HIDE);
 	}
+}
+
+LRESULT CServoDlg::OnToolbarBtnClicked(WPARAM wParam, LPARAM lParam)
+{
+	int id = (int)lParam;
+	if (id == IDC_BUTTON_RUN) {
+		theApp.m_model.getMaster().start();
+		m_pTopToolbar->GetBtn(IDC_BUTTON_RUN)->EnableWindow(FALSE);
+		m_pTopToolbar->GetBtn(IDC_BUTTON_STOP)->EnableWindow(TRUE);
+	}
+	else if (id == IDC_BUTTON_STOP) {
+		theApp.m_model.getMaster().stop();
+		m_pTopToolbar->GetBtn(IDC_BUTTON_RUN)->EnableWindow(TRUE);
+		m_pTopToolbar->GetBtn(IDC_BUTTON_STOP)->EnableWindow(FALSE);
+	}
+	else if (id == IDC_BUTTON_ROBOT) {
+		SERVO::CEFEM* pEFEM = (SERVO::CEFEM*)theApp.m_model.getMaster().getEquipment(EQ_ID_EFEM);
+		CRobotCmdTestDlg dlg;
+		dlg.SetEFEM(pEFEM);
+		dlg.DoModal();
+	}
+	return 0;
+}
+
+CString& CServoDlg::GetRuntimeFormatText(CString& strText, const char* pszSuffix)
+{
+	ULONGLONG ullRunTime = (ULONGLONG)(theApp.m_model.getMaster().getRunTime() * 0.001);
+	int h, m, s;
+	h = int(ullRunTime / 3600);
+	m = int((ullRunTime % 3600) / 60);
+	s = int(ullRunTime % 60);
+
+	SERVO::MASTERSTATE state = theApp.m_model.getMaster().getState();
+	if (state == SERVO::MASTERSTATE::RUNNING) {
+		strText.Format(_T("正在运行:%02d:%02d:%02d   %s"), h, m, s, pszSuffix);
+	}
+	else {
+		strText.Format(_T("已运行:%02d:%02d:%02d   %s"), h, m, s, pszSuffix);
+	}
+
+	return strText;
 }
\ No newline at end of file
diff --git a/SourceCode/Bond/Servo/ServoDlg.h b/SourceCode/Bond/Servo/ServoDlg.h
index f78d8c5..a281b1c 100644
--- a/SourceCode/Bond/Servo/ServoDlg.h
+++ b/SourceCode/Bond/Servo/ServoDlg.h
@@ -13,6 +13,8 @@
 #include "CPanelAttributes.h"
 #include "CPageGraph1.h"
 #include "CPageGraph2.h"
+#include "TopToolbar.h"
+#include "CMyStatusbar.h"
 
 
 // CServoDlg 对话框
@@ -30,7 +32,7 @@
 	void InitRxWindows();
 	void Resize();
 	void ShowChildPage(int index);
-
+	CString& GetRuntimeFormatText(CString& strText, const char* pszSuffix);
 
 private:
 	IObserver* m_pObserver;
@@ -56,9 +58,11 @@
 	HICON m_hIcon;
 	COLORREF m_crBkgnd;
 	HBRUSH m_hbrBkgnd;
+	CTopToolbar* m_pTopToolbar;
 	CPanelMaster* m_pPanelMaster;
 	CPanelEquipment* m_pPanelEquipment;
 	CPanelAttributes* m_pPanelAttributes;
+	CMyStatusbar* m_pMyStatusbar;
 
 	// 生成的消息映射函数
 	virtual BOOL OnInitDialog();
@@ -90,4 +94,5 @@
 	afx_msg void OnTimer(UINT_PTR nIDEvent);
 	afx_msg LRESULT OnPanelResize(WPARAM wParam, LPARAM lParam);
 	afx_msg void OnTabSelChanged(NMHDR* nmhdr, LRESULT* result);
+	LRESULT OnToolbarBtnClicked(WPARAM wParam, LPARAM lParam);
 };
diff --git a/SourceCode/Bond/Servo/ToolUnits.cpp b/SourceCode/Bond/Servo/ToolUnits.cpp
index f3a88bc..2964355 100644
--- a/SourceCode/Bond/Servo/ToolUnits.cpp
+++ b/SourceCode/Bond/Servo/ToolUnits.cpp
@@ -75,9 +75,8 @@
 ULONGLONG CToolUnits::getTimestamp()
 {
 	auto now = std::chrono::system_clock::now();
-	auto duration_in_milliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch());
-	uint64_t timestamp = duration_in_milliseconds.count();
-	return timestamp;
+	auto ms = std::chrono::time_point_cast<std::chrono::milliseconds>(now);
+	return static_cast<ULONGLONG>(ms.time_since_epoch().count());
 }
 
 void CToolUnits::createDir(const char* pszDir)
diff --git a/SourceCode/Bond/Servo/TopToolbar.cpp b/SourceCode/Bond/Servo/TopToolbar.cpp
new file mode 100644
index 0000000..32c9d8a
--- /dev/null
+++ b/SourceCode/Bond/Servo/TopToolbar.cpp
@@ -0,0 +1,218 @@
+// TopToolbar.cpp : 实现文件
+//
+
+#include "stdafx.h"
+#include "Servo.h"
+#include "TopToolbar.h"
+#include "afxdialogex.h"
+#include "Common.h"
+
+
+// CTopToolbar 对话框
+
+IMPLEMENT_DYNAMIC(CTopToolbar, CDialogEx)
+
+CTopToolbar::CTopToolbar(CWnd* pParent /*=NULL*/)
+	: CDialogEx(IDD_TOP_TOOLBAR, pParent)
+{
+	m_crBkgnd = TOP_TOOLBAR_BACKGROUND;
+	m_hbrBkgnd = nullptr;
+}
+
+CTopToolbar::~CTopToolbar()
+{
+}
+
+void CTopToolbar::DoDataExchange(CDataExchange* pDX)
+{
+	CDialogEx::DoDataExchange(pDX);
+	DDX_Control(pDX, IDC_BUTTON_RUN, m_btnRun);
+	DDX_Control(pDX, IDC_BUTTON_STOP, m_btnStop);
+	DDX_Control(pDX, IDC_BUTTON_ALARM, m_btnAlarm);
+	DDX_Control(pDX, IDC_BUTTON_SETTINGS, m_btnSettings);
+	DDX_Control(pDX, IDC_BUTTON_ROBOT, m_btnRobot);
+	DDX_Control(pDX, IDC_BUTTON_OPERATOR, m_btnOperator);
+}
+
+
+BEGIN_MESSAGE_MAP(CTopToolbar, CDialogEx)
+	ON_WM_CTLCOLOR()
+	ON_WM_DESTROY()
+	ON_WM_SIZE()
+	ON_NOTIFY(BLBUTTON_MENU_ITEM_CLICKED, IDC_BUTTON_OPERATOR, &CTopToolbar::OnButtonOperatorMenuClicked)
+END_MESSAGE_MAP()
+
+
+// CTopToolbar 消息处理程序
+
+
+BOOL CTopToolbar::OnInitDialog()
+{
+	CDialogEx::OnInitDialog();
+
+	InitBtn(m_btnRun, "Run_High_32.ico", "Run_Gray_32.ico");
+	InitBtn(m_btnStop, "Stop_High_32.ico", "Stop_Gray_32.ico");
+	InitBtn(m_btnAlarm, "Alarm_o_32.ico", "Alarm_gray_32.ico");
+	InitBtn(m_btnSettings, "Settings_High_32.ico", "Settings_Gray_32.ico");
+	InitBtn(m_btnRobot, "Robot_High_32.ico", "Robot_Gray_32.ico");
+	InitBtn(m_btnOperator, "Operator_High_32.ico", "Operator_Gray_32.ico");
+	HMENU hMenu = LoadMenu(AfxGetInstanceHandle(), MAKEINTRESOURCEA(IDR_MENU_OPEATOR));
+	m_btnOperator.SetMenu(hMenu);
+
+
+	return TRUE;  // return TRUE unless you set the focus to a control
+				  // 异常: OCX 属性页应返回 FALSE
+}
+
+
+HBRUSH CTopToolbar::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
+{
+	HBRUSH hbr = CDialogEx::OnCtlColor(pDC, pWnd, nCtlColor);
+
+	if (nCtlColor == CTLCOLOR_STATIC) {
+		pDC->SetBkColor(m_crBkgnd);
+	}
+
+	if (m_hbrBkgnd == nullptr) {
+		m_hbrBkgnd = CreateSolidBrush(m_crBkgnd);
+	}
+
+	return m_hbrBkgnd;
+}
+
+
+void CTopToolbar::OnDestroy()
+{
+	CDialogEx::OnDestroy();
+
+	if (m_hbrBkgnd != nullptr) {
+		::DeleteObject(m_hbrBkgnd);
+		m_hbrBkgnd = nullptr;
+	}
+}
+
+
+void CTopToolbar::OnSize(UINT nType, int cx, int cy)
+{
+	CDialogEx::OnSize(nType, cx, cy);
+	if (GetDlgItem(IDC_BUTTON_RUN) == nullptr) return;
+	Resize();
+}
+
+#define BTN_WIDTH		60
+#define BTN_HEIGHT		30
+void CTopToolbar::Resize()
+{
+	CWnd* pItem;
+	CRect rcClient, rcItem;
+	GetClientRect(&rcClient);
+	int nBthHeight = (rcClient.Height() - 10);
+	int x = 2, y = 3;
+
+	pItem = GetDlgItem(IDC_BUTTON_RUN);
+	pItem->MoveWindow(x, y, BTN_WIDTH, nBthHeight);
+	x += BTN_WIDTH;
+	x += 2;
+
+	pItem = GetDlgItem(IDC_BUTTON_STOP);
+	pItem->MoveWindow(x, y, BTN_WIDTH, nBthHeight);
+	x += BTN_WIDTH;
+	x += 2;
+
+	pItem = GetDlgItem(IDC_BUTTON_ALARM);
+	pItem->MoveWindow(x, y, BTN_WIDTH, nBthHeight);
+	x += BTN_WIDTH;
+	x += 2;
+
+	pItem = GetDlgItem(IDC_TOOLBAR_LINE1);
+	pItem->MoveWindow(x, y + 6, 2, nBthHeight - 12);
+	x += 4;
+
+	pItem = GetDlgItem(IDC_BUTTON_SETTINGS);
+	pItem->MoveWindow(x, y, BTN_WIDTH, nBthHeight);
+	x += BTN_WIDTH;
+	x += 2;
+
+	pItem = GetDlgItem(IDC_BUTTON_ROBOT);
+	pItem->MoveWindow(x, y, BTN_WIDTH, nBthHeight);
+	x += BTN_WIDTH;
+	x += 2;
+
+	x = rcClient.right - 5 - BTN_WIDTH - 20;
+	pItem = GetDlgItem(IDC_BUTTON_OPERATOR);
+	pItem->MoveWindow(x, y, BTN_WIDTH + 20, nBthHeight);
+
+
+	CWnd* pLine = GetDlgItem(IDC_LINE1);
+	pLine->MoveWindow(0, rcClient.bottom - 2, rcClient.Width(), 2);
+}
+
+void CTopToolbar::InitBtn(CBlButton& btn, const char* pszIcon1, const char* pszIcon2)
+{
+	CString strIcon1, strIcon2;
+	HICON hIcon1, hIcon2;
+	strIcon1.Format(_T("%s\\Res\\%s"), theApp.m_strAppDir, pszIcon1);
+	strIcon2.Format(_T("%s\\Res\\%s"), theApp.m_strAppDir, pszIcon2);
+	hIcon1 = (HICON)::LoadImage(AfxGetInstanceHandle(),
+		strIcon1, IMAGE_ICON, 32, 32,
+		LR_LOADFROMFILE | LR_DEFAULTCOLOR | LR_CREATEDIBSECTION | LR_DEFAULTSIZE);
+	hIcon2 = (HICON)::LoadImage(AfxGetInstanceHandle(),
+		strIcon2, IMAGE_ICON, 32, 32,
+		LR_LOADFROMFILE | LR_DEFAULTCOLOR | LR_CREATEDIBSECTION | LR_DEFAULTSIZE);
+	btn.SetBkgndColor(BS_NORMAL, TOP_TOOLBAR_BACKGROUND);
+	btn.SetBkgndColor(BS_PRESS, RGB(185, 209, 234));
+	btn.SetBkgndColor(BS_DISABLE, TOP_TOOLBAR_BACKGROUND);
+	btn.SetFrameColor(BS_NORMAL, TOP_TOOLBAR_BACKGROUND);
+	btn.SetFrameColor(BS_PRESS, RGB(185, 209, 234));
+	btn.SetFrameColor(BS_HOVER, RGB(185, 209, 234));
+	btn.SetFrameColor(BS_DISABLE, TOP_TOOLBAR_BACKGROUND);
+	btn.SetIcon(hIcon1, hIcon2, 32);
+}
+
+CWnd* CTopToolbar::GetBtn(UINT nId)
+{
+	return GetDlgItem(nId);
+}
+
+void CTopToolbar::SetOperatorBtnText(const char* pszText)
+{
+	m_btnOperator.SetWindowText(pszText);
+}
+
+BOOL CTopToolbar::OnCommand(WPARAM wParam, LPARAM lParam)
+{
+	switch (LOWORD(wParam)) {
+	case IDC_BUTTON_RUN:
+	case IDC_BUTTON_STOP:
+	case IDC_BUTTON_ALARM:
+	case IDC_BUTTON_SETTINGS:
+	case IDC_BUTTON_ROBOT:
+		GetParent()->SendMessage(ID_MSG_TOOLBAR_BTN_CLICKED, 0, LOWORD(wParam));
+		break;
+	}
+
+	return CDialogEx::OnCommand(wParam, lParam);
+}
+
+void CTopToolbar::OnButtonOperatorMenuClicked(NMHDR* pNMHDR, LRESULT* pResult)
+{
+	BLBUTTON_NMHDR* pblbNmhdr = reinterpret_cast<BLBUTTON_NMHDR*>(pNMHDR);
+	GetParent()->SendMessage(ID_MSG_TOOLBAR_BTN_CLICKED, (int)pblbNmhdr->dwData, IDC_BUTTON_OPERATOR);
+
+
+	*pResult = 0;
+}
+
+HMENU CTopToolbar::GetOperatorMenu()
+{
+	return m_btnOperator.GetMenu();
+}
+
+BOOL CTopToolbar::PreTranslateMessage(MSG* pMsg)
+{
+	if (pMsg->wParam == VK_RETURN || pMsg->wParam == VK_ESCAPE) {
+		return TRUE;
+	}
+
+	return CDialogEx::PreTranslateMessage(pMsg);
+}
diff --git a/SourceCode/Bond/Servo/TopToolbar.h b/SourceCode/Bond/Servo/TopToolbar.h
new file mode 100644
index 0000000..b65ad85
--- /dev/null
+++ b/SourceCode/Bond/Servo/TopToolbar.h
@@ -0,0 +1,58 @@
+#pragma once
+#include "BlButton.h"
+
+
+#define ID_MSG_TOOLBAR_BTN_CLICKED		WM_USER + 20368
+
+// CTopToolbar 对话框
+
+class CTopToolbar : public CDialogEx
+{
+	DECLARE_DYNAMIC(CTopToolbar)
+
+public:
+	CTopToolbar(CWnd* pParent = NULL);   // 标准构造函数
+	virtual ~CTopToolbar();
+
+
+public:
+	CWnd* GetBtn(UINT nId);
+	void SetOperatorBtnText(const char* pszText);
+	HMENU GetOperatorMenu();
+
+private:
+	void Resize();
+	void InitBtn(CBlButton& btn, const char* pszIcon1, const char* pszIcon2);
+
+private:
+	COLORREF m_crBkgnd;
+	HBRUSH m_hbrBkgnd;
+
+
+private:
+	CBlButton m_btnRun;
+	CBlButton m_btnStop;
+	CBlButton m_btnAlarm;
+	CBlButton m_btnSettings;
+	CBlButton m_btnRobot;
+	CBlButton m_btnOperator;
+
+
+// 对话框数据
+#ifdef AFX_DESIGN_TIME
+	enum { IDD = IDD_TOP_TOOLBAR };
+#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);
+	virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam);
+	afx_msg void OnButtonOperatorMenuClicked(NMHDR* pNMHDR, LRESULT* pResult);
+	virtual BOOL PreTranslateMessage(MSG* pMsg);
+};
diff --git a/SourceCode/Bond/Servo/resource.h b/SourceCode/Bond/Servo/resource.h
index f530d52..59bd598 100644
--- a/SourceCode/Bond/Servo/resource.h
+++ b/SourceCode/Bond/Servo/resource.h
Binary files differ
diff --git a/SourceCode/Bond/x64/Debug/Master.dat b/SourceCode/Bond/x64/Debug/Master.dat
index 86656a2..697ea90 100644
--- a/SourceCode/Bond/x64/Debug/Master.dat
+++ b/SourceCode/Bond/x64/Debug/Master.dat
Binary files differ
diff --git a/SourceCode/Bond/x64/Debug/Res/robot_Gray_32.ico b/SourceCode/Bond/x64/Debug/Res/robot_Gray_32.ico
new file mode 100644
index 0000000..a65dbdc
--- /dev/null
+++ b/SourceCode/Bond/x64/Debug/Res/robot_Gray_32.ico
Binary files differ
diff --git a/SourceCode/Bond/x64/Debug/Res/robot_High_32.ico b/SourceCode/Bond/x64/Debug/Res/robot_High_32.ico
new file mode 100644
index 0000000..7c56fac
--- /dev/null
+++ b/SourceCode/Bond/x64/Debug/Res/robot_High_32.ico
Binary files differ

--
Gitblit v1.9.3