From 2d69213b1b41b5b039e5dc6f6b7c55d53fd03037 Mon Sep 17 00:00:00 2001
From: LAPTOP-SNT8I5JK\Boounion <Chenluhua@qq.com>
Date: 星期二, 13 五月 2025 09:34:04 +0800
Subject: [PATCH] Merge branch 'clh'

---
 SourceCode/Bond/Servo/CArmTray.h                                                  |   23 
 SourceCode/Bond/Servo/CEqPortChangeStep.cpp                                       |   15 
 SourceCode/Bond/Servo/CArm.cpp                                                    |   97 +
 SourceCode/Bond/Servo/CPageGraph2.h                                               |    2 
 SourceCode/Bond/Servo/CJobDataS.cpp                                               |  333 ++++++
 SourceCode/Bond/Servo/CEFEM.h                                                     |   12 
 SourceCode/Bond/Servo/CPanelAttributes.cpp                                        |    1 
 SourceCode/Bond/Servo/EqsGraphWnd.cpp                                             |   27 
 SourceCode/Bond/Servo/ProductionLogDlg.cpp                                        |  412 ++++++++
 SourceCode/Bond/Servo/CRecipesManager.cpp                                         |  115 ++
 SourceCode/Bond/Servo/CEqCimMessageCmdStep.cpp                                    |    3 
 SourceCode/Bond/Servo/Servo.rc                                                    |    0 
 SourceCode/Bond/Servo/CEqReadStep.cpp                                             |   11 
 SourceCode/Bond/Servo/ServoDlg.h                                                  |   26 
 SourceCode/Bond/Servo/CEqVcrEventStep.cpp                                         |   15 
 SourceCode/Bond/Servo/CWriteStep.cpp                                              |    5 
 SourceCode/Bond/Servo/CJobDataB.cpp                                               |   36 
 Document/2860MES交握表.xlsx                                                          |    0 
 SourceCode/Bond/Servo/CLoadPort.cpp                                               |   15 
 Document/ESWIN_EAS_Bonder_Inline_Mapping_Address_v1.1.5.xlsx                      |    0 
 SourceCode/Bond/Servo/CAttribute.cpp                                              |   10 
 SourceCode/Bond/Servo/CEqModeStep.cpp                                             |    5 
 SourceCode/Bond/Servo/Servo.vcxproj.filters                                       |   12 
 SourceCode/Bond/Servo/CJobDataA.cpp                                               |    2 
 Document/ESWIN_EAS_Bonder_Inline_Mapping_Address_v1.1.2.xlsx                      |    0 
 SourceCode/Bond/Servo/CJobDataB.h                                                 |    2 
 SourceCode/Bond/Servo/CEqStatusStep.cpp                                           |    9 
 SourceCode/Bond/Servo/CEFEM.cpp                                                   |  152 +++
 SourceCode/Bond/Servo/CEqDateTimeSetCmdStep.cpp                                   |    3 
 SourceCode/Bond/Servo/CEquipment.h                                                |   29 
 Document/ESWIN_EAS_Bonder_Inline_Mapping_Address_v1.1.5(5).xlsx                   |    0 
 SourceCode/Bond/Servo/Servo.vcxproj                                               |   17 
 SourceCode/Bond/Servo/Servo.vcxproj.user                                          |    4 
 SourceCode/Bond/Servo/CEqCassetteTransferStateStep.cpp                            |   17 
 SourceCode/Bond/Servo/CJobDataS.h                                                 |    8 
 SourceCode/Bond/Servo/CEqCassetteCtrlCmdStep.cpp                                  |    3 
 SourceCode/Bond/Servo/CGlass.h                                                    |    4 
 SourceCode/Bond/Servo/Servo.cpp                                                   |   24 
 SourceCode/Bond/Servo/PageLog.cpp                                                 |   54 
 SourceCode/Bond/Servo/ProductionLogDlg.h                                          |   68 +
 SourceCode/Bond/Servo/CMaster.h                                                   |   16 
 SourceCode/Bond/Servo/CEqModeChangeStep.cpp                                       |    3 
 SourceCode/Bond/Servo/PageAlarm.cpp                                               |   64 
 SourceCode/Bond/Servo/CStep.h                                                     |    8 
 SourceCode/Bond/Servo/CEqWriteStep.cpp                                            |    3 
 SourceCode/Bond/Servo/CEquipment.cpp                                              |  332 ++++++
 SourceCode/Bond/Servo/CEqJobEventStep.h                                           |    6 
 SourceCode/Bond/Servo/CEqCimMessageClearStep.cpp                                  |    3 
 SourceCode/Bond/Servo/CEqCurrentRecipeChangeStep.cpp                              |    7 
 SourceCode/Bond/Servo/CMaster.cpp                                                 |  114 +
 SourceCode/Bond/Servo/CEqCimModeChangeStep.cpp                                    |    3 
 SourceCode/Bond/Servo/CEqReadIntStep.cpp                                          |    5 
 SourceCode/Bond/Servo/CArm.h                                                      |   30 
 SourceCode/Bond/Servo/CStep.cpp                                                   |   34 
 SourceCode/Bond/Servo/CEqReadStep.h                                               |    2 
 SourceCode/Bond/Servo/CPageGraph2.cpp                                             |   54 +
 SourceCode/Bond/Servo/CReadStep.cpp                                               |    5 
 SourceCode/Bond/Servo/EqsGraphWnd.h                                               |    2 
 Document/ESWIN_EAS_Equipment_Communication_Specification(CC-LINK)_v3.1(翻译结果).docx |    0 
 SourceCode/Bond/Servo/PageLog.h                                                   |   10 
 SourceCode/Bond/Servo/CEqAlarmStep.cpp                                            |   15 
 SourceCode/Bond/Servo/Model.cpp                                                   |   15 
 SourceCode/Bond/Servo/ServoDlg.cpp                                                |  225 ----
 SourceCode/Bond/Servo/CEqProcessStep.cpp                                          |   15 
 SourceCode/Bond/Servo/CPageGraph1.cpp                                             |    8 
 SourceCode/Bond/Servo/CAttributeVector.h                                          |    4 
 SourceCode/Bond/Servo/CRecipesManager.h                                           |    2 
 SourceCode/Bond/Servo/PageAlarm.h                                                 |   10 
 Document/PortFlow.pdf                                                             |    0 
 /dev/null                                                                         |    0 
 SourceCode/Bond/Servo/CAttribute.h                                                |    4 
 SourceCode/Bond/Servo/CEqJobEventStep.cpp                                         |   29 
 SourceCode/Bond/Servo/CJobDataA.h                                                 |    2 
 SourceCode/Bond/Servo/CEqVCREnableStep.cpp                                        |    2 
 SourceCode/Bond/Servo/CArmTray.cpp                                                |   56 +
 SourceCode/Bond/Servo/CAttributeVector.cpp                                        |   31 
 SourceCode/Bond/Servo/CBonder.cpp                                                 |  159 ++
 SourceCode/Bond/Servo/Common.h                                                    |  124 ++
 78 files changed, 2,489 insertions(+), 484 deletions(-)

diff --git "a/Document/2860MES\344\272\244\346\217\241\350\241\250.xlsx" "b/Document/2860MES\344\272\244\346\217\241\350\241\250.xlsx"
new file mode 100644
index 0000000..a27567c
--- /dev/null
+++ "b/Document/2860MES\344\272\244\346\217\241\350\241\250.xlsx"
Binary files differ
diff --git a/Document/ESWIN_EAS_Bonder_Inline_Mapping_Address_v1.1.2.xlsx b/Document/ESWIN_EAS_Bonder_Inline_Mapping_Address_v1.1.2.xlsx
index fe5bd01..77c0949 100644
--- a/Document/ESWIN_EAS_Bonder_Inline_Mapping_Address_v1.1.2.xlsx
+++ b/Document/ESWIN_EAS_Bonder_Inline_Mapping_Address_v1.1.2.xlsx
Binary files differ
diff --git "a/Document/ESWIN_EAS_Bonder_Inline_Mapping_Address_v1.1.5\0505\051.xlsx" "b/Document/ESWIN_EAS_Bonder_Inline_Mapping_Address_v1.1.5\0505\051.xlsx"
index 35d3f51..0e5b4b9 100644
--- "a/Document/ESWIN_EAS_Bonder_Inline_Mapping_Address_v1.1.5\0505\051.xlsx"
+++ "b/Document/ESWIN_EAS_Bonder_Inline_Mapping_Address_v1.1.5\0505\051.xlsx"
Binary files differ
diff --git a/Document/ESWIN_EAS_Bonder_Inline_Mapping_Address_v1.1.5.xlsx b/Document/ESWIN_EAS_Bonder_Inline_Mapping_Address_v1.1.5.xlsx
index ca31dfe..e7d314b 100644
--- a/Document/ESWIN_EAS_Bonder_Inline_Mapping_Address_v1.1.5.xlsx
+++ b/Document/ESWIN_EAS_Bonder_Inline_Mapping_Address_v1.1.5.xlsx
Binary files differ
diff --git "a/Document/ESWIN_EAS_Equipment_Communication_Specification\050CC-LINK\051_v3.1\050\347\277\273\350\257\221\347\273\223\346\236\234\051.docx" "b/Document/ESWIN_EAS_Equipment_Communication_Specification\050CC-LINK\051_v3.1\050\347\277\273\350\257\221\347\273\223\346\236\234\051.docx"
index a920e8a..f9457c2 100644
--- "a/Document/ESWIN_EAS_Equipment_Communication_Specification\050CC-LINK\051_v3.1\050\347\277\273\350\257\221\347\273\223\346\236\234\051.docx"
+++ "b/Document/ESWIN_EAS_Equipment_Communication_Specification\050CC-LINK\051_v3.1\050\347\277\273\350\257\221\347\273\223\346\236\234\051.docx"
Binary files differ
diff --git a/Document/PortFlow.pdf b/Document/PortFlow.pdf
new file mode 100644
index 0000000..f80585c
--- /dev/null
+++ b/Document/PortFlow.pdf
Binary files differ
diff --git "a/Document/~$WIN_EAS_Equipment_Communication_Specification\050CC-LINK\051_v3.1\050\347\277\273\350\257\221\347\273\223\346\236\234\051.docx" "b/Document/~$WIN_EAS_Equipment_Communication_Specification\050CC-LINK\051_v3.1\050\347\277\273\350\257\221\347\273\223\346\236\234\051.docx"
deleted file mode 100644
index ac59be7..0000000
--- "a/Document/~$WIN_EAS_Equipment_Communication_Specification\050CC-LINK\051_v3.1\050\347\277\273\350\257\221\347\273\223\346\236\234\051.docx"
+++ /dev/null
Binary files differ
diff --git a/SourceCode/Bond/Servo/CArm.cpp b/SourceCode/Bond/Servo/CArm.cpp
new file mode 100644
index 0000000..e698692
--- /dev/null
+++ b/SourceCode/Bond/Servo/CArm.cpp
@@ -0,0 +1,97 @@
+#include "stdafx.h"
+#include "CArm.h"
+
+
+namespace SERVO {
+	CArm::CArm() : CEquipment()
+	{
+	}
+
+	CArm::~CArm()
+	{
+
+	}
+
+	const char* CArm::getClassName()
+	{
+		static char* pszName = "CArm";
+		return pszName;
+	}
+
+	void CArm::init()
+	{
+		CEquipment::init();
+	}
+
+	void CArm::term()
+	{
+		CEquipment::term();
+	}
+
+	// 必须要实现的虚函数,在此初始化Pin列表
+	void CArm::initPins()
+	{
+
+	}
+
+	void CArm::onTimer(UINT nTimerid)
+	{
+		CEquipment::onTimer(nTimerid);
+	}
+
+	void CArm::serialize(CArchive& ar)
+	{
+		CEquipment::serialize(ar);
+	}
+
+	void CArm::getAttributeVector(CAttributeVector& attrubutes)
+	{
+		__super::getAttributeVector(attrubutes);
+	}
+
+	int CArm::recvIntent(CPin* pPin, CIntent* pIntent)
+	{
+		return __super::recvIntent(pPin, pIntent);
+	}
+
+	int CArm::tempStore(CGlass* pGlass)
+	{
+		// 保证列表中只存储一个物料
+		Lock();
+		for (auto item : m_glassList) {
+			item->release();
+		}
+		m_glassList.clear();
+		addGlassToList(pGlass);
+		Unlock();
+
+		if (m_listener.onDataChanged != nullptr) {
+			m_listener.onDataChanged(this, 0);
+		}
+
+		return 0;
+	}
+
+	int CArm::tempFetchOut(OUT CGlass*& pGlass)
+	{
+		Lock();
+		if (m_glassList.empty()) {
+			Unlock();
+			return -1;
+		}
+
+		pGlass = m_glassList.front();
+		pGlass->addRef();
+		for (auto item : m_glassList) {
+			item->release();
+		}
+		m_glassList.clear();
+		Unlock();
+
+		if (m_listener.onDataChanged != nullptr) {
+			m_listener.onDataChanged(this, 0);
+		}
+
+		return 0;
+	}
+}
diff --git a/SourceCode/Bond/Servo/CArm.h b/SourceCode/Bond/Servo/CArm.h
new file mode 100644
index 0000000..4a12834
--- /dev/null
+++ b/SourceCode/Bond/Servo/CArm.h
@@ -0,0 +1,30 @@
+#pragma once
+#include "CEquipment.h"
+
+
+namespace SERVO {
+	class CArm : public CEquipment
+	{
+    public:
+        CArm();
+        virtual ~CArm();
+
+    public:
+        virtual const char* getClassName();
+        virtual BOOL isArm() { return TRUE; };
+        virtual void init();
+        virtual void term();
+        virtual void initPins();
+        virtual void onTimer(UINT nTimerid);
+        virtual void serialize(CArchive& ar);
+        virtual void getAttributeVector(CAttributeVector& attrubutes);
+        virtual int recvIntent(CPin* pPin, CIntent* pIntent);
+
+    public:
+        int tempStore(CGlass* pGlass);
+
+        // 调用tempFetchOut后,pGlass必须release一次
+        int tempFetchOut(OUT CGlass*& pGlass);
+	};
+}
+
diff --git a/SourceCode/Bond/Servo/CArmTray.cpp b/SourceCode/Bond/Servo/CArmTray.cpp
new file mode 100644
index 0000000..ddb8b30
--- /dev/null
+++ b/SourceCode/Bond/Servo/CArmTray.cpp
@@ -0,0 +1,56 @@
+#include "stdafx.h"
+#include "CArmTray.h"
+
+
+namespace SERVO {
+	CArmTray::CArmTray() : CEquipment()
+	{
+	}
+
+	CArmTray::~CArmTray()
+	{
+
+	}
+
+	const char* CArmTray::getClassName()
+	{
+		static char* pszName = "CArmTray";
+		return pszName;
+	}
+
+	void CArmTray::init()
+	{
+		CEquipment::init();
+	}
+
+	void CArmTray::term()
+	{
+		CEquipment::term();
+	}
+
+	// 必须要实现的虚函数,在此初始化Pin列表
+	void CArmTray::initPins()
+	{
+
+	}
+
+	void CArmTray::onTimer(UINT nTimerid)
+	{
+		CEquipment::onTimer(nTimerid);
+	}
+
+	void CArmTray::serialize(CArchive& ar)
+	{
+		CEquipment::serialize(ar);
+	}
+
+	void CArmTray::getAttributeVector(CAttributeVector& attrubutes)
+	{
+		__super::getAttributeVector(attrubutes);
+	}
+
+	int CArmTray::recvIntent(CPin* pPin, CIntent* pIntent)
+	{
+		return __super::recvIntent(pPin, pIntent);
+	}
+}
diff --git a/SourceCode/Bond/Servo/CArmTray.h b/SourceCode/Bond/Servo/CArmTray.h
new file mode 100644
index 0000000..8a08cf0
--- /dev/null
+++ b/SourceCode/Bond/Servo/CArmTray.h
@@ -0,0 +1,23 @@
+#pragma once
+#include "CEquipment.h"
+
+
+namespace SERVO {
+	class CArmTray : public CEquipment
+	{
+    public:
+        CArmTray();
+        virtual ~CArmTray();
+
+    public:
+        virtual const char* getClassName();
+        virtual void init();
+        virtual void term();
+        virtual void initPins();
+        virtual void onTimer(UINT nTimerid);
+        virtual void serialize(CArchive& ar);
+        virtual void getAttributeVector(CAttributeVector& attrubutes);
+        virtual int recvIntent(CPin* pPin, CIntent* pIntent);
+	};
+}
+
diff --git a/SourceCode/Bond/Servo/CAttribute.cpp b/SourceCode/Bond/Servo/CAttribute.cpp
index 468ebf2..e9c902d 100644
--- a/SourceCode/Bond/Servo/CAttribute.cpp
+++ b/SourceCode/Bond/Servo/CAttribute.cpp
@@ -4,14 +4,15 @@
 namespace SERVO {
 	CAttribute::CAttribute()
 	{
-
+		m_nWeight = 0;
 	}
 
-	CAttribute::CAttribute(const char* pszName, const char* pszValue, const char* pszDescription)
+	CAttribute::CAttribute(const char* pszName, const char* pszValue, const char* pszDescription, unsigned int weight)
 	{
 		m_strName = pszName;
 		m_strValue = pszValue;
 		m_strDescription = pszDescription;
+		m_nWeight = weight;
 	}
 
 	CAttribute::~CAttribute()
@@ -33,4 +34,9 @@
 	{
 		return m_strDescription;
 	}
+
+	unsigned int CAttribute::getWeight()
+	{
+		return m_nWeight;
+	}
 }
diff --git a/SourceCode/Bond/Servo/CAttribute.h b/SourceCode/Bond/Servo/CAttribute.h
index 5c96b72..ee5098b 100644
--- a/SourceCode/Bond/Servo/CAttribute.h
+++ b/SourceCode/Bond/Servo/CAttribute.h
@@ -6,18 +6,20 @@
 	{
 	public:
 		CAttribute();
-		CAttribute(const char* pszName, const char* pszValue, const char* pszDescription);
+		CAttribute(const char* pszName, const char* pszValue, const char* pszDescription, unsigned int weight);
 		~CAttribute();
 
 	public:
 		std::string& getName();
 		std::string& getValue();
 		std::string& getDescription();
+		unsigned int getWeight();
 
 	private:
 		std::string m_strName;
 		std::string m_strValue;
 		std::string m_strDescription;
+		unsigned int m_nWeight;				// 权重,用于排序
 	};
 }
 
diff --git a/SourceCode/Bond/Servo/CAttributeVector.cpp b/SourceCode/Bond/Servo/CAttributeVector.cpp
index 6d9213a..733c629 100644
--- a/SourceCode/Bond/Servo/CAttributeVector.cpp
+++ b/SourceCode/Bond/Servo/CAttributeVector.cpp
@@ -1,5 +1,6 @@
 #include "stdafx.h"
 #include "CAttributeVector.h"
+#include <algorithm>
 
 
 namespace SERVO {
@@ -16,14 +17,33 @@
 		m_attributes.clear();
 	}
 
-	void CAttributeVector::addAttribute(CAttribute* pAttribute)
+	void CAttributeVector::addAttribute(CAttribute* pAttribute, BOOL bReplace/* = FALSE*/)
 	{
+		if (bReplace) {
+			for (auto it = m_attributes.begin(); it != m_attributes.end(); ) {
+				if ((*it)->getName().compare(pAttribute->getName()) == 0) {
+					delete (*it);
+					it = m_attributes.erase(it);
+				}
+				else {
+					++it;
+				}
+			}
+		}
+
 		m_attributes.push_back(pAttribute);
+	}
+
+	void CAttributeVector::addAttributeVector(CAttributeVector& av)
+	{
+		for (auto item : av.m_attributes) {
+			m_attributes.push_back(item);
+		}
 	}
 
 	unsigned int CAttributeVector::size()
 	{
-		return m_attributes.size();
+		return (unsigned int)m_attributes.size();
 	}
 
 	void CAttributeVector::clear()
@@ -34,6 +54,13 @@
 		m_attributes.clear();
 	}
 
+	void CAttributeVector::sortWithWeight()
+	{
+		std::sort(m_attributes.begin(), m_attributes.end(), [](CAttribute* pAttribute1, CAttribute* pAttribut2) {
+			return pAttribute1->getWeight() < pAttribut2->getWeight();
+		});
+	}
+
 	bool CAttributeVector::empty()
 	{
 		return m_attributes.empty();
diff --git a/SourceCode/Bond/Servo/CAttributeVector.h b/SourceCode/Bond/Servo/CAttributeVector.h
index c3b9b34..fdbb30a 100644
--- a/SourceCode/Bond/Servo/CAttributeVector.h
+++ b/SourceCode/Bond/Servo/CAttributeVector.h
@@ -11,8 +11,10 @@
 		~CAttributeVector();
 
 	public:
-		void addAttribute(CAttribute* pAttribute);
+		void addAttribute(CAttribute* pAttribute, BOOL bReplace = FALSE);
+		void addAttributeVector(CAttributeVector& av);
 		void clear();
+		void sortWithWeight();
 		unsigned int size();
 		bool empty();
 		CAttribute* getAttribute(unsigned int index);
diff --git a/SourceCode/Bond/Servo/CBonder.cpp b/SourceCode/Bond/Servo/CBonder.cpp
index 5ce0745..9d18867 100644
--- a/SourceCode/Bond/Servo/CBonder.cpp
+++ b/SourceCode/Bond/Servo/CBonder.cpp
@@ -47,7 +47,7 @@
 			// eq mode
 			CEqModeStep* pStep = new CEqModeStep();
 			pStep->setName(STEP_MODE);
-			pStep->setWriteSignalDev(m_nIndex == 0 ? 0x350 : 0x650);
+			pStep->setWriteSignalDev(m_nIndex == 0 ? 0x340 : 0x640);
 			pStep->setModeDev(m_nIndex == 0 ? 0x9d7d : 0xdd7d);
 			if (addStep(STEP_ID_EQMODE_CHANGED, pStep) != 0) {
 				delete pStep;
@@ -58,7 +58,7 @@
 			// eq status
 			CEqStatusStep* pStep = new CEqStatusStep();
 			pStep->setName(STEP_STATUS);
-			pStep->setWriteSignalDev(m_nIndex == 0 ? 0x351 : 0x651);
+			pStep->setWriteSignalDev(m_nIndex == 0 ? 0x341 : 0x641);
 			pStep->setStatusDev(m_nIndex == 0 ? 0x9d59 : 0xdd59);
 			if (addStep(STEP_ID_EQSTATUS_CHANGED, pStep) != 0) {
 				delete pStep;
@@ -70,8 +70,8 @@
 			static char* pszName[] = { STEP_ALARM_BLOCK1, STEP_ALARM_BLOCK2, STEP_ALARM_BLOCK3, STEP_ALARM_BLOCK4, STEP_ALARM_BLOCK5 };
 			static int dev[2][5] = { { 0x9f0e , 0x9f3b, 0x9f68, 0x9f95, 0x9fc2 },
 				{ 0xdf0e , 0xdf3b, 0xdf68, 0xdf95, 0xdfc2 } };
-			static int writeSignalDev[2][5] = { { 0x352, 0x353, 0x354, 0x355, 0x356 },
-				{ 0x652, 0x653, 0x654, 0x655, 0x656 } };
+			static int writeSignalDev[2][5] = { { 0x342, 0x343, 0x344, 0x345, 0x346 },
+				{ 0x642, 0x643, 0x644, 0x645, 0x646 } };
 			static int addr[] = { STEP_ID_EQALARM1, STEP_ID_EQALARM2, STEP_ID_EQALARM3, STEP_ID_EQALARM4, STEP_ID_EQALARM5 };
 
 			for (int i = 0; i < 5; i++) {
@@ -90,7 +90,7 @@
 			// eq process
 			CEqProcessStep* pStep = new CEqProcessStep();
 			pStep->setName(STEP_PROCESS);
-			pStep->setWriteSignalDev(m_nIndex == 0 ? 0x357 : 0x657);
+			pStep->setWriteSignalDev(m_nIndex == 0 ? 0x347 : 0x647);
 			pStep->setProcessDev(m_nIndex == 0 ? 0xab55 : 0xeb55);
 			if (addStep(STEP_ID_PROCESS_DATA_REPORT, pStep) != 0) {
 				delete pStep;
@@ -101,7 +101,7 @@
 			// eq cim mode change
 			CEqCimModeChangeStep* pStep = new CEqCimModeChangeStep();
 			pStep->setName(STEP_CIM_MODE_CHANGE);
-			pStep->setWriteSignalDev(m_nIndex == 0 ? 0x370 : 0x670);
+			pStep->setWriteSignalDev(m_nIndex == 0 ? 0x360 : 0x660);
 			pStep->setCimModeDev(m_nIndex == 0 ? 0x965 : 0x12b5);
 			if (addStep(STEP_ID_CIMMODE_CHANGED_CMD_REPLY, pStep) != 0) {
 				delete pStep;
@@ -112,7 +112,7 @@
 			// eq cim message cmd
 			CEqCimMessageCmdStep* pStep = new CEqCimMessageCmdStep();
 			pStep->setName(STEP_CIM_MESSAGE_CMD);
-			pStep->setWriteSignalDev(m_nIndex == 0 ? 0x371 : 0x671);
+			pStep->setWriteSignalDev(m_nIndex == 0 ? 0x361 : 0x661);
 			pStep->setCimMessageDev(m_nIndex == 0 ? 0x950 : 0x12a0);
 			if (addStep(STEP_ID_CIM_MSG_SET_CMD_REPLY, pStep) != 0) {
 				delete pStep;
@@ -132,9 +132,11 @@
 
 		{
 			// CIM Message Confirm
+			// 要将int32的值拆分为两个short, 分别为msg id和panel id
+			// 65538, 2为msg id, 1为panel id
 			CEqReadIntStep* pStep = new CEqReadIntStep(__INT32, m_nIndex == 0 ? 0x9d80 : 0xdd80);
 			pStep->setName(STEP_EQ_CIM_MESSAGE_CONFIRM);
-			pStep->setWriteSignalDev(m_nIndex == 0 ? 0x359 : 0x659);
+			pStep->setWriteSignalDev(m_nIndex == 0 ? 0x349 : 0x649);
 			if (addStep(STEP_ID_CIM_MSG_CONFIRM_REPORT, pStep) != 0) {
 				delete pStep;
 			}
@@ -143,7 +145,7 @@
 		{
 			CEqCimMessageClearStep* pStep = new CEqCimMessageClearStep();
 			pStep->setName(STEP_CIM_MESSAGE_CLEAR);
-			pStep->setWriteSignalDev(m_nIndex == 0 ? 0x372 : 0x672);
+			pStep->setWriteSignalDev(m_nIndex == 0 ? 0x362 : 0x662);
 			pStep->setClearCimMessageDev(m_nIndex == 0 ? 0x963 : 0x12b3);
 			if (addStep(STEP_ID_CIM_MSG_CLEAR_CMD_REPLY, pStep) != 0) {
 				delete pStep;
@@ -154,7 +156,7 @@
 		{
 			CEqDateTimeSetCmdStep* pStep = new CEqDateTimeSetCmdStep();
 			pStep->setName(STEP_DATETIME_SET_CMD);
-			pStep->setWriteSignalDev(m_nIndex == 0 ? 0x373 : 0x673);
+			pStep->setWriteSignalDev(m_nIndex == 0 ? 0x363 : 0x663);
 			pStep->setDateTimeDev(m_nIndex == 0 ? 0x966 : 0x12b6);
 			if (addStep(STEP_ID_DATETIME_SET_CMD_REPLY, pStep) != 0) {
 				delete pStep;
@@ -164,7 +166,7 @@
 		{
 			CEqModeChangeStep* pStep = new CEqModeChangeStep();
 			pStep->setName(STEP_EQ_MODE_CHANGE);
-			pStep->setWriteSignalDev(m_nIndex == 0 ? 0x375 : 0x675);
+			pStep->setWriteSignalDev(m_nIndex == 0 ? 0x365 : 0x665);
 			pStep->setEqModeDev(m_nIndex == 0 ? 0x96E : 0x12be);
 			if (addStep(STEP_ID_EQMODE_CHANGE_CMD_REPLY, pStep) != 0) {
 				delete pStep;
@@ -185,7 +187,7 @@
 		{
 			// master recipe list report
 			CEqReadStep* pStep = new CEqReadStep(m_nIndex == 0 ? 0xa955 : 0xe955, 255 * 2,
-				[&](int code, const char* pszData, size_t size) -> int {
+				[&](void* pFrom, int code, const char* pszData, size_t size) -> int {
 					if (code == ROK && pszData != nullptr && size > 0) {
 						// 此处解释配方数据
 						short ret = decodeRecipeListReport(pszData, size);
@@ -202,6 +204,86 @@
 			}
 		}
 
+		{
+			// 请求配方参数
+			CEqWriteStep* pStep = new CEqWriteStep();
+			pStep->setName(STEP_EQ_RECIPE_PARAMETER_REQ);
+			pStep->setWriteSignalDev(m_nIndex == 0 ? 0x367 : 0x667);
+			pStep->setDataDev(m_nIndex == 0 ? 0x125b : 0x1bab);
+			if (addStep(STEP_ID_RECIPE_PARAMETER_CMD_REPLY, pStep) != 0) {
+				delete pStep;
+			}
+		}
+
+		{
+			// recipe parameter report
+			CEqReadStep* pStep = new CEqReadStep(m_nIndex == 0 ? 0xaa54 : 0xea54, 257 * 2,
+				[&](void* pFrom, int code, const char* pszData, size_t size) -> int {
+					if (code == ROK && pszData != nullptr && size > 0) {
+						// 此处解释配方数据
+						short ret = decodeRecipeParameterReport(pszData, size);
+						pStep->setReturnCode(ret);
+					}
+					pStep->setReturnCode(MRLRC_OK);
+					return -1;
+				});
+			pStep->setName(STEP_EQ_RECIPE_PARAMETER);
+			pStep->setWriteSignalDev(m_nIndex == 0 ? 0x34c : 0x64c);
+			pStep->setReturnDev(m_nIndex == 0 ? 0x126c : 0x1bbc);
+			if (addStep(STEP_ID_RECIPE_PARAMETER_REPORT, pStep) != 0) {
+				delete pStep;
+			}
+		}
+
+		// 使用CEqReadStep替换CEqJobEventStep
+		{
+			// Received Job Report Upstream #1~9
+			char szBuffer[256];
+			for (int i = 0; i < 9; i++) {
+				CEqReadStep* pStep = new CEqReadStep((m_nIndex == 0 ? 0x8c90 : 0xcc90) + 320 * i, 320 * 2,
+					[&](void* pFrom, int code, const char* pszData, size_t size) -> int {
+						if (code == ROK && pszData != nullptr && size > 0) {
+							int port = (int)(__int64)((CEqReadStep*)pFrom)->getProp("Port");
+							if (port > 0) {
+								decodeReceivedJobReport((CStep*)pFrom, port, pszData, size);
+							}
+						}
+						return -1;
+					});
+				sprintf_s(szBuffer, "%s%d", STEP_EQ_RECEIVED_JOB_UPSn, i + 1);
+				pStep->setName(szBuffer);
+				pStep->setProp("Port", (void*)(__int64)(i + 1));
+				pStep->setWriteSignalDev((m_nIndex == 0 ? 0x300 : 0x600) + i);
+				if (addStep(STEP_ID_RECIVE_JOB_UPS1 + i, pStep) != 0) {
+					delete pStep;
+				}
+			}
+		}
+		{
+			// Sent Out Job Report Downstream #1~9
+			char szBuffer[256];
+			for (int i = 0; i < 9; i++) {
+				CEqReadStep* pStep = new CEqReadStep((m_nIndex == 0 ? 0x8000 : 0xc000) + 320 * i, 320 * 2,
+					[&](void* pFrom, int code, const char* pszData, size_t size) -> int {
+						if (code == ROK && pszData != nullptr && size > 0) {
+							int port = (int)(__int64)((CEqReadStep*)pFrom)->getProp("Port");
+							if (port > 0) {
+								decodeReceivedJobReport((CStep*)pFrom, port, pszData, size);
+							}
+						}
+						return -1;
+					});
+				sprintf_s(szBuffer, "%s%d", STEP_EQ_SENT_OUT_JOB_DOWNSn, i + 1);
+				pStep->setName(szBuffer);
+				pStep->setProp("Port", (void*)(__int64)(i + 1));
+				pStep->setWriteSignalDev((m_nIndex == 0 ? 0x30a : 0x60a) + i);
+				if (addStep(STEP_ID_SENT_OUT_JOB_DOWNS1 + i, pStep) != 0) {
+					delete pStep;
+				}
+			}
+		}
+
+		/*
 		{
 			CEqJobEventStep* pStep = new CEqJobEventStep();
 			pStep->setName(STEP_EQ_RECEIVED_JOB_UPS1);
@@ -223,7 +305,7 @@
 		{
 			CEqJobEventStep* pStep = new CEqJobEventStep();
 			pStep->setName(STEP_EQ_SENT_OUT_JOB_DOWNS1);
-			pStep->setWriteSignalDev(m_nIndex == 0 ? 0x310 : 0x610);
+			pStep->setWriteSignalDev(m_nIndex == 0 ? 0x30a : 0x60a);
 			pStep->setJobDataDev(m_nIndex == 0 ? 0x8000 : 0xc000);
 			if (addStep(STEP_ID_SENT_OUT_JOB_DOWNS1, pStep) != 0) {
 				delete pStep;
@@ -232,12 +314,61 @@
 		{
 			CEqJobEventStep* pStep = new CEqJobEventStep();
 			pStep->setName(STEP_EQ_SENT_OUT_JOB_DOWNS2);
-			pStep->setWriteSignalDev(m_nIndex == 0 ? 0x311 : 0x611);
+			pStep->setWriteSignalDev(m_nIndex == 0 ? 0x30b : 0x60b);
 			pStep->setJobDataDev(m_nIndex == 0 ? 0x8140 : 0xc140);
 			if (addStep(STEP_ID_SENT_OUT_JOB_DOWNS2, pStep) != 0) {
 				delete pStep;
 			}
 		}
+		*/
+
+		{
+			// Fetched Out Job Report #1~15
+			char szBuffer[256];
+			for (int i = 0; i < 15; i++) {
+				CEqReadStep* pStep = new CEqReadStep((m_nIndex == 0 ? 0x9c31 : 0xdc31) + 18 * i, 18 * 2,
+					[&](void* pFrom, int code, const char* pszData, size_t size) -> int {
+						if (code == ROK && pszData != nullptr && size > 0) {
+							int port = (int)(__int64)((CEqReadStep*)pFrom)->getProp("Port");
+							if (port > 0) {
+								decodeFetchedOutJobReport((CStep*)pFrom, port, pszData, size);
+							}
+						}
+						return -1;
+					});
+				sprintf_s(szBuffer, "%s%d", STEP_EQ_FETCHED_OUT_JOBn, i + 1);
+				pStep->setName(szBuffer);
+				pStep->setProp("Port", (void*)(__int64)(i + 1));
+				pStep->setWriteSignalDev((m_nIndex == 0 ? 0x323 : 0x623) + i);
+				if (addStep(STEP_ID_FETCHED_OUT_JOB_REPORT1 + i, pStep) != 0) {
+					delete pStep;
+				}
+			}
+		}
+
+		{
+			// Stored Job Report #1~15
+			char szBuffer[256];
+			for (int i = 0; i < 15; i++) {
+				CEqReadStep* pStep = new CEqReadStep((m_nIndex == 0 ? 0x9b23 : 0xdb23) + 18 * i, 18 * 2,
+					[&](void* pFrom, int code, const char* pszData, size_t size) -> int {
+						if (code == ROK && pszData != nullptr && size > 0) {
+							int port = (int)(__int64)((CEqReadStep*)pFrom)->getProp("Port");
+							if (port > 0) {
+								decodeStoredJobReport((CStep*)pFrom, port, pszData, size);
+							}
+						}
+						return -1;
+					});
+				sprintf_s(szBuffer, "%s%d", STEP_EQ_STORED_JOBn, i + 1);
+				pStep->setName(szBuffer);
+				pStep->setProp("Port", (void*)(__int64)(i + 1));
+				pStep->setWriteSignalDev((m_nIndex == 0 ? 0x314 : 0x614) + i);
+				if (addStep(STEP_ID_STORE_JOB_REPORT1 + i, pStep) != 0) {
+					delete pStep;
+				}
+			}
+		}
 	}
 
 	void CBonder::onTimer(UINT nTimerid)
diff --git a/SourceCode/Bond/Servo/CEFEM.cpp b/SourceCode/Bond/Servo/CEFEM.cpp
index 4520495..6b28e45 100644
--- a/SourceCode/Bond/Servo/CEFEM.cpp
+++ b/SourceCode/Bond/Servo/CEFEM.cpp
@@ -19,6 +19,8 @@
 		m_pPort[1] = nullptr;
 		m_pPort[2] = nullptr;
 		m_pPort[3] = nullptr;
+		m_pAligner = nullptr;
+		m_pFliper = nullptr;
 	}
 
 	CEFEM::~CEFEM()
@@ -36,6 +38,23 @@
 	{
 		if (index < 4) {
 			m_pPort[index] = pPort;
+		}
+	}
+
+	void CEFEM::setAligner(CAligner* pAligner)
+	{
+		m_pAligner = pAligner;
+	}
+
+	void CEFEM::setFliper(CFliper* pFliper)
+	{
+		m_pFliper = pFliper;
+	}
+
+	void CEFEM::setArmTray(unsigned int index, CArmTray* pArmTray)
+	{
+		if (index < 2) {
+			m_pArmTray[index] = pArmTray;
 		}
 	}
 
@@ -213,7 +232,6 @@
 			}
 		}
 
-
 		{
 			// 请求主配方列表的step
 			CEqWriteStep* pStep = new CEqWriteStep();
@@ -274,6 +292,78 @@
 			STEP_ID_PORT4_CASSETTIE_UNLOAD_READY, 0x60b0);
 		ADD_EQ_CASSETTE_TRANSFER_STATE_STEP(STEP_EQ_P4_CASSETTE_BLOCKED, 0x103,
 			STEP_ID_PORT4_CASSETTIE_BLOCKED, 0x60b0);
+
+		{
+			// Received Job Report Upstream#1~9
+			char szBuffer[256];
+			for (int i = 0; i < 9; i++) {
+				CEqReadStep* pStep = new CEqReadStep(0x4c90 + 320 * i, 320 * 2,
+					[&](void* pFrom, int code, const char* pszData, size_t size) -> int {
+						if (code == ROK && pszData != nullptr && size > 0) {
+							int port = (int)(__int64)((CEqReadStep*)pFrom)->getProp("Port");
+							if (port > 0) {
+								decodeFetchedOutJobReport((CStep*)pFrom, port, pszData, size);
+							}
+						}
+						return -1;
+					});
+				sprintf_s(szBuffer, "%s%d", STEP_EQ_RECEIVED_JOBn, i + 1);
+				pStep->setName(szBuffer);
+				pStep->setProp("Upstream", (void*)(__int64)(i + 1));
+				pStep->setWriteSignalDev(0x0 + i);
+				if (addStep(STEP_ID_FETCHED_OUT_JOB_REPORT1 + i, pStep) != 0) {
+					delete pStep;
+				}
+			}
+		}
+
+		{
+			// Fetched Out Job Report #1~15
+			char szBuffer[256];
+			for (int i = 0; i < 15; i++) {
+				CEqReadStep* pStep = new CEqReadStep(0x5c31 + 18 * i, 18 * 2,
+					[&](void* pFrom, int code, const char* pszData, size_t size) -> int {
+						if (code == ROK && pszData != nullptr && size > 0) {
+							int port = (int)(__int64)((CEqReadStep*)pFrom)->getProp("Port");
+							if (port > 0) {
+								decodeFetchedOutJobReport((CStep*)pFrom, port, pszData, size);
+							}
+						}
+						return -1;
+					});
+				sprintf_s(szBuffer, "%s%d", STEP_EQ_FETCHED_OUT_JOBn, i+1);
+				pStep->setName(szBuffer);
+				pStep->setProp("Port", (void*)(__int64)(i + 1));
+				pStep->setWriteSignalDev(0x023 + i);
+				if (addStep(STEP_ID_FETCHED_OUT_JOB_REPORT1 + i, pStep) != 0) {
+					delete pStep;
+				}
+			}
+		}
+
+		{
+			// Store Job Report #1~15
+			char szBuffer[256];
+			for (int i = 0; i < 15; i++) {
+				CEqReadStep* pStep = new CEqReadStep(0x5b23 + 18 * i, 18 * 2,
+					[&](void* pFrom, int code, const char* pszData, size_t size) -> int {
+						if (code == ROK && pszData != nullptr && size > 0) {
+							int port = (int)(__int64)((CEqReadStep*)pFrom)->getProp("Port");
+							if (port > 0) {
+								decodeStoredJobReport((CStep*)pFrom, port, pszData, size);
+							}
+						}
+						return -1;
+					});
+				sprintf_s(szBuffer, "%s%d", STEP_EQ_STORED_JOBn, i + 1);
+				pStep->setName(szBuffer);
+				pStep->setProp("Port", (void*)(__int64)(i + 1));
+				pStep->setWriteSignalDev(0x014 + i);
+				if (addStep(STEP_ID_STORE_JOB_REPORT1 + i, pStep) != 0) {
+					delete pStep;
+				}
+			}
+		}
 	}
 
 	int CEFEM::onStepEvent(CStep* pStep, int code)
@@ -335,4 +425,64 @@
 			}
 		}
 	}
+
+	int CEFEM::onFetchedOutJob(int port, const char* pszGlassId)
+	{
+		if (port == 1) {
+			return m_pPort[0]->fetchedOutJob(pszGlassId);
+		}
+		if (port == 2) {
+			return m_pPort[1]->fetchedOutJob(pszGlassId);
+		}
+		if (port == 3) {
+			return m_pPort[2]->fetchedOutJob(pszGlassId);
+		}
+		if (port == 4) {
+			return m_pPort[3]->fetchedOutJob(pszGlassId);
+		}
+		if (port == 5) {
+			return m_pArmTray[0]->fetchedOutJob(pszGlassId);
+		}
+		if (port == 6) {
+			return m_pArmTray[1]->fetchedOutJob(pszGlassId);
+		}
+		if (port == 7) {
+			return m_pAligner->fetchedOutJob(pszGlassId);
+		}
+		if (port == 8) {
+			return m_pFliper->fetchedOutJob(pszGlassId);
+		}
+
+		return -1;
+	}
+
+	int CEFEM::onStoreJob(int port, const char* pszGlassId)
+	{
+		if (port == 1) {
+			return m_pPort[0]->storedJob(pszGlassId);
+		}
+		if (port == 2) {
+			return m_pPort[1]->storedJob(pszGlassId);
+		}
+		if (port == 3) {
+			return m_pPort[2]->storedJob(pszGlassId);
+		}
+		if (port == 4) {
+			return m_pPort[3]->storedJob(pszGlassId);
+		}
+		if (port == 5) {
+			return m_pArmTray[0]->storedJob(pszGlassId);
+		}
+		if (port == 6) {
+			return m_pArmTray[1]->storedJob(pszGlassId);
+		}
+		if (port == 7) {
+			return m_pAligner->storedJob(pszGlassId);
+		}
+		if (port == 8) {
+			return m_pFliper->storedJob(pszGlassId);
+		}
+
+		return -1;
+	}
 }
diff --git a/SourceCode/Bond/Servo/CEFEM.h b/SourceCode/Bond/Servo/CEFEM.h
index 2d7cc4b..5bc4c0c 100644
--- a/SourceCode/Bond/Servo/CEFEM.h
+++ b/SourceCode/Bond/Servo/CEFEM.h
@@ -1,6 +1,9 @@
 #pragma once
 #include "CEquipment.h"
 #include "CLoadPort.h"
+#include "CAligner.h"
+#include "CFliper.h"
+#include "CArmTray.h"
 
 
 namespace SERVO {
@@ -24,13 +27,20 @@
         virtual int recvIntent(CPin* pPin, CIntent* pIntent);
         virtual BOOL glassWillArrive(CGlass* pGlass);
         virtual void onReceiveLBData(const char* pszData, size_t size);
+        virtual int onFetchedOutJob(int port, const char* pszGlassId);
+        virtual int onStoreJob(int port, const char* pszGlassId);
 
     public:
         void setPort(unsigned int index, CLoadPort* pPort);
-
+        void setAligner(CAligner* pAligner);
+        void setFliper(CFliper* pFliper);
+        void setArmTray(unsigned int index, CArmTray* pArmTray);
 
     private:
         CLoadPort* m_pPort[4];
+        CAligner* m_pAligner;
+        CFliper* m_pFliper;
+        CArmTray* m_pArmTray[2];
     };
 }
 
diff --git a/SourceCode/Bond/Servo/CEqAlarmStep.cpp b/SourceCode/Bond/Servo/CEqAlarmStep.cpp
index db6f707..f488927 100644
--- a/SourceCode/Bond/Servo/CEqAlarmStep.cpp
+++ b/SourceCode/Bond/Servo/CEqAlarmStep.cpp
@@ -24,20 +24,21 @@
 	{
 		CReadStep::getAttributeVector(attrubutes);
 
+		unsigned int weight = 31;
 		attrubutes.addAttribute(new CAttribute("Alarm State",
-			std::to_string(m_nAlarmState).c_str(), ""));
+			std::to_string(m_nAlarmState).c_str(), "", weight++));
 		attrubutes.addAttribute(new CAttribute("Unit ID",
-			std::to_string(m_nUnitId).c_str(), ""));
+			std::to_string(m_nUnitId).c_str(), "", weight++));
 		attrubutes.addAttribute(new CAttribute("Alarm Level",
-			std::to_string(m_nAlarmLevel).c_str(), ""));
+			std::to_string(m_nAlarmLevel).c_str(), "", weight++));
 		attrubutes.addAttribute(new CAttribute("Alarm Code",
-			std::to_string(m_nAlarmCode).c_str(), ""));
+			std::to_string(m_nAlarmCode).c_str(), "", weight++));
 		attrubutes.addAttribute(new CAttribute("Alarm ID",
-			std::to_string(m_nAlarmId).c_str(), ""));
+			std::to_string(m_nAlarmId).c_str(), "", weight++));
 		attrubutes.addAttribute(new CAttribute("Text",
-			m_strText.c_str(), ""));
+			m_strText.c_str(), "", weight++));
 		attrubutes.addAttribute(new CAttribute("Description",
-			m_strDescription.c_str(), ""));
+			m_strDescription.c_str(), "", weight++));
 	}
 
 	int CEqAlarmStep::onReadData()
diff --git a/SourceCode/Bond/Servo/CEqCassetteCtrlCmdStep.cpp b/SourceCode/Bond/Servo/CEqCassetteCtrlCmdStep.cpp
index fd4b4a8..63cf42b 100644
--- a/SourceCode/Bond/Servo/CEqCassetteCtrlCmdStep.cpp
+++ b/SourceCode/Bond/Servo/CEqCassetteCtrlCmdStep.cpp
@@ -41,9 +41,10 @@
 	{
 		CWriteStep::getAttributeVector(attrubutes);
 
+		unsigned int weight = 31;
 		std::string strTemp;
 		attrubutes.addAttribute(new CAttribute("Control Command Dev",
-			("W" + CToolUnits::toHexString(m_nCtrlCmdDev, strTemp)).c_str(), ""));
+			("W" + CToolUnits::toHexString(m_nCtrlCmdDev, strTemp)).c_str(), "", weight++));
 	}
 }
 
diff --git a/SourceCode/Bond/Servo/CEqCassetteTransferStateStep.cpp b/SourceCode/Bond/Servo/CEqCassetteTransferStateStep.cpp
index 22c85a7..2dc627e 100644
--- a/SourceCode/Bond/Servo/CEqCassetteTransferStateStep.cpp
+++ b/SourceCode/Bond/Servo/CEqCassetteTransferStateStep.cpp
@@ -25,23 +25,24 @@
 	{
 		CReadStep::getAttributeVector(attrubutes);
 
+		unsigned int weight = 31;
 		std::string strTemp;
 		attrubutes.addAttribute(new CAttribute("Dev",
-			("W" + CToolUnits::toHexString(m_nPortStatusDev, strTemp)).c_str(), ""));
+			("W" + CToolUnits::toHexString(m_nPortStatusDev, strTemp)).c_str(), "", weight++));
 		attrubutes.addAttribute(new CAttribute("Port Status",
-			getPortStatusDescription(strTemp).c_str(), ""));
+			getPortStatusDescription(strTemp).c_str(), "", weight++));
 		attrubutes.addAttribute(new CAttribute("CassetteSequenceNo",
-			std::to_string(m_nCassetteSequenceNo).c_str(), ""));
+			std::to_string(m_nCassetteSequenceNo).c_str(), "", weight++));
 		attrubutes.addAttribute(new CAttribute("CassetteID",
-			m_strCassetteID.c_str(), ""));
+			m_strCassetteID.c_str(), "", weight++));
 		attrubutes.addAttribute(new CAttribute("LoadingCassetteType",
-			getLoadingCassetteTypeDescription(strTemp).c_str(), ""));
+			getLoadingCassetteTypeDescription(strTemp).c_str(), "", weight++));
 		attrubutes.addAttribute(new CAttribute("Q-Time Flag",
-			getQTimeFlagDescription(strTemp).c_str(), ""));
+			getQTimeFlagDescription(strTemp).c_str(), "", weight++));
 		attrubutes.addAttribute(new CAttribute("CassetteMappingState",
-			getCassetteMappingStateDescription(strTemp).c_str(), ""));
+			getCassetteMappingStateDescription(strTemp).c_str(), "", weight++));
 		attrubutes.addAttribute(new CAttribute("CassetteStatus",
-			getCassetteStatusDescription(strTemp).c_str(), ""));
+			getCassetteStatusDescription(strTemp).c_str(), "", weight++));
 	}
 
 	int CEqCassetteTransferStateStep::onReadData()
diff --git a/SourceCode/Bond/Servo/CEqCimMessageClearStep.cpp b/SourceCode/Bond/Servo/CEqCimMessageClearStep.cpp
index 3a4acee..3dc038c 100644
--- a/SourceCode/Bond/Servo/CEqCimMessageClearStep.cpp
+++ b/SourceCode/Bond/Servo/CEqCimMessageClearStep.cpp
@@ -30,8 +30,9 @@
 	{
 		CWriteStep::getAttributeVector(attrubutes);
 
+		unsigned int weight = 31;
 		std::string strTemp;
 		attrubutes.addAttribute(new CAttribute("Clear Cim Message Dev",
-			("W" + CToolUnits::toHexString(m_nClearCimMessageDev, strTemp)).c_str(), ""));
+			("W" + CToolUnits::toHexString(m_nClearCimMessageDev, strTemp)).c_str(), "", weight++));
 	}
 }
diff --git a/SourceCode/Bond/Servo/CEqCimMessageCmdStep.cpp b/SourceCode/Bond/Servo/CEqCimMessageCmdStep.cpp
index 3439d3a..d766185 100644
--- a/SourceCode/Bond/Servo/CEqCimMessageCmdStep.cpp
+++ b/SourceCode/Bond/Servo/CEqCimMessageCmdStep.cpp
@@ -31,8 +31,9 @@
 	{
 		CWriteStep::getAttributeVector(attrubutes);
 
+		unsigned int weight = 31;
 		std::string strTemp;
 		attrubutes.addAttribute(new CAttribute("Cim Message Dev",
-			("W" + CToolUnits::toHexString(m_nCimMessageDev, strTemp)).c_str(), ""));
+			("W" + CToolUnits::toHexString(m_nCimMessageDev, strTemp)).c_str(), "", weight++));
 	}
 }
diff --git a/SourceCode/Bond/Servo/CEqCimModeChangeStep.cpp b/SourceCode/Bond/Servo/CEqCimModeChangeStep.cpp
index cbb8e17..5b29e6e 100644
--- a/SourceCode/Bond/Servo/CEqCimModeChangeStep.cpp
+++ b/SourceCode/Bond/Servo/CEqCimModeChangeStep.cpp
@@ -39,8 +39,9 @@
 	{
 		CWriteStep::getAttributeVector(attrubutes);
 
+		unsigned int weight = 31;
 		std::string strTemp;
 		attrubutes.addAttribute(new CAttribute("Cim Mode Dev",
-			("W" + CToolUnits::toHexString(m_nCimModeDev, strTemp)).c_str(), ""));
+			("W" + CToolUnits::toHexString(m_nCimModeDev, strTemp)).c_str(), "", weight++));
 	}
 }
diff --git a/SourceCode/Bond/Servo/CEqCurrentRecipeChangeStep.cpp b/SourceCode/Bond/Servo/CEqCurrentRecipeChangeStep.cpp
index 37a7abe..cb022ea 100644
--- a/SourceCode/Bond/Servo/CEqCurrentRecipeChangeStep.cpp
+++ b/SourceCode/Bond/Servo/CEqCurrentRecipeChangeStep.cpp
@@ -24,12 +24,13 @@
 	{
 		CReadStep::getAttributeVector(attrubutes);
 
+		unsigned int weight = 31;
 		attrubutes.addAttribute(new CAttribute("UnitNo",
-			std::to_string(m_nUnitNo).c_str(), ""));
+			std::to_string(m_nUnitNo).c_str(), "", weight++));
 		attrubutes.addAttribute(new CAttribute("CurrentMasterRecipeId",
-			std::to_string(m_nCurrentMasterRecipeId).c_str(), ""));
+			std::to_string(m_nCurrentMasterRecipeId).c_str(), "", weight++));
 		attrubutes.addAttribute(new CAttribute("LocalRecipeId",
-			std::to_string(m_nLocalRecipeId).c_str(), ""));
+			std::to_string(m_nLocalRecipeId).c_str(), "", weight++));
 	}
 
 	int CEqCurrentRecipeChangeStep::onReadData()
diff --git a/SourceCode/Bond/Servo/CEqDateTimeSetCmdStep.cpp b/SourceCode/Bond/Servo/CEqDateTimeSetCmdStep.cpp
index 57a8d92..244c96e 100644
--- a/SourceCode/Bond/Servo/CEqDateTimeSetCmdStep.cpp
+++ b/SourceCode/Bond/Servo/CEqDateTimeSetCmdStep.cpp
@@ -29,8 +29,9 @@
 	{
 		CWriteStep::getAttributeVector(attrubutes);
 
+		unsigned int weight = 31;
 		std::string strTemp;
 		attrubutes.addAttribute(new CAttribute("DateTime Dev",
-			("W" + CToolUnits::toHexString(m_nDateTimeDev, strTemp)).c_str(), ""));
+			("W" + CToolUnits::toHexString(m_nDateTimeDev, strTemp)).c_str(), "", weight++));
 	}
 }
diff --git a/SourceCode/Bond/Servo/CEqJobEventStep.cpp b/SourceCode/Bond/Servo/CEqJobEventStep.cpp
index a0efb8b..7a084fe 100644
--- a/SourceCode/Bond/Servo/CEqJobEventStep.cpp
+++ b/SourceCode/Bond/Servo/CEqJobEventStep.cpp
@@ -21,28 +21,11 @@
 
 	void CEqJobEventStep::getAttributeVector(CAttributeVector& attrubutes)
 	{
-		CReadStep::getAttributeVector(attrubutes);
-
+		unsigned int weight = 31;
 		std::string strTemp;
 		attrubutes.addAttribute(new CAttribute("Dev",
-			("W" + CToolUnits::toHexString(m_nJobDataADev, strTemp)).c_str(), ""));
-		attrubutes.addAttribute(new CAttribute("PortNo",
-			std::to_string(m_jobDataA.getPortNo()).c_str(), ""));
-		attrubutes.addAttribute(new CAttribute("CarrierId",
-			m_jobDataA.getCarrierId().c_str(), ""));
-		attrubutes.addAttribute(new CAttribute("PruductId",
-			m_jobDataA.getPruductId().c_str(), ""));
-		attrubutes.addAttribute(new CAttribute("CarrierState",
-			m_jobDataA.getCarrierStateDescription(strTemp).c_str(), ""));
-		attrubutes.addAttribute(new CAttribute("SlotMapping",
-			std::to_string(m_jobDataA.getSlotMapping()).c_str(), ""));
-		attrubutes.addAttribute(new CAttribute("SlotSelectedFlag",
-			std::to_string(m_jobDataA.getSlotSelectedFlag()).c_str(), ""));
-		std::vector<std::string>& ids = m_jobDataA.getGlassIds();
-		for (int i = 0; i < ids.size(); i++) {
-			attrubutes.addAttribute(new CAttribute((std::string("GlassId") + std::to_string(i+1)).c_str(),
-				ids[i].c_str(), ""));
-		}
+			("W" + CToolUnits::toHexString(m_nJobDataADev, strTemp)).c_str(), "", weight++));
+		m_jobDataS.getAttributeVector(attrubutes, weight);
 	}
 
 	int CEqJobEventStep::onReadData()
@@ -57,7 +40,7 @@
 			return -1;
 		}
 
-		m_jobDataA.unserialize(szBuffer, 640);
+		m_jobDataS.unserialize(szBuffer, 640);
 		LOGI("<CEqJobEventStep-%s>Read JobDataA\n", m_strName.c_str());
 
 		return 0;
@@ -79,8 +62,8 @@
 		return 0;
 	}
 
-	CJobDataA* CEqJobEventStep::getJobDataA()
+	CJobDataS* CEqJobEventStep::getJobDataS()
 	{
-		return &m_jobDataA;
+		return &m_jobDataS;
 	}
 }
diff --git a/SourceCode/Bond/Servo/CEqJobEventStep.h b/SourceCode/Bond/Servo/CEqJobEventStep.h
index 380470f..71eb425 100644
--- a/SourceCode/Bond/Servo/CEqJobEventStep.h
+++ b/SourceCode/Bond/Servo/CEqJobEventStep.h
@@ -1,6 +1,6 @@
 #pragma once
 #include "CReadStep.h"
-#include "CJobDataA.h"
+#include "CJobDataS.h"
 
 
 namespace SERVO {
@@ -16,11 +16,11 @@
 		virtual int onComplete();
 		virtual int onTimeout();
 		void setJobDataDev(int nDev);
-		CJobDataA* getJobDataA();
+		CJobDataS* getJobDataS();
 
 	private:
 		int m_nJobDataADev;
-		CJobDataA m_jobDataA;
+		CJobDataS m_jobDataS;
 	};
 }
 
diff --git a/SourceCode/Bond/Servo/CEqModeChangeStep.cpp b/SourceCode/Bond/Servo/CEqModeChangeStep.cpp
index 6bb6f1e..2802c4b 100644
--- a/SourceCode/Bond/Servo/CEqModeChangeStep.cpp
+++ b/SourceCode/Bond/Servo/CEqModeChangeStep.cpp
@@ -39,8 +39,9 @@
 	{
 		CWriteStep::getAttributeVector(attrubutes);
 
+		unsigned int weight = 31;
 		std::string strTemp;
 		attrubutes.addAttribute(new CAttribute("Equipment Mode Dev",
-			("W" + CToolUnits::toHexString(m_nEqModeDev, strTemp)).c_str(), ""));
+			("W" + CToolUnits::toHexString(m_nEqModeDev, strTemp)).c_str(), "", weight++));
 	}
 }
diff --git a/SourceCode/Bond/Servo/CEqModeStep.cpp b/SourceCode/Bond/Servo/CEqModeStep.cpp
index 8b21988..91d1803 100644
--- a/SourceCode/Bond/Servo/CEqModeStep.cpp
+++ b/SourceCode/Bond/Servo/CEqModeStep.cpp
@@ -19,11 +19,12 @@
 	{
 		CReadStep::getAttributeVector(attrubutes);
 
+		unsigned int weight = 31;
 		std::string strTemp;
 		attrubutes.addAttribute(new CAttribute("Mode",
-			std::to_string(m_nMode).c_str(), getModeDescription(strTemp).c_str()));
+			std::to_string(m_nMode).c_str(), getModeDescription(strTemp).c_str(), weight++));
 		attrubutes.addAttribute(new CAttribute("Mode Dev",
-			("W" + CToolUnits::toHexString(m_nModeDev, strTemp)).c_str(), ""));
+			("W" + CToolUnits::toHexString(m_nModeDev, strTemp)).c_str(), "", weight++));
 	}
 
 	int CEqModeStep::onReadData()
diff --git a/SourceCode/Bond/Servo/CEqPortChangeStep.cpp b/SourceCode/Bond/Servo/CEqPortChangeStep.cpp
index 0927225..5d85b6c 100644
--- a/SourceCode/Bond/Servo/CEqPortChangeStep.cpp
+++ b/SourceCode/Bond/Servo/CEqPortChangeStep.cpp
@@ -24,21 +24,22 @@
 	{
 		CReadStep::getAttributeVector(attrubutes);
 
+		unsigned int weight = 31;
 		std::string strTemp;
 		attrubutes.addAttribute(new CAttribute("Port Dev",
-			("W" + CToolUnits::toHexString(m_nPortDev, strTemp)).c_str(), ""));
+			("W" + CToolUnits::toHexString(m_nPortDev, strTemp)).c_str(), "", weight++));
 		attrubutes.addAttribute(new CAttribute("PortType",
-			std::to_string(m_nPortType).c_str(), getPortTypeDescription(strTemp).c_str()));
+			std::to_string(m_nPortType).c_str(), getPortTypeDescription(strTemp).c_str(), weight++));
 		attrubutes.addAttribute(new CAttribute("PortMode",
-			std::to_string(m_nPortMode).c_str(), getPortModeDescription(strTemp).c_str()));
+			std::to_string(m_nPortMode).c_str(), getPortModeDescription(strTemp).c_str(), weight++));
 		attrubutes.addAttribute(new CAttribute("PortCassetteType",
-			std::to_string(m_nPortCassetteType).c_str(), getPortCassetteTypeDescription(strTemp).c_str()));
+			std::to_string(m_nPortCassetteType).c_str(), getPortCassetteTypeDescription(strTemp).c_str(), weight++));
 		attrubutes.addAttribute(new CAttribute("PortTransferMode",
-			std::to_string(m_nPortTransferMode).c_str(), getPortTransferModeDescription(strTemp).c_str()));
+			std::to_string(m_nPortTransferMode).c_str(), getPortTransferModeDescription(strTemp).c_str(), weight++));
 		attrubutes.addAttribute(new CAttribute("PortEnableMode",
-			std::to_string(m_nPortEanbleMode).c_str(), getPortEnableModeDescription(strTemp).c_str()));
+			std::to_string(m_nPortEanbleMode).c_str(), getPortEnableModeDescription(strTemp).c_str(), weight++));
 		attrubutes.addAttribute(new CAttribute("PortTypeAutoChangeMode",
-			std::to_string(m_nPortTypeAutoChangeMode).c_str(), getPortTypeAutoChangeModeDescription(strTemp).c_str()));
+			std::to_string(m_nPortTypeAutoChangeMode).c_str(), getPortTypeAutoChangeModeDescription(strTemp).c_str(), weight++));
 	}
 
 	int CEqPortChangeStep::onReadData()
diff --git a/SourceCode/Bond/Servo/CEqProcessStep.cpp b/SourceCode/Bond/Servo/CEqProcessStep.cpp
index 4f08edc..8c607bc 100644
--- a/SourceCode/Bond/Servo/CEqProcessStep.cpp
+++ b/SourceCode/Bond/Servo/CEqProcessStep.cpp
@@ -22,25 +22,26 @@
 	{
 		CReadStep::getAttributeVector(attrubutes);
 
+		unsigned int weight = 31;
 		attrubutes.addAttribute(new CAttribute("Glass ID",
-			m_strGlassId.c_str(), ""));
+			m_strGlassId.c_str(), "", weight++));
 		attrubutes.addAttribute(new CAttribute("Start Time",
-			m_strStartTime.c_str(), ""));
+			m_strStartTime.c_str(), "", weight++));
 		attrubutes.addAttribute(new CAttribute("End Time",
-			m_strEndTime.c_str(), ""));
+			m_strEndTime.c_str(), "", weight++));
 		attrubutes.addAttribute(new CAttribute("Total Parameter",
-			std::to_string(m_nTotalParameter).c_str(), ""));
+			std::to_string(m_nTotalParameter).c_str(), "", weight++));
 		attrubutes.addAttribute(new CAttribute("Total Group",
-			std::to_string(m_nTotalGroup).c_str(), ""));
+			std::to_string(m_nTotalGroup).c_str(), "", weight++));
 		attrubutes.addAttribute(new CAttribute("Current Group",
-			std::to_string(m_nCurrentGroup).c_str(), ""));
+			std::to_string(m_nCurrentGroup).c_str(), "", weight++));
 
 		char szName[256];
 		int index = 0;
 		for (auto item : m_params) {
 			sprintf_s(szName, 256, "Parameter %d", ++index);
 			attrubutes.addAttribute(new CAttribute(szName,
-				item.c_str(), ""));
+				item.c_str(), "", weight++));
 		}
 	}
 
diff --git a/SourceCode/Bond/Servo/CEqReadIntStep.cpp b/SourceCode/Bond/Servo/CEqReadIntStep.cpp
index e966f42..c6bb18e 100644
--- a/SourceCode/Bond/Servo/CEqReadIntStep.cpp
+++ b/SourceCode/Bond/Servo/CEqReadIntStep.cpp
@@ -27,11 +27,12 @@
 	{
 		CReadStep::getAttributeVector(attrubutes);
 
+		unsigned int weight = 31;
 		std::string strTemp;
 		attrubutes.addAttribute(new CAttribute("Dev",
-			("W" + CToolUnits::toHexString(m_nValueDev, strTemp)).c_str(), ""));
+			("W" + CToolUnits::toHexString(m_nValueDev, strTemp)).c_str(), "", weight++));
 		attrubutes.addAttribute(new CAttribute("Value",
-			std::to_string(m_nValue).c_str(), ""));
+			std::to_string(m_nValue).c_str(), "", weight++));
 	}
 
 	int CEqReadIntStep::onReadData()
diff --git a/SourceCode/Bond/Servo/CEqReadStep.cpp b/SourceCode/Bond/Servo/CEqReadStep.cpp
index 854338e..e94ba79 100644
--- a/SourceCode/Bond/Servo/CEqReadStep.cpp
+++ b/SourceCode/Bond/Servo/CEqReadStep.cpp
@@ -27,9 +27,10 @@
 	{
 		CReadStep::getAttributeVector(attrubutes);
 
+		unsigned int weight = 31;
 		std::string strTemp;
 		attrubutes.addAttribute(new CAttribute("Dev",
-			("W" + CToolUnits::toHexString(m_nDataDev, strTemp)).c_str(), ""));
+			("W" + CToolUnits::toHexString(m_nDataDev, strTemp)).c_str(), "", weight++));
 	}
 
 	int CEqReadStep::onReadData()
@@ -43,14 +44,14 @@
 		if (0 != nRet) {
 			LOGI("<CEqReadStep>Read data error.");
 			if (m_onReadBlock != nullptr) {
-				m_onReadBlock(RERROR, nullptr, 0);
+				m_onReadBlock(this, RERROR, nullptr, 0);
 			}
 			return -1;
 		}
 
 		LOGI("<CEqReadStep>read data succeed.");
 		if (m_onReadBlock != nullptr) {
-			m_onReadBlock(ROK, szBuffer, m_nReadSize);
+			m_onReadBlock(this, ROK, szBuffer, m_nReadSize);
 		}
 
 
@@ -62,7 +63,7 @@
 		CReadStep::onComplete();
 		LOGI("<CEqReadStep> onComplete.");
 		if (m_onReadBlock != nullptr) {
-			m_onReadBlock(RCOMPLETE, nullptr, 0);
+			m_onReadBlock(this, RCOMPLETE, nullptr, 0);
 		}
 
 		return 0;
@@ -73,7 +74,7 @@
 		CReadStep::onTimeout();
 		LOGI("<CEqReadStep> onTimeout.");
 		if (m_onReadBlock != nullptr) {
-			m_onReadBlock(RTIMEOUT, nullptr, 0);
+			m_onReadBlock(this, RTIMEOUT, nullptr, 0);
 		}
 
 		return 0;
diff --git a/SourceCode/Bond/Servo/CEqReadStep.h b/SourceCode/Bond/Servo/CEqReadStep.h
index fa9a2b3..3a83c35 100644
--- a/SourceCode/Bond/Servo/CEqReadStep.h
+++ b/SourceCode/Bond/Servo/CEqReadStep.h
@@ -11,7 +11,7 @@
 #define RCOMPLETE		1					/* 读数据流程完成 */
 
 namespace SERVO {
-	typedef std::function<int(int code, const char* pszData, size_t size)> ONREAD;
+	typedef std::function<int(void* pFrom, int code, const char* pszData, size_t size)> ONREAD;
 
 	class CEqReadStep : public CReadStep
 	{
diff --git a/SourceCode/Bond/Servo/CEqStatusStep.cpp b/SourceCode/Bond/Servo/CEqStatusStep.cpp
index 52eaa0f..6108c58 100644
--- a/SourceCode/Bond/Servo/CEqStatusStep.cpp
+++ b/SourceCode/Bond/Servo/CEqStatusStep.cpp
@@ -9,7 +9,7 @@
 	{
 		m_nStatusDev = 0;
 		for (int i = 0; i < STATUS_MAX; i++) {
-			m_nStatus[i] = 7;
+			m_nStatus[i] = 0;
 			m_nReasonCode[i] = 0;
 		}
 	
@@ -25,19 +25,20 @@
 	{
 		CReadStep::getAttributeVector(attrubutes);
 
+		unsigned int weight = 31;
 		char szName[256];
 		for (int i = 0; i < STATUS_MAX; i++) {
 			sprintf_s(szName, 256, "Status %d", i + 1);
 			attrubutes.addAttribute(new CAttribute(szName,
-				std::to_string(m_nStatus[i]).c_str(), ""));
+				std::to_string(m_nStatus[i]).c_str(), "", weight++));
 			sprintf_s(szName, 256, "Reason Code %d", i + 1);
 			attrubutes.addAttribute(new CAttribute(szName,
-				std::to_string(m_nReasonCode[i]).c_str(), ""));
+				std::to_string(m_nReasonCode[i]).c_str(), "", weight++));
 		}
 
 		std::string strTemp;
 		attrubutes.addAttribute(new CAttribute("Status Dev",
-			("W" + CToolUnits::toHexString(m_nStatusDev, strTemp)).c_str(), ""));
+			("W" + CToolUnits::toHexString(m_nStatusDev, strTemp)).c_str(), "", weight++));
 	}
 
 	int CEqStatusStep::getStatus(unsigned int uint)
diff --git a/SourceCode/Bond/Servo/CEqVCREnableStep.cpp b/SourceCode/Bond/Servo/CEqVCREnableStep.cpp
index 5f07263..ab73e23 100644
--- a/SourceCode/Bond/Servo/CEqVCREnableStep.cpp
+++ b/SourceCode/Bond/Servo/CEqVCREnableStep.cpp
@@ -43,6 +43,6 @@
 
 		std::string strTemp;
 		attrubutes.addAttribute(new CAttribute("VCR Mode Dev",
-			("W" + CToolUnits::toHexString(m_nEqVCRModeDev, strTemp)).c_str(), ""));
+			("W" + CToolUnits::toHexString(m_nEqVCRModeDev, strTemp)).c_str(), "", 31));
 	}
 }
diff --git a/SourceCode/Bond/Servo/CEqVcrEventStep.cpp b/SourceCode/Bond/Servo/CEqVcrEventStep.cpp
index e4c14d7..fd24db2 100644
--- a/SourceCode/Bond/Servo/CEqVcrEventStep.cpp
+++ b/SourceCode/Bond/Servo/CEqVcrEventStep.cpp
@@ -23,21 +23,22 @@
 	{
 		CReadStep::getAttributeVector(attrubutes);
 
+		unsigned int weight = 31;
 		std::string strTemp;
 		attrubutes.addAttribute(new CAttribute("Dev",
-			("W" + CToolUnits::toHexString(m_nVcrEventReportDev, strTemp)).c_str(), ""));
+			("W" + CToolUnits::toHexString(m_nVcrEventReportDev, strTemp)).c_str(), "", weight++));
 		attrubutes.addAttribute(new CAttribute("GlassId",
-			m_vcrEventReport.getGlassId().c_str(), ""));
+			m_vcrEventReport.getGlassId().c_str(), "", weight++));
 		attrubutes.addAttribute(new CAttribute("CassetteSequenceNo",
-			std::to_string(m_vcrEventReport.getCassetteSequenceNo()).c_str(), ""));
+			std::to_string(m_vcrEventReport.getCassetteSequenceNo()).c_str(), "", weight++));
 		attrubutes.addAttribute(new CAttribute("JobSequenceNo",
-			std::to_string(m_vcrEventReport.getJobSequenceNo()).c_str(), ""));
+			std::to_string(m_vcrEventReport.getJobSequenceNo()).c_str(), "", weight++));
 		attrubutes.addAttribute(new CAttribute("UnitNo",
-			std::to_string(m_vcrEventReport.getUnitNo()).c_str(), ""));
+			std::to_string(m_vcrEventReport.getUnitNo()).c_str(), "", weight++));
 		attrubutes.addAttribute(new CAttribute("VCR No",
-			std::to_string(m_vcrEventReport.getVcrNo()).c_str(), ""));
+			std::to_string(m_vcrEventReport.getVcrNo()).c_str(), "", weight++));
 		attrubutes.addAttribute(new CAttribute("VCR Result",
-			m_vcrEventReport.getVcrResultDescription(strTemp).c_str(), ""));
+			m_vcrEventReport.getVcrResultDescription(strTemp).c_str(), "", weight++));
 	}
 
 	int CEqVcrEventStep::onReadData()
diff --git a/SourceCode/Bond/Servo/CEqWriteStep.cpp b/SourceCode/Bond/Servo/CEqWriteStep.cpp
index da4a0cc..5bd1025 100644
--- a/SourceCode/Bond/Servo/CEqWriteStep.cpp
+++ b/SourceCode/Bond/Servo/CEqWriteStep.cpp
@@ -41,9 +41,10 @@
 	{
 		CWriteStep::getAttributeVector(attrubutes);
 
+		unsigned int weight = 31;
 		std::string strTemp;
 		attrubutes.addAttribute(new CAttribute("Data Dev",
-			("W" + CToolUnits::toHexString(m_nDataDev, strTemp)).c_str(), ""));
+			("W" + CToolUnits::toHexString(m_nDataDev, strTemp)).c_str(), "", weight++));
 	}
 
 	int CEqWriteStep::onComplete()
diff --git a/SourceCode/Bond/Servo/CEquipment.cpp b/SourceCode/Bond/Servo/CEquipment.cpp
index 096870f..3b15620 100644
--- a/SourceCode/Bond/Servo/CEquipment.cpp
+++ b/SourceCode/Bond/Servo/CEquipment.cpp
@@ -2,6 +2,7 @@
 #include "CEquipment.h"
 #include "ToolUnits.h"
 #include <regex>
+#include "CArm.h"
 
 
 #define CHECK_READ_STEP_SIGNAL(addr, data, size) {							\
@@ -34,6 +35,7 @@
 		m_bVCREnable[0] = FALSE;
 		m_pCclink = nullptr;
 		m_nBaseAlarmId = 0;
+		m_pArm = nullptr;
 		InitializeCriticalSection(&m_criticalSection);
 	}
 
@@ -74,6 +76,13 @@
 	void CEquipment::setCcLink(CCCLinkIEControl* pCcLink)
 	{
 		m_pCclink = pCcLink;
+	}
+
+	void CEquipment::setArm(CEquipment* pEquipment)
+	{
+		ASSERT(pEquipment->isArm());
+		ASSERT(!this->isArm());
+		m_pArm = pEquipment;
 	}
 
 	void CEquipment::setBaseAlarmId(int nBaseId)
@@ -194,48 +203,50 @@
 	void CEquipment::getAttributeVector(CAttributeVector& attrubutes)
 	{
 		attrubutes.clear();
+
+		unsigned int weight = 0;
 		attrubutes.addAttribute(new CAttribute("Network",
-			std::to_string(m_station.nNetNo).c_str(), ""));
+			std::to_string(m_station.nNetNo).c_str(), "", weight++));
 		attrubutes.addAttribute(new CAttribute("Station",
-			std::to_string(m_station.nStNo).c_str(), ""));
+			std::to_string(m_station.nStNo).c_str(), "", weight++));
 		attrubutes.addAttribute(new CAttribute("ID",
-			std::to_string(m_nID).c_str(), ""));
+			std::to_string(m_nID).c_str(), "", weight++));
 		attrubutes.addAttribute(new CAttribute("Name",
-			m_strName.c_str(), ""));
+			m_strName.c_str(), "", weight++));
 		attrubutes.addAttribute(new CAttribute("Description",
-			m_strDescription.c_str(), ""));
+			m_strDescription.c_str(), "", weight++));
 		attrubutes.addAttribute(new CAttribute("Alive",
-			this->isAlive() ? _T("TRUE") : _T("FALSE"), ""));
+			this->isAlive() ? _T("TRUE") : _T("FALSE"), "", weight++));
 		attrubutes.addAttribute(new CAttribute("CIM State",
-			m_bCimState ? _T("ON") : _T("OFF"), ""));
+			m_bCimState ? _T("ON") : _T("OFF"), "", weight++));
 		attrubutes.addAttribute(new CAttribute("Upstream",
-			m_bUpstreamInline ? _T("Inline") : _T("Offline"), ""));
+			m_bUpstreamInline ? _T("Inline") : _T("Offline"), "", weight++));
 		attrubutes.addAttribute(new CAttribute("Downstream",
-			m_bDownstreamInline ? _T("Inline") : _T("Offline"), ""));
+			m_bDownstreamInline ? _T("Inline") : _T("Offline"), "", weight++));
 		attrubutes.addAttribute(new CAttribute("Local Alarm",
-			m_bLocalAlarm ? _T("TRUE") : _T("FALSE"), ""));
+			m_bLocalAlarm ? _T("TRUE") : _T("FALSE"), "", weight++));
 		attrubutes.addAttribute(new CAttribute("Auto Recipe Change",
-			m_bAutoRecipeChange ? _T("TRUE") : _T("FALSE"), ""));
+			m_bAutoRecipeChange ? _T("TRUE") : _T("FALSE"), "", weight++));
 		char szTemp[256];
 		for (int i = 0; i < VCR_MAX; i++) {
 			sprintf_s(szTemp, 256, "VCR-%d", i + 1);
 			attrubutes.addAttribute(new CAttribute(szTemp,
-				m_bVCREnable[i] ? _T("Enable") : _T("Disable"), ""));
+				m_bVCREnable[i] ? _T("Enable") : _T("Disable"), "", weight++));
 		}
 
 		for (auto item : m_inputPins) {
 			attrubutes.addAttribute(new CAttribute(item->getName().c_str(),
-				std::to_string((int)item->getType()).c_str(), ""));
+				std::to_string((int)item->getType()).c_str(), "", weight++));
 		}
 
 		for (auto item : m_outputPins) {
 			attrubutes.addAttribute(new CAttribute(item->getName().c_str(),
-				std::to_string((int)item->getType()).c_str(), ""));
+				std::to_string((int)item->getType()).c_str(), "", weight++));
 		}
 
 		for (auto item : m_glassList) {
 			attrubutes.addAttribute(new CAttribute("Glass",
-				item->getID().c_str(), ""));
+				item->getID().c_str(), "", weight++));
 		}
 	}
 
@@ -319,7 +330,7 @@
 
 		// 以下解释和处理数据
 		BOOL bFlag;
-		int index = 0x840;
+		int index = 0x540;
 
 
 		// alive
@@ -382,6 +393,14 @@
 			CHECK_READ_STEP_SIGNAL(STEP_ID_EQMODE_CHANGED + i, pszData, size);
 		}
 
+		// process data report
+		CHECK_READ_STEP_SIGNAL(STEP_ID_PROCESS_DATA_REPORT, pszData, size);
+
+		// 配方改变
+		CHECK_READ_STEP_SIGNAL(STEP_ID_CURRENT_RECIPE_CHANGE_REPORT, pszData, size);
+		
+		// 主配方上报
+		CHECK_READ_STEP_SIGNAL(STEP_ID_MASTER_RECIPE_LIST_REPORT, pszData, size);
 
 		// CIM Mode
 		CHECK_WRITE_STEP_SIGNAL(STEP_ID_CIMMODE_CHANGED_CMD_REPLY, pszData, size);
@@ -415,6 +434,40 @@
 		CHECK_READ_STEP_SIGNAL(STEP_ID_RECIVE_JOB_UPS2, pszData, size);
 		CHECK_READ_STEP_SIGNAL(STEP_ID_SENT_OUT_JOB_DOWNS1, pszData, size);
 		CHECK_READ_STEP_SIGNAL(STEP_ID_SENT_OUT_JOB_DOWNS2, pszData, size);
+
+		// Store Job Report #1~15
+		CHECK_READ_STEP_SIGNAL(STEP_ID_STORE_JOB_REPORT1, pszData, size);
+		CHECK_READ_STEP_SIGNAL(STEP_ID_STORE_JOB_REPORT2, pszData, size);
+		CHECK_READ_STEP_SIGNAL(STEP_ID_STORE_JOB_REPORT3, pszData, size);
+		CHECK_READ_STEP_SIGNAL(STEP_ID_STORE_JOB_REPORT4, pszData, size);
+		CHECK_READ_STEP_SIGNAL(STEP_ID_STORE_JOB_REPORT5, pszData, size);
+		CHECK_READ_STEP_SIGNAL(STEP_ID_STORE_JOB_REPORT6, pszData, size);
+		CHECK_READ_STEP_SIGNAL(STEP_ID_STORE_JOB_REPORT7, pszData, size);
+		CHECK_READ_STEP_SIGNAL(STEP_ID_STORE_JOB_REPORT8, pszData, size);
+		CHECK_READ_STEP_SIGNAL(STEP_ID_STORE_JOB_REPORT9, pszData, size);
+		CHECK_READ_STEP_SIGNAL(STEP_ID_STORE_JOB_REPORT10, pszData, size);
+		CHECK_READ_STEP_SIGNAL(STEP_ID_STORE_JOB_REPORT11, pszData, size);
+		CHECK_READ_STEP_SIGNAL(STEP_ID_STORE_JOB_REPORT12, pszData, size);
+		CHECK_READ_STEP_SIGNAL(STEP_ID_STORE_JOB_REPORT13, pszData, size);
+		CHECK_READ_STEP_SIGNAL(STEP_ID_STORE_JOB_REPORT14, pszData, size);
+		CHECK_READ_STEP_SIGNAL(STEP_ID_STORE_JOB_REPORT15, pszData, size);
+
+		// Fetched Out Job Report #1~15
+		CHECK_READ_STEP_SIGNAL(STEP_ID_FETCHED_OUT_JOB_REPORT1, pszData, size);
+		CHECK_READ_STEP_SIGNAL(STEP_ID_FETCHED_OUT_JOB_REPORT2, pszData, size);
+		CHECK_READ_STEP_SIGNAL(STEP_ID_FETCHED_OUT_JOB_REPORT3, pszData, size);
+		CHECK_READ_STEP_SIGNAL(STEP_ID_FETCHED_OUT_JOB_REPORT4, pszData, size);
+		CHECK_READ_STEP_SIGNAL(STEP_ID_FETCHED_OUT_JOB_REPORT5, pszData, size);
+		CHECK_READ_STEP_SIGNAL(STEP_ID_FETCHED_OUT_JOB_REPORT6, pszData, size);
+		CHECK_READ_STEP_SIGNAL(STEP_ID_FETCHED_OUT_JOB_REPORT7, pszData, size);
+		CHECK_READ_STEP_SIGNAL(STEP_ID_FETCHED_OUT_JOB_REPORT8, pszData, size);
+		CHECK_READ_STEP_SIGNAL(STEP_ID_FETCHED_OUT_JOB_REPORT9, pszData, size);
+		CHECK_READ_STEP_SIGNAL(STEP_ID_FETCHED_OUT_JOB_REPORT10, pszData, size);
+		CHECK_READ_STEP_SIGNAL(STEP_ID_FETCHED_OUT_JOB_REPORT11, pszData, size);
+		CHECK_READ_STEP_SIGNAL(STEP_ID_FETCHED_OUT_JOB_REPORT12, pszData, size);
+		CHECK_READ_STEP_SIGNAL(STEP_ID_FETCHED_OUT_JOB_REPORT13, pszData, size);
+		CHECK_READ_STEP_SIGNAL(STEP_ID_FETCHED_OUT_JOB_REPORT14, pszData, size);
+		CHECK_READ_STEP_SIGNAL(STEP_ID_FETCHED_OUT_JOB_REPORT15, pszData, size);
 
 
 		// CEqCassetteTranserStateStep
@@ -769,6 +822,75 @@
 		return pGlass;
 	}
 
+	int CEquipment::fetchedOutJob(const char* pszGlassId)
+	{
+		if (m_pArm == nullptr) {
+			return -1;
+		}
+
+		// 找到指定的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(pszGlassId) == 0) {
+				pContext = (*iter);
+				m_glassList.erase(iter);
+				break;
+			}
+		}
+		if (pContext == nullptr) {
+			Unlock();
+			return -3;
+		}
+
+		((CArm*)m_pArm)->tempStore(pContext);
+		pContext->release();
+		Unlock();
+
+		if (m_listener.onDataChanged != nullptr) {
+			m_listener.onDataChanged(this, 0);
+		}
+
+		return 0;
+	}
+
+	int CEquipment::storedJob(const char* pszGlassId)
+	{
+		if (m_pArm == nullptr) {
+			return -1;
+		}
+
+		CGlass* pGlass = nullptr;
+		if (((CArm*)m_pArm)->tempFetchOut(pGlass) != 0) {
+			return -2;
+		}
+
+
+		ASSERT(pGlass);
+		Lock();
+		pGlass->addPath(m_nID);
+		pGlass->addRef();					// 加入list,addRef
+		m_glassList.push_back(pGlass);
+		pGlass->release();				// tempFetchOut需要调用一次release
+		Unlock();
+
+		if (m_listener.onDataChanged != nullptr) {
+			m_listener.onDataChanged(this, 0);
+		}
+
+		return 0;
+	}
+
+	BOOL CEquipment::isGlassListEmpty()
+	{
+		return m_glassList.empty();
+	}
+
 	bool CEquipment::isAlarmStep(SERVO::CStep* pStep)
 	{
 		return CToolUnits::startsWith(pStep->getName(), STEP_ALARM_START);
@@ -904,8 +1026,186 @@
 		return 0;
 	}
 
+	int CEquipment::recipeParameterRequest(short masterRecipeId, short localRecipeId, short unitNo)
+	{
+		SERVO::CEqWriteStep* pStep = (SERVO::CEqWriteStep*)getStepWithName(STEP_EQ_MASTER_RECIPE_LIST_REQ);
+		if (pStep == nullptr) {
+			return -1;
+		}
+
+		LOGI("<CEquipment-%s>正在请求单元<%d>主配方列表", m_strName.c_str(), unitNo);
+		if (m_recipesManager.syncing() != 0) {
+			return -2;
+		}
+		pStep->writeShort(unitNo, [&, unitNo](int code) -> int {
+			if (code == WOK) {
+				LOGI("<CEquipment-%s>请求单元<%d>主配方列表成功,正在等待数据.", m_strName.c_str(), unitNo);
+			}
+			else {
+				m_recipesManager.syncFailed();
+				LOGI("<CEquipment-%s>请求单元<%d>主配方列表失败,code:%d", m_strName.c_str(), unitNo, code);
+			}
+
+			return 0;
+			});
+		return 0;
+	}
+
 	short CEquipment::decodeRecipeListReport(const char* pszData, size_t size)
 	{
 		return m_recipesManager.decodeRecipeListReport(pszData, size);
 	}
+
+	short CEquipment::decodeRecipeParameterReport(const char* pszData, size_t size)
+	{
+		return m_recipesManager.decodeRecipeParameterReport(pszData, size);
+	}
+
+	int CEquipment::decodeReceivedJobReport(CStep* pStep, int port, const char* pszData, size_t size)
+	{
+		CJobDataS jobDataS;
+		int nRet = jobDataS.unserialize(&pszData[0], (int)size);
+		if (nRet < 0) return nRet;
+
+		// 缓存Attribute,用于调试时显示信息
+		unsigned int weight = 201;
+		CAttributeVector attrubutes;
+		jobDataS.getAttributeVector(attrubutes, weight);
+		pStep->addAttributeVector(attrubutes);
+
+
+		onReceivedJob(port, &jobDataS);
+
+		return nRet;
+	}
+
+	int CEquipment::onReceivedJob(int port, CJobDataS* pJobDataS)
+	{
+		LOGI("<CEquipment-%s>onReceivedJob.", m_strName.c_str());
+		// return fetchedOutJob(pszGlassId);
+		return 0;
+	}
+
+	int CEquipment::decodeSentOutJobReport(CStep* pStep, int port, const char* pszData, size_t size)
+	{
+		CJobDataS jobDataS;
+		int nRet = jobDataS.unserialize(&pszData[0], (int)size);
+		if (nRet < 0) return nRet;
+
+		// 缓存Attribute,用于调试时显示信息
+		unsigned int weight = 201;
+		CAttributeVector attrubutes;
+		jobDataS.getAttributeVector(attrubutes, weight);
+		pStep->addAttributeVector(attrubutes);
+
+
+		onReceivedJob(port, &jobDataS);
+
+		return nRet;
+	}
+
+	int CEquipment::onSentOutJob(int port, CJobDataS* pJobDataS)
+	{
+		LOGI("<CEquipment-%s>onSentOutJob.", m_strName.c_str());
+		// return fetchedOutJob(pszGlassId);
+		return 0;
+	}
+
+	int CEquipment::decodeFetchedOutJobReport(CStep* pStep, int port, const char* pszData, size_t size)
+	{
+		int index = 0;
+		short unitOrPort, unitOrPortNo, subUnitNo, subSlotNo;
+		CJobDataB jobDataB;
+		int nRet = jobDataB.unserialize(&pszData[index], (int)size);
+		if (nRet < 0) return nRet;
+		index += nRet;
+
+		memcpy(&unitOrPort, &pszData[index], sizeof(short));
+		index += sizeof(short);
+		memcpy(&unitOrPortNo, &pszData[index], sizeof(short));
+		index += sizeof(short);
+		memcpy(&subUnitNo, &pszData[index], sizeof(short));
+		index += sizeof(short);
+		memcpy(&subSlotNo, &pszData[index], sizeof(short));
+		index += sizeof(short);
+
+
+		// 缓存Attribute,用于调试时显示信息
+		unsigned int weight = 201;
+		pStep->addAttribute(new CAttribute("UnitOrPort",
+			std::to_string(unitOrPort).c_str(), "", weight++));
+		pStep->addAttribute(new CAttribute("UnitOrPortNo",
+			std::to_string(unitOrPortNo).c_str(), "", weight++));
+		pStep->addAttribute(new CAttribute("SubUnitNo",
+			std::to_string(subUnitNo).c_str(), "", weight++));
+		pStep->addAttribute(new CAttribute("SubSlotNo",
+			std::to_string(subSlotNo).c_str(), "", weight++));
+		pStep->addAttribute(new CAttribute("CassetteSequenceNo",
+			std::to_string(jobDataB.getCassetteSequenceNo()).c_str(), "", weight++));
+		pStep->addAttribute(new CAttribute("JobSequenceNo",
+			std::to_string(jobDataB.getJobSequenceNo()).c_str(), "", weight++));
+		pStep->addAttribute(new CAttribute("GlassId",
+			jobDataB.getGlassId().c_str(), "", weight++));
+
+
+		onFetchedOutJob(port, jobDataB.getGlassId().c_str());
+
+		return index;
+	}
+
+	int CEquipment::onFetchedOutJob(int port, const char* pszGlassId)
+	{
+		LOGI("<CEquipment-%s>onFetchedOutJob:port:%d|GlassId:%s", 
+			m_strName.c_str(), port, pszGlassId);
+		return fetchedOutJob(pszGlassId);
+	}
+
+	int CEquipment::decodeStoredJobReport(CStep* pStep, int port, const char* pszData, size_t size)
+	{
+		int index = 0;
+		short unitOrPort, unitOrPortNo, subUnitNo, subSlotNo;
+		CJobDataB jobDataB;
+		int nRet = jobDataB.unserialize(&pszData[index], (int)size);
+		if (nRet < 0) return nRet;
+		index += nRet;
+
+		memcpy(&unitOrPort, &pszData[index], sizeof(short));
+		index += sizeof(short);
+		memcpy(&unitOrPortNo, &pszData[index], sizeof(short));
+		index += sizeof(short);
+		memcpy(&subUnitNo, &pszData[index], sizeof(short));
+		index += sizeof(short);
+		memcpy(&subSlotNo, &pszData[index], sizeof(short));
+		index += sizeof(short);
+
+
+		// 缓存Attribute,用于调试时显示信息
+		unsigned int weight = 201;
+		pStep->addAttribute(new CAttribute("UnitOrPort",
+			std::to_string(unitOrPort).c_str(), "", weight++));
+		pStep->addAttribute(new CAttribute("UnitOrPortNo",
+			std::to_string(unitOrPortNo).c_str(), "", weight++));
+		pStep->addAttribute(new CAttribute("SubUnitNo",
+			std::to_string(subUnitNo).c_str(), "", weight++));
+		pStep->addAttribute(new CAttribute("SubSlotNo",
+			std::to_string(subSlotNo).c_str(), "", weight++));
+		pStep->addAttribute(new CAttribute("CassetteSequenceNo",
+			std::to_string(jobDataB.getCassetteSequenceNo()).c_str(), "", weight++));
+		pStep->addAttribute(new CAttribute("JobSequenceNo",
+			std::to_string(jobDataB.getJobSequenceNo()).c_str(), "", weight++));
+		pStep->addAttribute(new CAttribute("GlassId",
+			jobDataB.getGlassId().c_str(), "", weight++));
+
+
+		onStoreJob(port, jobDataB.getGlassId().c_str());
+
+		return index;
+	}
+
+	int CEquipment::onStoreJob(int port, const char* pszGlassId)
+	{
+		LOGI("<CEquipment-%s>onStore:port:%d|GlassId:%s",
+			m_strName.c_str(), port, pszGlassId);
+		return storedJob(pszGlassId);
+	}
 }
\ No newline at end of file
diff --git a/SourceCode/Bond/Servo/CEquipment.h b/SourceCode/Bond/Servo/CEquipment.h
index 14283bd..24eb6ff 100644
--- a/SourceCode/Bond/Servo/CEquipment.h
+++ b/SourceCode/Bond/Servo/CEquipment.h
@@ -27,6 +27,10 @@
 #include <list>
 #include "CGlass.h"
 #include "CRecipesManager.h"
+#include "CJobDataA.h"
+#include "CJobDataB.h"
+#include "CJobDataC.h"
+#include "CJobDataS.h"
 
 
 namespace SERVO {
@@ -74,6 +78,8 @@
 		virtual const char* getClassName() = 0;
 		virtual void setListener(EquipmentListener listener);
 		void setCcLink(CCCLinkIEControl* pCcLink);
+		virtual BOOL isArm() { return FALSE; };
+		void setArm(CEquipment* pEquipment);
 		void setBaseAlarmId(int nBaseId);
 		int getBaseAlarmId();
 		void setID(int nID);
@@ -110,6 +116,10 @@
 		virtual BOOL glassWillArrive(CGlass* pGlass);
 		virtual int outputGlass(int port);
 		virtual int glassArrived(CGlass* pGlass);
+		virtual int onReceivedJob(int port, CJobDataS* pJobDataS);
+		virtual int onSentOutJob(int port, CJobDataS* pJobDataS);
+		virtual int onFetchedOutJob(int port, const char* pszGlassId);
+		virtual int onStoreJob(int port, const char* pszGlassId);
 		void getGlassList(std::list<CGlass*>& list);
 		CGlass* getFrontGlass();
 		BOOL removeClass(CGlass* pGlass);
@@ -133,6 +143,17 @@
 		// unitNo: 0:local; Others:unit No
 		int masterRecipeListRequest(short unitNo);
 
+		// 请求配方参数
+		// masterRecipeId: 主配方id
+		// localRecipeId: 本地配方id
+		// unitNo: 0:local; Others:unit No
+		int recipeParameterRequest(short masterRecipeId, short localRecipeId, short unitNo);
+
+	public:
+		int fetchedOutJob(const char* pszGlassId);
+		int storedJob(const char* pszGlassId);
+		BOOL isGlassListEmpty();
+
 
 	// 以下为从CC-Link读取到的Bit标志位检测函数
 	public:
@@ -151,6 +172,11 @@
 		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 decodeReceivedJobReport(CStep* pStep, int port, const char* pszData, size_t size);
+		int decodeSentOutJobReport(CStep* pStep, int port, const char* pszData, size_t size);
+		int decodeFetchedOutJobReport(CStep* pStep, int port, const char* pszData, size_t size);
+		int decodeStoredJobReport(CStep* pStep, int port, const char* pszData, size_t size);
 
 	protected:
 		EquipmentListener m_listener;
@@ -181,6 +207,9 @@
 		std::map<unsigned int, CStep*> m_mapStep;
 		int m_nBaseAlarmId;
 		CRecipesManager m_recipesManager;
+
+	private:
+		CEquipment* m_pArm;
 	};
 }
 
diff --git a/SourceCode/Bond/Servo/CGlass.h b/SourceCode/Bond/Servo/CGlass.h
index e19a9a6..38ecaf2 100644
--- a/SourceCode/Bond/Servo/CGlass.h
+++ b/SourceCode/Bond/Servo/CGlass.h
@@ -2,6 +2,10 @@
 #include "Context.h"
 #include <string>
 #include "CPath.h"
+#include "CJobDataA.h"
+#include "CJobDataB.h"
+#include "CJobDataC.h"
+#include "CJobDataS.h"
 
 
 namespace SERVO {
diff --git a/SourceCode/Bond/Servo/CJobDataA.cpp b/SourceCode/Bond/Servo/CJobDataA.cpp
index 4c5e3e4..03d90ff 100644
--- a/SourceCode/Bond/Servo/CJobDataA.cpp
+++ b/SourceCode/Bond/Servo/CJobDataA.cpp
@@ -64,7 +64,7 @@
 		return 320 * 2;
 	}
 
-	int CJobDataA::unserialize(char* pszBuffer, int nBufferSize)
+	int CJobDataA::unserialize(const char* pszBuffer, int nBufferSize)
 	{
 		if (nBufferSize < 640) return -1;
 
diff --git a/SourceCode/Bond/Servo/CJobDataA.h b/SourceCode/Bond/Servo/CJobDataA.h
index 86b761a..c3879d4 100644
--- a/SourceCode/Bond/Servo/CJobDataA.h
+++ b/SourceCode/Bond/Servo/CJobDataA.h
@@ -20,7 +20,7 @@
 		int getSlotSelectedFlag();
 		std::vector<std::string>& getGlassIds();
 		int serialize(char* pszBuffer, int nBufferSize);
-		int unserialize(char* pszBuffer, int nBufferSize);
+		int unserialize(const char* pszBuffer, int nBufferSize);
 
 	private:
 		short m_nPortNo;
diff --git a/SourceCode/Bond/Servo/CJobDataB.cpp b/SourceCode/Bond/Servo/CJobDataB.cpp
index cf25ff2..9c00cb7 100644
--- a/SourceCode/Bond/Servo/CJobDataB.cpp
+++ b/SourceCode/Bond/Servo/CJobDataB.cpp
@@ -1,5 +1,6 @@
 #include "stdafx.h"
 #include "CJobDataB.h"
+#include "ToolUnits.h"
 
 
 namespace SERVO {
@@ -43,4 +44,39 @@
 	{
 		m_strGlassId = pszGlassId;
 	}
+
+	int CJobDataB::serialize(char* pszBuffer, int nBufferSize)
+	{
+		if (nBufferSize < 28) return -1;
+
+		int index = 0;
+		memcpy(&pszBuffer[index], &m_nCassetteSequenceNo, sizeof(short));
+		index += sizeof(short);
+
+		memcpy(&pszBuffer[index], &m_nJobSequenceNo, sizeof(short));
+		index += sizeof(short);
+
+		int strLen = min(20, m_strGlassId.size());
+		memcpy(&pszBuffer[index], m_strGlassId.c_str(), strLen);
+		index += 20;
+
+		return 14 * 2;
+	}
+
+	int CJobDataB::unserialize(const char* pszBuffer, int nBufferSize)
+	{
+		if (nBufferSize < 14) return -1;
+
+		int index = 0;
+		memcpy(&m_nCassetteSequenceNo, &pszBuffer[index], sizeof(short));
+		index += sizeof(short);
+
+		memcpy(&m_nJobSequenceNo, &pszBuffer[index], sizeof(short));
+		index += sizeof(short);
+
+		CToolUnits::convertString(&pszBuffer[index], 20, m_strGlassId);
+		index += 20;
+
+		return 14 * 2;
+	}
 }
diff --git a/SourceCode/Bond/Servo/CJobDataB.h b/SourceCode/Bond/Servo/CJobDataB.h
index 589ba72..c1ed9c2 100644
--- a/SourceCode/Bond/Servo/CJobDataB.h
+++ b/SourceCode/Bond/Servo/CJobDataB.h
@@ -15,6 +15,8 @@
 		void setJobSequenceNo(int no);
 		std::string& getGlassId();
 		void setGlassId(const char* pszGlassId);
+		int serialize(char* pszBuffer, int nBufferSize);
+		int unserialize(const char* pszBuffer, int nBufferSize);
 
 	private:
 		int m_nCassetteSequenceNo;
diff --git a/SourceCode/Bond/Servo/CJobDataS.cpp b/SourceCode/Bond/Servo/CJobDataS.cpp
index f474931..0c9de03 100644
--- a/SourceCode/Bond/Servo/CJobDataS.cpp
+++ b/SourceCode/Bond/Servo/CJobDataS.cpp
@@ -1,8 +1,12 @@
 #include "stdafx.h"
 #include "CJobDataS.h"
+#include "ToolUnits.h"
 
 
 namespace SERVO {
+#define JOBDATAS_SIZE				(256 * 2)
+#define ENABLE_JOBDATAS_RAWDATA		TRUE
+
 	CJobDataS::CJobDataS()
 	{
 		m_nCassetteSequenceNo = 0;
@@ -25,11 +29,19 @@
 		m_nSourceSlotNo = 0;
 		m_nTargetPortNo = 0;
 		m_nTargetSlotNo = 0;
+		m_pRawData = nullptr;
+		if (ENABLE_JOBDATAS_RAWDATA) {
+			m_pRawData = new char[JOBDATAS_SIZE];
+			serialize(m_pRawData, JOBDATAS_SIZE);
+		}
 	}
 
 	CJobDataS::~CJobDataS()
 	{
-
+		if (m_pRawData != nullptr) {
+			delete[] m_pRawData;
+			m_pRawData = nullptr;
+		}
 	}
 
 	int CJobDataS::getCassetteSequenceNo()
@@ -94,7 +106,7 @@
 
 	std::string& CJobDataS::getGlass2Id()
 	{
-		return m_strGlass1Id;
+		return m_strGlass2Id;
 	}
 
 	void CJobDataS::setGlass2Id(const char* pszId)
@@ -327,4 +339,321 @@
 	{
 		m_nTargetSlotNo = no;
 	}
+
+	int CJobDataS::serialize(char* pszBuffer, int nBufferSize)
+	{
+		if (nBufferSize < 256 * 2) return -1;
+
+		int index = 0;
+		memcpy(&pszBuffer[index], &m_nCassetteSequenceNo, sizeof(short));
+		index += sizeof(short);
+
+		memcpy(&pszBuffer[index], &m_nJobSequenceNo, sizeof(short));
+		index += sizeof(short);
+
+		int strLen = min(40, (int)m_strLotId.size());
+		memcpy(&pszBuffer[index], m_strLotId.c_str(), strLen);
+		index += 40;
+
+		strLen = min(20, (int)m_strProductId.size());
+		memcpy(&pszBuffer[index], m_strProductId.c_str(), strLen);
+		index += 20;
+
+		strLen = min(20, (int)m_strOperationId.size());
+		memcpy(&pszBuffer[index], m_strOperationId.c_str(), strLen);
+		index += 20;
+
+		strLen = min(20, (int)m_strGlass1Id.size());
+		memcpy(&pszBuffer[index], m_strGlass1Id.c_str(), strLen);
+		index += 20;
+
+		strLen = min(20, (int)m_strGlass2Id.size());
+		memcpy(&pszBuffer[index], m_strGlass2Id.c_str(), strLen);
+		index += 20;
+
+		memcpy(&pszBuffer[index], &m_nJobType, sizeof(short));
+		index += sizeof(short);
+
+		memcpy(&pszBuffer[index], &m_nMaterialsType, sizeof(short));
+		index += sizeof(short);
+
+		memcpy(&pszBuffer[index], &m_nProductType, sizeof(short));
+		index += sizeof(short);
+
+		memcpy(&pszBuffer[index], &m_nDummyType, sizeof(short));
+		index += sizeof(short);
+
+		memcpy(&pszBuffer[index], &m_nSkipFlag, sizeof(int));
+		index += sizeof(int);
+		
+		memcpy(&pszBuffer[index], &m_nProcessFlag, sizeof(int));
+		index += sizeof(int);
+
+		memcpy(&pszBuffer[index], &m_nProcessResonCode, sizeof(short));
+		index += sizeof(short);
+
+		memcpy(&pszBuffer[index], &m_nLastGlassFlag, sizeof(short));
+		index += sizeof(short);
+
+		memcpy(&pszBuffer[index], &m_nFirstGlassFlag, sizeof(short));
+		index += sizeof(short);
+
+		memcpy(&pszBuffer[index], &m_nLastGlassFlag, sizeof(short));
+		index += sizeof(short);
+
+		memcpy(&pszBuffer[index], &m_nQTime[0], sizeof(short));
+		index += sizeof(short);
+
+		memcpy(&pszBuffer[index], &m_nQTime[1], sizeof(short));
+		index += sizeof(short);
+
+		memcpy(&pszBuffer[index], &m_nQTime[2], sizeof(short));
+		index += sizeof(short);
+
+		memcpy(&pszBuffer[index], &m_nQTimeOverFlag, sizeof(short));
+		index += sizeof(short);
+
+		memcpy(&pszBuffer[index], &m_nMasterRecipe, sizeof(short));
+		index += sizeof(short);
+
+		strLen = min(10, (int)m_strProductRecipeId.size());
+		memcpy(&pszBuffer[index], m_strProductRecipeId.c_str(), strLen);
+		index += 10;
+
+		strLen = min(10, (int)m_strPCode.size());
+		memcpy(&pszBuffer[index], m_strPCode.c_str(), strLen);
+		index += 10;
+
+		strLen = min(10, (int)m_strUseType.size());
+		memcpy(&pszBuffer[index], m_strUseType.c_str(), strLen);
+		index += 10;
+
+		strLen = min(80, (int)m_strPanelMeasure.size());
+		memcpy(&pszBuffer[index], m_strPanelMeasure.c_str(), strLen);
+		index += 80;
+
+		memcpy(&pszBuffer[index], &m_nMode, sizeof(short));
+		index += sizeof(short);
+
+		memcpy(&pszBuffer[index], &m_nSlotUnitSelectFlag, sizeof(short));
+		index += sizeof(short);
+
+		memcpy(&pszBuffer[index], &m_nSourcePortNo, sizeof(short));
+		index += sizeof(short);
+
+		memcpy(&pszBuffer[index], &m_nSourceSlotNo, sizeof(short));
+		index += sizeof(short);
+
+		memcpy(&pszBuffer[index], &m_nTargetPortNo, sizeof(short));
+		index += sizeof(short);
+
+		memcpy(&pszBuffer[index], &m_nTargetSlotNo, sizeof(short));
+		index += sizeof(short);
+
+		return 256 * 2;
+	}
+
+	int CJobDataS::unserialize(const char* pszBuffer, int nBufferSize)
+	{
+		if (nBufferSize < 256 * 2) return -1;
+
+		int index = 0;
+		memcpy(&m_nCassetteSequenceNo, &pszBuffer[index], sizeof(short));
+		index += sizeof(short);
+
+		memcpy(&m_nJobSequenceNo, &pszBuffer[index], sizeof(short));
+		index += sizeof(short);
+
+		CToolUnits::convertString(&pszBuffer[index], 40, m_strLotId);
+		index += 40;
+
+		CToolUnits::convertString(&pszBuffer[index], 20, m_strProductId);
+		index += 20;
+
+		CToolUnits::convertString(&pszBuffer[index], 20, m_strOperationId);
+		index += 20;
+
+		CToolUnits::convertString(&pszBuffer[index], 20, m_strGlass1Id);
+		index += 20;
+
+		CToolUnits::convertString(&pszBuffer[index], 20, m_strGlass2Id);
+		index += 20;
+
+		memcpy(&m_nJobType, &pszBuffer[index], sizeof(short));
+		index += sizeof(short);
+
+		memcpy(&m_nMaterialsType, &pszBuffer[index], sizeof(short));
+		index += sizeof(short);
+
+		memcpy(&m_nProductType, &pszBuffer[index], sizeof(short));
+		index += sizeof(short);
+
+		memcpy(&m_nDummyType, &pszBuffer[index], sizeof(short));
+		index += sizeof(short);
+
+		memcpy(&m_nSkipFlag, &pszBuffer[index], sizeof(int));
+		index += sizeof(int);
+
+		memcpy(&m_nProcessFlag, &pszBuffer[index], sizeof(int));
+		index += sizeof(int);
+
+		memcpy(&m_nProcessResonCode, &pszBuffer[index], sizeof(short));
+		index += sizeof(short);
+
+		memcpy(&m_nLastGlassFlag, &pszBuffer[index], sizeof(short));
+		index += sizeof(short);
+
+		memcpy(&m_nFirstGlassFlag, &pszBuffer[index], sizeof(short));
+		index += sizeof(short);
+
+		memcpy(&m_nQTime[0], &pszBuffer[index], sizeof(short));
+		index += sizeof(short);
+
+		memcpy(&m_nQTime[1], &pszBuffer[index], sizeof(short));
+		index += sizeof(int);
+
+		memcpy(&m_nQTime[2], &pszBuffer[index], sizeof(int));
+		index += sizeof(short);
+
+		memcpy(&m_nQTimeOverFlag, &pszBuffer[index], sizeof(short));
+		index += sizeof(short);
+
+		memcpy(&m_nMasterRecipe, &pszBuffer[index], sizeof(short));
+		index += sizeof(short);
+
+		CToolUnits::convertString(&pszBuffer[index], 10, m_strProductRecipeId);
+		index += 10;
+
+		CToolUnits::convertString(&pszBuffer[index], 10, m_strProductRecipeId);
+		index += 10;
+
+		CToolUnits::convertString(&pszBuffer[index], 10, m_strProductRecipeId);
+		index += 10;
+
+		CToolUnits::convertString(&pszBuffer[index], 80, m_strProductRecipeId);
+		index += 80;
+
+		memcpy(&m_nMode, &pszBuffer[index], sizeof(short));
+		index += sizeof(short);
+
+		memcpy(&m_nSlotUnitSelectFlag, &pszBuffer[index], sizeof(short));
+		index += sizeof(short);
+
+		memcpy(&m_nSourcePortNo, &pszBuffer[index], sizeof(short));
+		index += sizeof(short);
+
+		memcpy(&m_nSourceSlotNo, &pszBuffer[index], sizeof(short));
+		index += sizeof(short);
+
+		memcpy(&m_nTargetPortNo, &pszBuffer[index], sizeof(short));
+		index += sizeof(short);
+
+		memcpy(&m_nTargetSlotNo, &pszBuffer[index], sizeof(short));
+		index += sizeof(short);
+
+
+		// 缓存原始数据
+		if (m_pRawData != nullptr) {
+			memcpy(m_pRawData, pszBuffer, JOBDATAS_SIZE);
+		}
+
+
+		return 256 * 2;
+	}
+
+	void CJobDataS::getAttributeVector(CAttributeVector& attrubutes, int beginWeight)
+	{
+		unsigned int weight = beginWeight;
+		std::string strTemp;
+
+		attrubutes.addAttribute(new CAttribute("CassetteSequenceNo",
+			std::to_string(getCassetteSequenceNo()).c_str(), "", weight++));
+
+		attrubutes.addAttribute(new CAttribute("JobSequenceNo",
+			std::to_string(getJobSequenceNo()).c_str(), "", weight++));
+
+		attrubutes.addAttribute(new CAttribute("LotId",
+			getLotId().c_str(), "", weight++));
+
+		attrubutes.addAttribute(new CAttribute("ProductId",
+			getProductId().c_str(), "", weight++));
+
+		attrubutes.addAttribute(new CAttribute("OperationId",
+			getOperationId().c_str(), "", weight++));
+
+		attrubutes.addAttribute(new CAttribute("Glass1Id",
+			getGlass1Id().c_str(), "", weight++));
+
+		attrubutes.addAttribute(new CAttribute("Glass2Id",
+			getGlass2Id().c_str(), "", weight++));
+
+		attrubutes.addAttribute(new CAttribute("JobType",
+			std::to_string(getJobType()).c_str(), "", weight++));
+
+		attrubutes.addAttribute(new CAttribute("MaterialsType",
+			std::to_string(getMaterialsType()).c_str(), "", weight++));
+
+		attrubutes.addAttribute(new CAttribute("ProductType",
+			std::to_string(getProductType()).c_str(), "", weight++));
+
+		attrubutes.addAttribute(new CAttribute("DummyType",
+			std::to_string(getDummyType()).c_str(), "", weight++));
+
+		attrubutes.addAttribute(new CAttribute("SkipFlag",
+			std::to_string(getSkipFlag()).c_str(), "", weight++));
+
+		attrubutes.addAttribute(new CAttribute("ProcessFlag",
+			std::to_string(getProcessFlag()).c_str(), "", weight++));
+
+		attrubutes.addAttribute(new CAttribute("ProcessResonCode",
+			std::to_string(getProcessResonCode()).c_str(), "", weight++));
+
+		attrubutes.addAttribute(new CAttribute("LastGlassFlag",
+			std::to_string(getLastGlassFlag()).c_str(), "", weight++));
+
+		attrubutes.addAttribute(new CAttribute("FirstGlassFlag",
+			std::to_string(getFirstGlassFlag()).c_str(), "", weight++));
+
+		attrubutes.addAttribute(new CAttribute("QTime1",
+			std::to_string(getQTime(0)).c_str(), "", weight++));
+
+		attrubutes.addAttribute(new CAttribute("QTime2",
+			std::to_string(getQTime(1)).c_str(), "", weight++));
+
+		attrubutes.addAttribute(new CAttribute("QTime3",
+			std::to_string(getQTime(2)).c_str(), "", weight++));
+
+		attrubutes.addAttribute(new CAttribute("QTimeOverFlag",
+			std::to_string(getQTimeOverFlag()).c_str(), "", weight++));
+
+		attrubutes.addAttribute(new CAttribute("MasterRecipe",
+			std::to_string(getMasterRecipe()).c_str(), "", weight++));
+
+		attrubutes.addAttribute(new CAttribute("ProductRecipeId",
+			getProductRecipeId().c_str(), "", weight++));
+
+		attrubutes.addAttribute(new CAttribute("PCode",
+			getPCode().c_str(), "", weight++));
+
+		attrubutes.addAttribute(new CAttribute("UseType",
+			getUseType().c_str(), "", weight++));
+
+		attrubutes.addAttribute(new CAttribute("PanelMeasure",
+			getPanelMeasure().c_str(), "", weight++));
+
+		attrubutes.addAttribute(new CAttribute("SlotUnitSelectFlag",
+			std::to_string(getSlotUnitSelectFlag()).c_str(), "", weight++));
+
+		attrubutes.addAttribute(new CAttribute("SourcePortNo",
+			std::to_string(getSourcePortNo()).c_str(), "", weight++));
+
+		attrubutes.addAttribute(new CAttribute("SourceSlotNo",
+			std::to_string(getSourceSlotNo()).c_str(), "", weight++));
+
+		attrubutes.addAttribute(new CAttribute("TargetPortNo",
+			std::to_string(getTargetPortNo()).c_str(), "", weight++));
+
+		attrubutes.addAttribute(new CAttribute("TargetSlotNo",
+			std::to_string(getTargetSlotNo()).c_str(), "", weight++));
+	}
 }
diff --git a/SourceCode/Bond/Servo/CJobDataS.h b/SourceCode/Bond/Servo/CJobDataS.h
index a2e3964..3894db2 100644
--- a/SourceCode/Bond/Servo/CJobDataS.h
+++ b/SourceCode/Bond/Servo/CJobDataS.h
@@ -1,4 +1,5 @@
 #pragma once
+#include "CAttributeVector.h"
 
 
 namespace SERVO {
@@ -67,6 +68,10 @@
 		void setTargetPortNo(int no);
 		int getTargetSlotNo();
 		void setTargetSlotNo(int no);
+		int serialize(char* pszBuffer, int nBufferSize);
+		int unserialize(const char* pszBuffer, int nBufferSize);
+		void getAttributeVector(CAttributeVector& attrubutes, int beginWeight);
+
 
 	private:
 		int m_nCassetteSequenceNo;
@@ -98,6 +103,9 @@
 		int m_nSourceSlotNo;
 		int m_nTargetPortNo;
 		int m_nTargetSlotNo;
+
+	private:
+		char* m_pRawData;
 	};
 }
 
diff --git a/SourceCode/Bond/Servo/CLoadPort.cpp b/SourceCode/Bond/Servo/CLoadPort.cpp
index 32ee535..9cab3d1 100644
--- a/SourceCode/Bond/Servo/CLoadPort.cpp
+++ b/SourceCode/Bond/Servo/CLoadPort.cpp
@@ -181,21 +181,22 @@
 	{
 		__super::getAttributeVector(attrubutes);
 
+		unsigned int weight = 101;
 		std::string strTemp;
 		attrubutes.addAttribute(new CAttribute("Index",
-			std::to_string(m_nIndex).c_str(), ""));
+			std::to_string(m_nIndex).c_str(), "", weight++));
 		attrubutes.addAttribute(new CAttribute("Type",
-			getPortTypeDescription(m_nType, strTemp).c_str(), ""));
+			getPortTypeDescription(m_nType, strTemp).c_str(), "", weight++));
 		attrubutes.addAttribute(new CAttribute("Mode",
-			getPortModeDescription(m_nMode, strTemp).c_str(), ""));
+			getPortModeDescription(m_nMode, strTemp).c_str(), "", weight++));
 		attrubutes.addAttribute(new CAttribute("CassetteType",
-			getPortCassetteTypeDescription(m_nCassetteType, strTemp).c_str(), ""));
+			getPortCassetteTypeDescription(m_nCassetteType, strTemp).c_str(), "", weight++));
 		attrubutes.addAttribute(new CAttribute("TransferMode",
-			getPortTransferModeDescription(m_nTransferMode, strTemp).c_str(), ""));
+			getPortTransferModeDescription(m_nTransferMode, strTemp).c_str(), "", weight++));
 		attrubutes.addAttribute(new CAttribute("Enable",
-			m_bEnable ? "Eanble" : "Disable", ""));
+			m_bEnable ? "Eanble" : "Disable", "", weight++));
 		attrubutes.addAttribute(new CAttribute("Auto Change",
-			m_bAutoChangeEnable ? "Eanble" : "Disable", ""));
+			m_bAutoChangeEnable ? "Eanble" : "Disable", "", weight++));
 	}
 
 	int CLoadPort::recvIntent(CPin* pPin, CIntent* pIntent)
diff --git a/SourceCode/Bond/Servo/CMaster.cpp b/SourceCode/Bond/Servo/CMaster.cpp
index 40f4705..6394380 100644
--- a/SourceCode/Bond/Servo/CMaster.cpp
+++ b/SourceCode/Bond/Servo/CMaster.cpp
@@ -24,7 +24,7 @@
 
 	CMaster::CMaster()
 	{
-		m_listener = {nullptr, nullptr, nullptr, nullptr};
+		m_listener = {nullptr, nullptr, nullptr, nullptr, nullptr};
 		m_bDataModify = FALSE;
 		m_hEventReadBitsThreadExit[0] = ::CreateEvent(NULL, TRUE, FALSE, NULL);
 		m_hEventReadBitsThreadExit[1] = ::CreateEvent(NULL, TRUE, FALSE, NULL);
@@ -56,6 +56,7 @@
 		m_listener.onEqCimStateChanged = listener.onEqCimStateChanged;
 		m_listener.onEqAlarm = listener.onEqAlarm;
 		m_listener.onEqVcrEventReport = listener.onEqVcrEventReport;
+		m_listener.onEqDataChanged = listener.onEqDataChanged;
 	}
 
 	int CMaster::init()
@@ -91,24 +92,63 @@
 
 		// 初始化添加各子设备
 		CLoadPort* pPort1, * pPort2, * pPort3, * pPort4;
+		CBonder* pBonder1, * pBonder2;
 		CEFEM* pEfem;
+		CArm* pArm;
+		CArmTray* pArmTray1, * pArmTray2;
+		CFliper* pFliper;
+		CVacuumBake* pVacuumBake;
+		CAligner* pAligner;
+		CBakeCooling* pBakeCooling;
+
 		pPort1 = addLoadPort(0);
 		pPort2 = addLoadPort(1);
 		pPort3 = addLoadPort(2);
 		pPort4 = addLoadPort(3);
 		pEfem = addEFEM();
+		pArm = addArm();
+		pArmTray1 = addArmTray(0);
+		pArmTray2 = addArmTray(1);
+		pFliper = addFliper();
+		pVacuumBake = addVacuumBake();
+		pAligner = addAligner();
+		pBonder1 = addBonder(0);
+		pBonder2 = addBonder(1);
+		pBakeCooling = addBakeCooling();
+
+		ASSERT(pEfem);
+		ASSERT(pFliper);
+		ASSERT(pVacuumBake);
+		ASSERT(pAligner);
+		ASSERT(pBonder1);
+		ASSERT(pBonder2);
+		ASSERT(pBakeCooling);
+
 		pEfem->setPort(0, pPort1);
 		pEfem->setPort(1, pPort1);
 		pEfem->setPort(2, pPort1);
 		pEfem->setPort(3, pPort1);
+		pEfem->setFliper(pFliper);
+		pEfem->setAligner(pAligner);
+		pEfem->setArmTray(0, pArmTray1);
+		pEfem->setArmTray(1, pArmTray2);
+		pPort1->setArm(pArm);
+		pPort2->setArm(pArm);
+		pPort3->setArm(pArm);
+		pPort4->setArm(pArm);
+		pArmTray1->setArm(pArm);
+		pArmTray2->setArm(pArm);
+		pFliper->setArm(pArm);
+		pVacuumBake->setArm(pArm);
+		pAligner->setArm(pArm);
+		pBonder1->setArm(pArm);
+		pBonder2->setArm(pArm);
+		pBakeCooling->setArm(pArm);
 
-		addFliper();
-		addVacuumBake();
-		addAligner();
-		addBonder(0);
-		addBonder(1);
-		addBakeCooling();
 		connectEquipments();
+
+
+
 
 		
 		// 读缓存数据
@@ -206,6 +246,10 @@
 		};
 		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);
+			}
 		};
 
 		pEquipment->setListener(listener);
@@ -255,7 +299,7 @@
 		return pEquipment;
 	}
 
-	int CMaster::addFliper()
+	CFliper* CMaster::addFliper()
 	{
 		CFliper* pEquipment = new CFliper();
 		pEquipment->setID(EQ_ID_FLIPER);
@@ -269,10 +313,10 @@
 
 		pEquipment->init();
 		LOGE("已添加“Fliper”.");
-		return 0;
+		return pEquipment;
 	}
 
-	int CMaster::addVacuumBake()
+	CVacuumBake* CMaster::addVacuumBake()
 	{
 		CVacuumBake* pEquipment = new CVacuumBake();
 		pEquipment->setID(EQ_ID_VACUUMBAKE);
@@ -286,10 +330,11 @@
 
 		pEquipment->init();
 		LOGE("已添加“VacuumBake”.");
-		return 0;
+
+		return pEquipment;
 	}
 
-	int CMaster::addAligner()
+	CAligner* CMaster::addAligner()
 	{
 		CAligner* pEquipment = new CAligner();
 		pEquipment->setID(EQ_ID_ALIGNER);
@@ -303,7 +348,8 @@
 
 		pEquipment->init();
 		LOGE("已添加“Aligner”.");
-		return 0;
+
+		return pEquipment;
 	}
 
 	CEFEM* CMaster::addEFEM()
@@ -324,11 +370,43 @@
 		return pEquipment;
 	}
 
+	CArm* CMaster::addArm()
+	{
+		CArm* pEquipment = new CArm();
+		pEquipment->setID(EQ_ID_ARM);
+		pEquipment->setBaseAlarmId(BASE_ALARM_EFEM);
+		pEquipment->setName("ARM");
+		pEquipment->setDescription("ARM.");
+		addToEquipmentList(pEquipment);
+
+
+		pEquipment->init();
+		LOGE("已添加“ARM”.");
+
+		return pEquipment;
+	}
+
+	CArmTray* CMaster::addArmTray(int index)
+	{
+		CArmTray* pEquipment = new CArmTray();
+		pEquipment->setID(index == 0 ? EQ_ID_ARM_TRAY1 : EQ_ID_ARM_TRAY2);
+		pEquipment->setBaseAlarmId(BASE_ALARM_EFEM);
+		pEquipment->setName(index == 0 ? "Arm Tray1" : "Arm Tray2");
+		pEquipment->setDescription(index == 0 ? "Arm Tray1." : "Arm Tray2.");
+		addToEquipmentList(pEquipment);
+
+
+		pEquipment->init();
+		LOGE("已添加“%s”.", pEquipment->getName().c_str());
+
+		return pEquipment;
+	}
+
 	/* 添加bonder1 或 bonder2 
 	 * index -- 0, bonder1
 	 * index -- 1, bonder2
 	 */
-	int CMaster::addBonder(int index)
+	CBonder* CMaster::addBonder(int index)
 	{
 		ASSERT(index == 0 || index == 1);
 		CBonder* pEquipment = new CBonder();
@@ -346,10 +424,10 @@
 		LOGE("已添加“%s”.", pEquipment->getName().c_str());
 
 
-		return 0;
+		return pEquipment;
 	}
 
-	int CMaster::addBakeCooling()
+	CBakeCooling* CMaster::addBakeCooling()
 	{
 		CBakeCooling* pEquipment = new CBakeCooling();
 		pEquipment->setID(EQ_ID_BAKE_COOLING);
@@ -360,10 +438,10 @@
 		pEquipment->setStation(0, 255);
 		addToEquipmentList(pEquipment);
 
-
 		pEquipment->init();
 		LOGE("已添加“Aligner”.");
-		return 0;
+
+		return pEquipment;
 	}
 
 	void CMaster::onTimer(UINT nTimerid)
diff --git a/SourceCode/Bond/Servo/CMaster.h b/SourceCode/Bond/Servo/CMaster.h
index 913d1c9..31ea5da 100644
--- a/SourceCode/Bond/Servo/CMaster.h
+++ b/SourceCode/Bond/Servo/CMaster.h
@@ -8,6 +8,8 @@
 #include "CAligner.h"
 #include "CVacuumBake.h"
 #include "CBakeCooling.h"
+#include "CArm.h"
+#include "CArmTray.h"
 #include "CCLinkIEControl.h"
 
 
@@ -16,12 +18,14 @@
     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;
     typedef std::function<void(void* pMaster, CEquipment* pEquipment, CVcrEventReport* pReport)> ONEQVCREVENTREPORT;
+    typedef std::function<void(void* pMaster, CEquipment* pEquipment, int code)> ONEQDATACHANGED;
     typedef struct _MasterListener
     {
         ONEQALIVE				onEqAlive;
         ONEQALIVE		        onEqCimStateChanged;
         ONEQALARM               onEqAlarm;
         ONEQVCREVENTREPORT	    onEqVcrEventReport;
+        ONEQDATACHANGED         onEqDataChanged;
     } MasterListener;
 
     class CMaster
@@ -44,12 +48,14 @@
     private:
         int addToEquipmentList(CEquipment* pEquipment);
         CLoadPort* addLoadPort(int index);
-        int addFliper();
-        int addVacuumBake();
-        int addAligner();
+        CFliper* addFliper();
+        CVacuumBake* addVacuumBake();
+        CAligner* addAligner();
         CEFEM* addEFEM();
-        int addBonder(int index);
-        int addBakeCooling();
+        CArm* addArm();
+        CArmTray* addArmTray(int index);
+        CBonder* addBonder(int index);
+        CBakeCooling* addBakeCooling();
         void connectEquipments();
         int saveCache();
         int saveCacheAndBackups();
diff --git a/SourceCode/Bond/Servo/CPageGraph1.cpp b/SourceCode/Bond/Servo/CPageGraph1.cpp
index 9a45e1c..f274ae0 100644
--- a/SourceCode/Bond/Servo/CPageGraph1.cpp
+++ b/SourceCode/Bond/Servo/CPageGraph1.cpp
@@ -114,6 +114,7 @@
 BOOL CPageGraph1::OnInitDialog()
 {
 	CDialogEx::OnInitDialog();
+	InitRxWindows();
 	SetTimer(1, 3000, nullptr);
 
 
@@ -269,6 +270,11 @@
 	if (m_hbrBkgnd != nullptr) {
 		::DeleteObject(m_hbrBkgnd);
 	}
+
+	if (m_pObserver != nullptr) {
+		m_pObserver->unsubscribe();
+		m_pObserver = NULL;
+	}
 }
 
 void CPageGraph1::OnSize(UINT nType, int cx, int cy)
@@ -417,7 +423,6 @@
 	CString s; s.Format(_T("OnGraphItemClicked %d"), pGraphNmhdr->dwData);
 	SERVO::CEquipment* pEquipment = (SERVO::CEquipment*)m_pGraph->GetIndicateBoxData(pGraphNmhdr->dwData);
 	if (pEquipment != nullptr) {
-		//AfxMessageBox(pEquipment->getName().c_str());
 		theApp.m_model.notifyPtr(RX_CODE_SELECT_EQUIPMENT, pEquipment);
 	}
 
@@ -428,7 +433,6 @@
 {
 	if (1 == nIDEvent) {
 		KillTimer(1);
-		InitRxWindows();
 
 		// 鏇存柊鐘舵��
 		{
diff --git a/SourceCode/Bond/Servo/CPageGraph2.cpp b/SourceCode/Bond/Servo/CPageGraph2.cpp
index ffc169d..cc44782 100644
--- a/SourceCode/Bond/Servo/CPageGraph2.cpp
+++ b/SourceCode/Bond/Servo/CPageGraph2.cpp
@@ -22,6 +22,7 @@
 	m_pEqsGraphWnd = nullptr;
 	m_crBkgnd = PAGE_GRPAH2_BACKGROUND_COLOR;
 	m_hbrBkgnd = nullptr;
+	m_pObserver = nullptr;
 }
 
 CPageGraph2::~CPageGraph2()
@@ -45,9 +46,44 @@
 // CPageGraph2 娑堟伅澶勭悊绋嬪簭
 
 
+void CPageGraph2::InitRxWindows()
+{
+	/* code */
+	// 璁㈤槄鏁版嵁
+	IRxWindows* pRxWindows = RX_GetRxWindows();
+	pRxWindows->enableLog(5);
+	if (m_pObserver == NULL) {
+		m_pObserver = pRxWindows->allocObserver([&](IAny* pAny) -> void {
+			// onNext
+			pAny->addRef();
+			int code = pAny->getCode();
+			if (RX_CODE_EQ_DATA_CHANGED == code) {
+				// 閫氱煡璁惧鐘舵��
+				SERVO::CEquipment* pEquipment = nullptr;
+				if (pAny->getPtrValue("ptr", (void*&)pEquipment)) {
+					if (pEquipment != nullptr) {
+						m_pEqsGraphWnd->ShowItemIndicator((DWORD_PTR)pEquipment, !pEquipment->isGlassListEmpty());
+					}
+				}
+			}
+
+			pAny->release();
+			}, [&]() -> void {
+				// onComplete
+			}, [&](IThrowable* pThrowable) -> void {
+				// onErrorm
+				pThrowable->printf();
+			});
+
+		theApp.m_model.getObservable()->observeOn(pRxWindows->mainThread())
+			->subscribe(m_pObserver);
+	}
+}
+
 BOOL CPageGraph2::OnInitDialog()
 {
 	CDialogEx::OnInitDialog();
+	InitRxWindows();
 	SetTimer(1, 2000, nullptr);
 
 
@@ -154,11 +190,14 @@
 		// 娴嬭瘯
 		else if (nCmd == ID_EQSGRAPHITEM_TEST1) {
 			SERVO::CEquipment* pEquipment = (SERVO::CEquipment*)pItem->pData;
-			pEquipment->outputGlass(0);
+			if (pEquipment->getID() == EQ_ID_LOADPORT1) {
+				pEquipment->outputGlass(1);
+			}
+			pEquipment->fetchedOutJob("P20250320A1A2");
 		}
 		else if (nCmd == ID_EQSGRAPHITEM_TEST2) {
 			SERVO::CEquipment* pEquipment = (SERVO::CEquipment*)pItem->pData;
-			pEquipment->outputGlass(1);
+			pEquipment->storedJob("P20250320A1A2");
 		}
 		else if (nCmd == ID_EQSGRAPHITEM_TEST3) {
 			SERVO::CEquipment* pEquipment = (SERVO::CEquipment*)pItem->pData;
@@ -216,13 +255,13 @@
 			}
 			*/
 			
-			/*
+			
 			if (pEquipment->getID() == EQ_ID_Bonder1
 				|| pEquipment->getID() == EQ_ID_Bonder2) {
 				static int ii = 0; ii++;
 				pEquipment->setEqMode((ii % 5) + 1);
 			}
-			*/
+			
 
 			/*
 			SERVO::CGlass* pGlass = pEquipment->getFrontGlass();
@@ -290,6 +329,11 @@
 	if (m_hbrBkgnd != nullptr) {
 		::DeleteObject(m_hbrBkgnd);
 	}
+
+	if (m_pObserver != nullptr) {
+		m_pObserver->unsubscribe();
+		m_pObserver = NULL;
+	}
 }
 
 
@@ -325,6 +369,8 @@
 	for (auto outPin : outPins) {
 		m_pEqsGraphWnd->AddPin(pItem, OUTPIN, outPin->getName().c_str(), (DWORD_PTR)outPin);
 	}
+
+	m_pEqsGraphWnd->ShowItemIndicator((DWORD_PTR)pEquipment, !pEquipment->isGlassListEmpty());
 }
 
 void CPageGraph2::OnTimer(UINT_PTR nIDEvent)
diff --git a/SourceCode/Bond/Servo/CPageGraph2.h b/SourceCode/Bond/Servo/CPageGraph2.h
index a90ca36..736fb65 100644
--- a/SourceCode/Bond/Servo/CPageGraph2.h
+++ b/SourceCode/Bond/Servo/CPageGraph2.h
@@ -14,11 +14,13 @@
 
 
 private:
+	void InitRxWindows();
 	void AddEqToGraphWnd(SERVO::CEquipment* pEquipment);
 	void SaveEqsGraphData();
 	void GetItemDataFormIni(const char* pszItemName, int& left, int& top);
 
 private:
+	IObserver* m_pObserver;
 	CEqsGraphWnd* m_pEqsGraphWnd;
 	COLORREF m_crBkgnd;
 	HBRUSH m_hbrBkgnd;
diff --git a/SourceCode/Bond/Servo/CPanelAttributes.cpp b/SourceCode/Bond/Servo/CPanelAttributes.cpp
index f278435..611ebac 100644
--- a/SourceCode/Bond/Servo/CPanelAttributes.cpp
+++ b/SourceCode/Bond/Servo/CPanelAttributes.cpp
@@ -59,6 +59,7 @@
 	SetDlgItemText(IDC_LABEL_TITLE, pStep->getName().c_str());
 	SERVO::CAttributeVector attrubutes;
 	pStep->getAttributeVector(attrubutes);
+	attrubutes.sortWithWeight();
 	unsigned int nSize = attrubutes.size();
 	for (unsigned int i = 0; i < nSize; i++) {
 		SERVO::CAttribute* pAttribute = attrubutes.getAttribute(i);
diff --git a/SourceCode/Bond/Servo/CReadStep.cpp b/SourceCode/Bond/Servo/CReadStep.cpp
index 5fd5dfd..d3c7747 100644
--- a/SourceCode/Bond/Servo/CReadStep.cpp
+++ b/SourceCode/Bond/Servo/CReadStep.cpp
@@ -154,10 +154,11 @@
 		CStep::getAttributeVector(attrubutes);
 		std::string strTemp;
 
+		unsigned int weight = 21;
 		attrubutes.addAttribute(new CAttribute("Current Step",
-			std::to_string(m_nCurStep).c_str(), ""));
+			std::to_string(m_nCurStep).c_str(), "", weight++));
 		attrubutes.addAttribute(new CAttribute("Signal Dev",
-			("W" + CToolUnits::toHexString(m_nWriteSignalDev, strTemp)).c_str(), ""));
+			("W" + CToolUnits::toHexString(m_nWriteSignalDev, strTemp)).c_str(), "", weight++));
 	}
 
 	void CReadStep::init()
diff --git a/SourceCode/Bond/Servo/CRecipesManager.cpp b/SourceCode/Bond/Servo/CRecipesManager.cpp
index e858b42..57d2c01 100644
--- a/SourceCode/Bond/Servo/CRecipesManager.cpp
+++ b/SourceCode/Bond/Servo/CRecipesManager.cpp
@@ -15,6 +15,7 @@
 	{
 		m_nSyncStatus = SS_NONE;
 		m_nTotalMasterRecipeCount = 0;
+		m_nTotalParameterCount = 0;
 		m_nWordThreadAddr = 0;
 		m_hWorkStop = nullptr;
 		m_hWorkThreadHandle = nullptr;
@@ -124,8 +125,22 @@
 		ASSERT(pRecipeList);
 
 
-		// 这里暂时只处理reportType=4,即Request from EAS
-		if (reportType == 4) {
+		/*
+		 1: Create
+		 2: Modify
+		 3: Delete
+		 4: Request from EAS
+		 */
+		if (reportType == RT_CREATE) {
+
+		}
+		else if (reportType == RT_MODIFY) {
+
+		}
+		else if (reportType == RT_DELETE) {
+
+		}
+		else if (reportType == RT_REQUEST_FROM_EAS) {
 			int nRet = pRecipeList->addRecipePacket(toatlGroupCount, currentGroupCount, pszIdsData, 250 * 2);
 			if (MRLRC_CURRENT_RECIPE_COMPLETE == nRet) {
 				lock();
@@ -150,6 +165,102 @@
 		return MRLRC_OK;
 	}
 
+	short CRecipesManager::decodeRecipeParameterReport(const char* pszData, size_t size)
+	{
+		int index = 0;
+		int masterRecipeId, localRecipeId, unitNo, reportType;
+		int totalParameterCount;
+		int toatlGroupCount, currentGroupCount;
+		const char* pszParameterData;
+
+		masterRecipeId = CToolUnits::toInt16(&pszData[index]);
+		index += 2;
+
+		localRecipeId = CToolUnits::toInt16(&pszData[index]);
+		index += 2;
+
+		unitNo = CToolUnits::toInt16(&pszData[index]);
+		index += 2;
+
+		reportType = CToolUnits::toInt16(&pszData[index]);
+		index += 2;
+
+		totalParameterCount = CToolUnits::toInt16(&pszData[index]);
+		index += 2;
+
+		toatlGroupCount = CToolUnits::toInt16(&pszData[index]);
+		index += 2;
+
+		currentGroupCount = CToolUnits::toInt16(&pszData[index]);
+		index += 2;
+
+		pszParameterData = &pszData[index];
+
+
+		lock();
+		if (m_nTotalParameterCount == 0) m_nTotalParameterCount = toatlGroupCount;
+		if (m_nTotalParameterCount != toatlGroupCount) {
+			return MRLRC_MASTER_RECIPE_LIST_COUNT_NG;
+		}
+		m_nTimeoutCount = 0;
+		unlock();
+
+
+
+
+		// 找到对应CRecipeList, 找不到则新建
+		/*
+		lock();
+		CRecipeList* pRecipeList = getRecipeListFromTemp(unitNo);
+		if (pRecipeList == nullptr) {
+			pRecipeList = new CRecipeList(unitNo);
+			m_mapRecipesTemp[unitNo] = pRecipeList;
+		}
+		unlock();
+		ASSERT(pRecipeList);
+		*/
+
+		/*
+		 1: Create
+		 2: Modify
+		 3: Delete
+		 4: Request from EAS
+		 */
+		/*
+		if (reportType == RT_CREATE) {
+
+		}
+		else if (reportType == RT_MODIFY) {
+
+		}
+		else if (reportType == RT_DELETE) {
+
+		}
+		else if (reportType == RT_REQUEST_FROM_EAS) {
+			int nRet = pRecipeList->addRecipePacket(toatlGroupCount, currentGroupCount, pszIdsData, 250 * 2);
+			if (MRLRC_CURRENT_RECIPE_COMPLETE == nRet) {
+				lock();
+				if (m_nTotalMasterRecipeCount == m_mapRecipesTemp.size()) {
+					for (auto item : m_mapRecipes) {
+						delete item.second;
+					}
+					m_mapRecipes = m_mapRecipesTemp;
+					m_mapRecipesTemp.clear();
+					m_nSyncStatus = SS_COMPLETE;
+					unlock();
+					return MRLRC_OK;
+				}
+				unlock();
+			}
+			else if (MRLRC_CONTINUE == nRet) {
+				return MRLRC_CONTINUE;
+			}
+		}
+		*/
+
+		return MRLRC_OK;
+	}
+
 	CRecipeList* CRecipesManager::getRecipeListFromTemp(int unitNo)
 	{
 		auto iter = m_mapRecipesTemp.find(unitNo);
diff --git a/SourceCode/Bond/Servo/CRecipesManager.h b/SourceCode/Bond/Servo/CRecipesManager.h
index d8e01dc..4c35285 100644
--- a/SourceCode/Bond/Servo/CRecipesManager.h
+++ b/SourceCode/Bond/Servo/CRecipesManager.h
@@ -21,6 +21,7 @@
 		int syncing();
 		void syncFailed();
 		short decodeRecipeListReport(const char* pszData, size_t size);
+		short decodeRecipeParameterReport(const char* pszData, size_t size);
 		CRecipeList* getRecipeListFromTemp(int unitNo);
 
 	public:
@@ -35,6 +36,7 @@
 		CRITICAL_SECTION m_cs;		// 同步锁
 		int m_nSyncStatus;
 		int m_nTotalMasterRecipeCount;
+		int m_nTotalParameterCount;
 		std::map<int, CRecipeList*> m_mapRecipes;
 		std::map<int, CRecipeList*> m_mapRecipesTemp;
 	};
diff --git a/SourceCode/Bond/Servo/CStep.cpp b/SourceCode/Bond/Servo/CStep.cpp
index 7ffc65d..d1907c7 100644
--- a/SourceCode/Bond/Servo/CStep.cpp
+++ b/SourceCode/Bond/Servo/CStep.cpp
@@ -53,11 +53,14 @@
 
 	void CStep::getAttributeVector(CAttributeVector& attrubutes)
 	{
+		unsigned int weight = 1;
 		attrubutes.clear();
 		attrubutes.addAttribute(new CAttribute("Network", 
-			std::to_string(m_station.nNetNo).c_str(), ""));
+			std::to_string(m_station.nNetNo).c_str(), "", weight++));
 		attrubutes.addAttribute(new CAttribute("Station",
-			std::to_string(m_station.nStNo).c_str(), ""));
+			std::to_string(m_station.nStNo).c_str(), "", weight++));
+		attrubutes.addAttributeVector(m_attributeVector);
+
 	}
 
 	void CStep::init()
@@ -70,6 +73,33 @@
 
 	}
 
+	void CStep::setProp(const char* pszKey, void* pValue)
+	{
+		m_mapProp[pszKey] = pValue;
+	}
+
+	void* CStep::getProp(const char* pszKey)
+	{
+		auto iter = m_mapProp.find(pszKey);
+		if (iter == m_mapProp.end()) return nullptr;
+		return iter->second;
+	}
+
+	void CStep::addAttribute(CAttribute* pAttribute)
+	{
+		// 添加attribute时,要前删除存在的同名的attribute
+		m_attributeVector.addAttribute(pAttribute, TRUE);
+	}
+
+	void CStep::addAttributeVector(CAttributeVector& attributeVector)
+	{
+		// 添加attribute时,要前删除存在的同名的attribute
+		unsigned int size = attributeVector.size();
+		for (unsigned int i = 0; i < size; i++) {
+			m_attributeVector.addAttribute(attributeVector.getAttribute(i), TRUE);
+		}
+	}
+
 	void CStep::convertString(const char* pszBuffer, int size, std::string& strOut)
 	{
 		strOut.clear();
diff --git a/SourceCode/Bond/Servo/CStep.h b/SourceCode/Bond/Servo/CStep.h
index 866e6f2..20520f3 100644
--- a/SourceCode/Bond/Servo/CStep.h
+++ b/SourceCode/Bond/Servo/CStep.h
@@ -2,6 +2,7 @@
 #include "CCLinkIEControl.h"
 #include "CAttributeVector.h"
 #include "ToolUnits.h"
+#include <map>
 
 
 namespace SERVO {
@@ -26,7 +27,10 @@
 		virtual void getAttributeVector(CAttributeVector& attrubutes);
 		virtual void init();
 		virtual void term();
-
+		void setProp(const char* pszKey, void* pValue);
+		void* getProp(const char* pszKey);
+		void addAttribute(CAttribute* pAttribute);
+		void addAttributeVector(CAttributeVector& attributeVector);
 
 	protected:
 		inline void Lock() { EnterCriticalSection(&m_criticalSection); }
@@ -40,6 +44,8 @@
 		CEquipment* m_pEquipment;
 		CCCLinkIEControl* m_pCclink;
 		CRITICAL_SECTION m_criticalSection;
+		std::map<std::string, void*> m_mapProp;
+		CAttributeVector m_attributeVector;
 	};
 }
 
diff --git a/SourceCode/Bond/Servo/CWriteStep.cpp b/SourceCode/Bond/Servo/CWriteStep.cpp
index ba18a5c..0470421 100644
--- a/SourceCode/Bond/Servo/CWriteStep.cpp
+++ b/SourceCode/Bond/Servo/CWriteStep.cpp
@@ -141,10 +141,11 @@
 		CStep::getAttributeVector(attrubutes);
 		std::string temp;
 
+		unsigned int weight = 20;
 		attrubutes.addAttribute(new CAttribute("Current Step",
-			std::to_string(m_nCurStep).c_str(), ""));
+			std::to_string(m_nCurStep).c_str(), "", weight++));
 		attrubutes.addAttribute(new CAttribute("Signal Dev",
-			("W" + CToolUnits::toHexString(m_nWriteSignalDev, temp)).c_str(), ""));
+			("W" + CToolUnits::toHexString(m_nWriteSignalDev, temp)).c_str(), "", weight++));
 	}
 
 	void CWriteStep::init()
diff --git a/SourceCode/Bond/Servo/Common.h b/SourceCode/Bond/Servo/Common.h
index 34d4258..b4b4a75 100644
--- a/SourceCode/Bond/Servo/Common.h
+++ b/SourceCode/Bond/Servo/Common.h
@@ -13,6 +13,7 @@
 #define RX_CODE_SELECT_STEP				1007
 #define RX_CODE_ALARM_SET				1008
 #define RX_CODE_ALARM_CLEAR				1009
+#define RX_CODE_EQ_DATA_CHANGED			1010
 
 
 /* Channel Name */
@@ -61,6 +62,9 @@
 #define EQ_ID_VACUUMBAKE		9
 #define EQ_ID_ALIGNER			10
 #define EQ_ID_BAKE_COOLING		11
+#define EQ_ID_ARM				12
+#define EQ_ID_ARM_TRAY1			13
+#define EQ_ID_ARM_TRAY2			14
 #define EQ_ID_OPERATOR_REMOVE	999
 
 
@@ -133,14 +137,75 @@
 #define STEP_EQ_P3_CASSETTE_CTRL_CMD	_T("EQPort3CassetteCtrlCmd")
 #define STEP_EQ_P4_CASSETTE_CTRL_CMD	_T("EQPort4CassetteCtrlCmd")
 #define STEP_EQ_CIM_MESSAGE_CONFIRM		_T("EQCimMessageConfirm")
+#define STEP_EQ_RECEIVED_JOB_UPSn		_T("EQJEReceivedJobUps")
 #define STEP_EQ_RECEIVED_JOB_UPS1		_T("EQJEReceivedJobUps1")
 #define STEP_EQ_RECEIVED_JOB_UPS2		_T("EQJEReceivedJobUps2")
+#define STEP_EQ_RECEIVED_JOB_UPS3		_T("EQJEReceivedJobUps3")
+#define STEP_EQ_RECEIVED_JOB_UPS4		_T("EQJEReceivedJobUps4")
+#define STEP_EQ_RECEIVED_JOB_UPS5		_T("EQJEReceivedJobUps5")
+#define STEP_EQ_RECEIVED_JOB_UPS6		_T("EQJEReceivedJobUps6")
+#define STEP_EQ_RECEIVED_JOB_UPS7		_T("EQJEReceivedJobUps7")
+#define STEP_EQ_RECEIVED_JOB_UPS8		_T("EQJEReceivedJobUps8")
+#define STEP_EQ_RECEIVED_JOB_UPS9		_T("EQJEReceivedJobUps9")
+#define STEP_EQ_SENT_OUT_JOB_DOWNSn		_T("EQJESentOutJobDowns")
 #define STEP_EQ_SENT_OUT_JOB_DOWNS1		_T("EQJESentOutJobDowns1")
 #define STEP_EQ_SENT_OUT_JOB_DOWNS2		_T("EQJESentOutJobDowns2")
+#define STEP_EQ_SENT_OUT_JOB_DOWNS3		_T("EQJESentOutJobDowns3")
+#define STEP_EQ_SENT_OUT_JOB_DOWNS4		_T("EQJESentOutJobDowns4")
+#define STEP_EQ_SENT_OUT_JOB_DOWNS5		_T("EQJESentOutJobDowns5")
+#define STEP_EQ_SENT_OUT_JOB_DOWNS6		_T("EQJESentOutJobDowns6")
+#define STEP_EQ_SENT_OUT_JOB_DOWNS7		_T("EQJESentOutJobDowns7")
+#define STEP_EQ_SENT_OUT_JOB_DOWNS8		_T("EQJESentOutJobDowns8")
+#define STEP_EQ_SENT_OUT_JOB_DOWNS9		_T("EQJESentOutJobDowns9")
 #define STEP_EQ_VCR1_EVENT_REPORT		_T("EQVcr1EventReport")
 #define STEP_EQ_RURRENT_RECIPE_CHANGE	_T("EQCurrentRecipeChange")
 #define STEP_EQ_MASTER_RECIPE_LIST_REQ	_T("EQMasterRecipeListReq")
 #define STEP_EQ_MASTER_RECIPE_LIST		_T("EQMasterRecipeListReport")
+#define STEP_EQ_RECIPE_PARAMETER_REQ	_T("EQRecipeParameterReq")
+#define STEP_EQ_RECIPE_PARAMETER		_T("EQRecipeParameterReport")
+#define STEP_EQ_RECEIVED_JOBn			_T("EQReceivedJobReport")
+#define STEP_EQ_RECEIVED_JOB1			_T("EQReceivedJobReport1")
+#define STEP_EQ_RECEIVED_JOB2			_T("EQReceivedJobReport2")
+#define STEP_EQ_RECEIVED_JOB3			_T("EQReceivedJobReport3")
+#define STEP_EQ_RECEIVED_JOB4			_T("EQReceivedJobReport4")
+#define STEP_EQ_RECEIVED_JOB5			_T("EQReceivedJobReport5")
+#define STEP_EQ_RECEIVED_JOB6			_T("EQReceivedJobReport6")
+#define STEP_EQ_RECEIVED_JOB7			_T("EQReceivedJobReport7")
+#define STEP_EQ_RECEIVED_JOB8			_T("EQReceivedJobReport8")
+#define STEP_EQ_RECEIVED_JOB9			_T("EQReceivedJobReport9")
+#define STEP_EQ_FETCHED_OUT_JOBn		_T("EQFetchedOutJobReport")
+#define STEP_EQ_FETCHED_OUT_JOB1		_T("EQFetchedOutJobReport1")
+#define STEP_EQ_FETCHED_OUT_JOB2		_T("EQFetchedOutJobReport2")
+#define STEP_EQ_FETCHED_OUT_JOB3		_T("EQFetchedOutJobReport3")
+#define STEP_EQ_FETCHED_OUT_JOB4		_T("EQFetchedOutJobReport4")
+#define STEP_EQ_FETCHED_OUT_JOB5		_T("EQFetchedOutJobReport5")
+#define STEP_EQ_FETCHED_OUT_JOB6		_T("EQFetchedOutJobReport6")
+#define STEP_EQ_FETCHED_OUT_JOB7		_T("EQFetchedOutJobReport7")
+#define STEP_EQ_FETCHED_OUT_JOB8		_T("EQFetchedOutJobReport8")
+#define STEP_EQ_FETCHED_OUT_JOB9		_T("EQFetchedOutJobReport9")
+#define STEP_EQ_FETCHED_OUT_JOB10		_T("EQFetchedOutJobReport10")
+#define STEP_EQ_FETCHED_OUT_JOB11		_T("EQFetchedOutJobReport11")
+#define STEP_EQ_FETCHED_OUT_JOB12		_T("EQFetchedOutJobReport12")
+#define STEP_EQ_FETCHED_OUT_JOB13		_T("EQFetchedOutJobReport13")
+#define STEP_EQ_FETCHED_OUT_JOB14		_T("EQFetchedOutJobReport14")
+#define STEP_EQ_FETCHED_OUT_JOB15		_T("EQFetchedOutJobReport15")
+#define STEP_EQ_STORED_JOBn				_T("EQStoredJobReport")
+#define STEP_EQ_STORED_JOB1				_T("EQStoredJobReport1")
+#define STEP_EQ_STORED_JOB2				_T("EQStoredJobReport2")
+#define STEP_EQ_STORED_JOB3				_T("EQStoredJobReport3")
+#define STEP_EQ_STORED_JOB4				_T("EQStoredJobReport4")
+#define STEP_EQ_STORED_JOB5				_T("EQStoredJobReport5")
+#define STEP_EQ_STORED_JOB6				_T("EQStoredJobReport6")
+#define STEP_EQ_STORED_JOB7				_T("EQStoredJobReport7")
+#define STEP_EQ_STORED_JOB8				_T("EQStoredJobReport8")
+#define STEP_EQ_STORED_JOB9				_T("EQStoredJobReport9")
+#define STEP_EQ_STORED_JOB10			_T("EQStoredJobReport10")
+#define STEP_EQ_STORED_JOB11			_T("EQStoredJobReport11")
+#define STEP_EQ_STORED_JOB12			_T("EQStoredJobReport12")
+#define STEP_EQ_STORED_JOB13			_T("EQStoredJobReport13")
+#define STEP_EQ_STORED_JOB14			_T("EQStoredJobReport14")
+#define STEP_EQ_STORED_JOB15			_T("EQStoredJobReport15")
+
 
 
 /* Step ID */
@@ -151,6 +216,7 @@
 #define STEP_ID_VCR_ENABLE_CMD_REPLY			0x554
 #define STEP_ID_EQMODE_CHANGE_CMD_REPLY			0x555
 #define STEP_ID_MASTER_RECIPE_LIST_CMD_REPLY	0x556
+#define STEP_ID_RECIPE_PARAMETER_CMD_REPLY		0x557
 #define STEP_ID_EQMODE_CHANGED					0x560
 #define STEP_ID_EQSTATUS_CHANGED				0x561
 #define STEP_ID_EQALARM1						0x562
@@ -163,10 +229,55 @@
 #define STEP_ID_CIM_MSG_CONFIRM_REPORT			0x569
 #define STEP_ID_VCR1_EVENT_REPORT				0x56A
 #define STEP_ID_MASTER_RECIPE_LIST_REPORT		0x56B
+#define STEP_ID_RECIPE_PARAMETER_REPORT			0x56C
 #define STEP_ID_RECIVE_JOB_UPS1					0x580
 #define STEP_ID_RECIVE_JOB_UPS2					0x581
+#define STEP_ID_RECIVE_JOB_UPS3					0x582
+#define STEP_ID_RECIVE_JOB_UPS4					0x583
+#define STEP_ID_RECIVE_JOB_UPS5					0x584
+#define STEP_ID_RECIVE_JOB_UPS6					0x585
+#define STEP_ID_RECIVE_JOB_UPS7					0x586
+#define STEP_ID_RECIVE_JOB_UPS8					0x587
+#define STEP_ID_RECIVE_JOB_UPS9					0x588
 #define STEP_ID_SENT_OUT_JOB_DOWNS1				0x590
 #define STEP_ID_SENT_OUT_JOB_DOWNS2				0x591
+#define STEP_ID_SENT_OUT_JOB_DOWNS3				0x592
+#define STEP_ID_SENT_OUT_JOB_DOWNS4				0x593
+#define STEP_ID_SENT_OUT_JOB_DOWNS5				0x594
+#define STEP_ID_SENT_OUT_JOB_DOWNS6				0x595
+#define STEP_ID_SENT_OUT_JOB_DOWNS7				0x596
+#define STEP_ID_SENT_OUT_JOB_DOWNS8				0x597
+#define STEP_ID_SENT_OUT_JOB_DOWNS9				0x598
+#define STEP_ID_STORE_JOB_REPORT1				0x5A0
+#define STEP_ID_STORE_JOB_REPORT2				0x5A1
+#define STEP_ID_STORE_JOB_REPORT3				0x5A2
+#define STEP_ID_STORE_JOB_REPORT4				0x5A3
+#define STEP_ID_STORE_JOB_REPORT5				0x5A4
+#define STEP_ID_STORE_JOB_REPORT6				0x5A5
+#define STEP_ID_STORE_JOB_REPORT7				0x5A6
+#define STEP_ID_STORE_JOB_REPORT8				0x5A7
+#define STEP_ID_STORE_JOB_REPORT9				0x5A8
+#define STEP_ID_STORE_JOB_REPORT10				0x5A9
+#define STEP_ID_STORE_JOB_REPORT11				0x5AA
+#define STEP_ID_STORE_JOB_REPORT12				0x5AB
+#define STEP_ID_STORE_JOB_REPORT13				0x5AC
+#define STEP_ID_STORE_JOB_REPORT14				0x5AD
+#define STEP_ID_STORE_JOB_REPORT15				0x5AE
+#define STEP_ID_FETCHED_OUT_JOB_REPORT1			0x5AF
+#define STEP_ID_FETCHED_OUT_JOB_REPORT2			0x5B0
+#define STEP_ID_FETCHED_OUT_JOB_REPORT3			0x5B1
+#define STEP_ID_FETCHED_OUT_JOB_REPORT4			0x5B2
+#define STEP_ID_FETCHED_OUT_JOB_REPORT5			0x5B3
+#define STEP_ID_FETCHED_OUT_JOB_REPORT6			0x5B4
+#define STEP_ID_FETCHED_OUT_JOB_REPORT7			0x5B5
+#define STEP_ID_FETCHED_OUT_JOB_REPORT8			0x5B6
+#define STEP_ID_FETCHED_OUT_JOB_REPORT9			0x5B7
+#define STEP_ID_FETCHED_OUT_JOB_REPORT10		0x5B8
+#define STEP_ID_FETCHED_OUT_JOB_REPORT11		0x5B9
+#define STEP_ID_FETCHED_OUT_JOB_REPORT12		0x5BA
+#define STEP_ID_FETCHED_OUT_JOB_REPORT13		0x5BB
+#define STEP_ID_FETCHED_OUT_JOB_REPORT14		0x5BC
+#define STEP_ID_FETCHED_OUT_JOB_REPORT15		0x5BD
 #define STEP_ID_PORT1_TYPE_CHANGE				0x600
 #define STEP_ID_PORT2_TYPE_CHANGE				0x601
 #define STEP_ID_PORT3_TYPE_CHANGE				0x602
@@ -298,3 +409,16 @@
 #define ORDER_BY_GROUP_COUNT_NG				7
 
 
+/*
+ Report type
+ 1: Create
+ 2: Modify
+ 3: Delete
+ 4: Request from EAS
+ */
+#define RT_CREATE				1
+#define RT_MODIFY				2
+#define RT_DELETE				3
+#define RT_REQUEST_FROM_EAS		4
+
+
diff --git a/SourceCode/Bond/Servo/EqsGraphWnd.cpp b/SourceCode/Bond/Servo/EqsGraphWnd.cpp
index 466ca8e..9aa534d 100644
--- a/SourceCode/Bond/Servo/EqsGraphWnd.cpp
+++ b/SourceCode/Bond/Servo/EqsGraphWnd.cpp
@@ -1911,10 +1911,12 @@
 	HBRUSH hbrItemBackground[2];
 	HBRUSH hbrItemFrame[2];
 	HBRUSH hbrPinBackground[3];
+	HBRUSH hbrIndicator;
 	hbrItemBackground[0] = CreateSolidBrush(m_crItemBackground[0]);
 	hbrItemBackground[1] = CreateSolidBrush(m_crItemBackground[1]);
 	hbrItemFrame[0] = CreateSolidBrush(m_crItemFrame[0]);
 	hbrItemFrame[1] = CreateSolidBrush(m_crItemFrame[1]);
+	hbrIndicator = CreateSolidBrush(RGB(34, 177, 76));
 	for (int i = 0; i < 3; i++) {
 		hbrPinBackground[i] = CreateSolidBrush(m_crPinBkgnd[i]);
 	}
@@ -1960,6 +1962,21 @@
 			HFONT hFontOld = (HFONT)::SelectObject(hMemDC, m_hFontName);
 			::SetTextColor(hMemDC, pItem->bHighlight ? m_crItemNameText[1] : m_crItemNameText[0]);
 			::DrawText(hMemDC, pItem->text, (int)strlen(pItem->text), &rcItem, DT_CENTER | DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS);
+
+			
+			// 添加一个小绿点指示器
+			if(pItem->bShowIndicator[0]){
+				RECT rcIndicator;
+				rcIndicator.left = rcItem.left + 5;
+				rcIndicator.top = rcItem.top + 5;
+				rcIndicator.right = rcIndicator.left + 12;
+				rcIndicator.bottom = rcIndicator.top + 12;
+				HRGN hRgn = CreateRoundRectRgn(rcIndicator.left, rcIndicator.top, rcIndicator.right, rcIndicator.bottom, 2, 2);
+				::FillRgn(hMemDC, hRgn, hbrIndicator);
+				::FrameRgn(hMemDC, hRgn, hbrItemFrame[0], 1, 1);
+				::DeleteObject(hRgn);
+			}
+
 
 			if (pItem->nShowType != ITEM_SMALL) {
 				RECT rcId = rcItem;
@@ -2074,6 +2091,7 @@
 		::DeleteObject(hbrItemBackground[1]);
 		::DeleteObject(hbrItemFrame[0]);
 		::DeleteObject(hbrItemFrame[1]);
+		::DeleteObject(hbrIndicator);		
 	}
 
 
@@ -2390,6 +2408,15 @@
 	SetTimer(m_hWnd, TIMER_ANIMATION_RECT, uElpase, NULL);
 }
 
+void CEqsGraphWnd::ShowItemIndicator(DWORD_PTR dwItemData, BOOL bShow)
+{
+	EQITEM* pItem = GetItem(dwItemData);
+	if (pItem != nullptr) {
+		pItem->bShowIndicator[0] = bShow;
+		::InvalidateRect(m_hWnd, nullptr, TRUE);
+	}
+}
+
 double CEqsGraphWnd::PointToSegDist(double x, double y, double x1, double y1, double x2, double y2)
 {
 	double cross = (x2 - x1) * (x - x1) + (y2 - y1) * (y - y1);
diff --git a/SourceCode/Bond/Servo/EqsGraphWnd.h b/SourceCode/Bond/Servo/EqsGraphWnd.h
index 89b56f5..c54d768 100644
--- a/SourceCode/Bond/Servo/EqsGraphWnd.h
+++ b/SourceCode/Bond/Servo/EqsGraphWnd.h
@@ -54,6 +54,7 @@
 	DWORD_PTR pInPins;
 	DWORD_PTR pOutPins;
 	int nFlashFlag;
+	BOOL bShowIndicator[2];
 } EQITEM;
 
 typedef struct tagPIN
@@ -143,6 +144,7 @@
 	void SetItemPos(EQITEM* pItem, int x, int y);
 	void FlashItem(EQITEM* pItem);
 	void AnimationItem(EQITEM*pItem);
+	void ShowItemIndicator(DWORD_PTR dwItemData, BOOL bShow);
 
 private:
 	void Init();
diff --git a/SourceCode/Bond/Servo/Model.cpp b/SourceCode/Bond/Servo/Model.cpp
index 5dab65a..95183ef 100644
--- a/SourceCode/Bond/Servo/Model.cpp
+++ b/SourceCode/Bond/Servo/Model.cpp
@@ -19,6 +19,12 @@
 
 IObservable* CModel::getObservable()
 {
+	if (m_pObservable == nullptr) {
+		m_pObservable = RX_AllocaObservable([&](IObservableEmitter* e) -> void {
+			m_pObservableEmitter = e;			// 保存发射器
+		});
+	}
+
 	return m_pObservable;
 }
 
@@ -53,11 +59,6 @@
 	CLog::GetLog()->SetLogsDir(strLogDir);
 	CLog::GetLog()->SetEquipmentId((LPTSTR)(LPCTSTR)strUnitId);
 	LOGI("\r\n\r\n~~~ Prog Start! ~~~");
-
-
-	m_pObservable = RX_AllocaObservable([&](IObservableEmitter* e) -> void {
-		m_pObservableEmitter = e;			// 保存发射器
-	});
 
 
 	SECSListener listener;
@@ -152,6 +153,10 @@
 	masterListener.onEqVcrEventReport = [&](void* pMaster, SERVO::CEquipment* pEquipment, SERVO::CVcrEventReport* pReport) {
 		LOGE("<CModel>onEqVcrEventReport.");
 	};
+	masterListener.onEqDataChanged = [&](void* pMaster, SERVO::CEquipment* pEquipment, int code) {
+		LOGE("<CModel>onEqDataChanged.");
+		notifyPtr(RX_CODE_EQ_DATA_CHANGED, pEquipment);
+	};
 	m_master.setListener(masterListener);
 
 
diff --git a/SourceCode/Bond/Servo/AlarmDlg.cpp b/SourceCode/Bond/Servo/PageAlarm.cpp
similarity index 86%
rename from SourceCode/Bond/Servo/AlarmDlg.cpp
rename to SourceCode/Bond/Servo/PageAlarm.cpp
index 3ca1d9c..90a1a74 100644
--- a/SourceCode/Bond/Servo/AlarmDlg.cpp
+++ b/SourceCode/Bond/Servo/PageAlarm.cpp
@@ -4,7 +4,7 @@
 #include "stdafx.h"
 #include "Servo.h"
 #include "afxdialogex.h"
-#include "AlarmDlg.h"
+#include "PageAlarm.h"
 #include "AlarmManager.h"
 #include "Common.h"
 #include <iomanip>
@@ -12,11 +12,11 @@
 #define PAGE_SIZE						100
 #define PAGE_BACKGROUND_COLOR			RGB(252, 252, 255)
 
-// CAlarmDlg 瀵硅瘽妗�
+// CPageAlarm 瀵硅瘽妗�
 
-IMPLEMENT_DYNAMIC(CAlarmDlg, CDialogEx)
+IMPLEMENT_DYNAMIC(CPageAlarm, CDialogEx)
 
-CAlarmDlg::CAlarmDlg(CWnd* pParent /*=nullptr*/)
+CPageAlarm::CPageAlarm(CWnd* pParent /*=nullptr*/)
 	: CDialogEx(IDD_DIALOG_ALARM, pParent)
 {
 	m_crBkgnd = PAGE_BACKGROUND_COLOR;
@@ -37,11 +37,11 @@
 	m_szTimeEnd[0] = '\0';
 }
 
-CAlarmDlg::~CAlarmDlg()
+CPageAlarm::~CPageAlarm()
 {
 }
 
-void CAlarmDlg::InitRxWindow()
+void CPageAlarm::InitRxWindow()
 {
 	/* code */
 	// 璁㈤槄鏁版嵁
@@ -73,7 +73,7 @@
 	}
 }
 
-void CAlarmDlg::Resize()
+void CPageAlarm::Resize()
 {
 	CWnd* pItem;
 	CRect rcClient;
@@ -83,14 +83,14 @@
 	pItem->MoveWindow(12, 58, rcClient.Width() - 24, rcClient.Height() - 64);
 }
 
-void CAlarmDlg::LoadAlarms()
+void CPageAlarm::LoadAlarms()
 {
 	// 鍒锋柊鍘嗗彶鎶ヨ鏁版嵁
 	m_nCurPage = 1;
 	UpdatePageData();
 }
 
-void CAlarmDlg::UpdatePageData()
+void CPageAlarm::UpdatePageData()
 {
 	// 鏍规嵁杩囨护鏉′欢鍔犺浇鏁版嵁锛屾彁渚涙弿杩板拰鏃堕棿鑼冨洿鏌ヨ
 	auto vecData = AlarmManager::getInstance().getFilteredAlarms("", "", m_strDeviceName, m_strUnitName, m_strKeyword, m_szTimeStart, m_szTimeEnd, m_nCurPage, PAGE_SIZE);
@@ -103,7 +103,7 @@
 	UpdatePageControls();
 }
 
-void CAlarmDlg::UpdatePageControls()
+void CPageAlarm::UpdatePageControls()
 {
 	// 鏇存柊鍒嗛〉淇℃伅
 	CString strPage;
@@ -115,7 +115,11 @@
 	GetDlgItem(IDC_BUTTON_NEXT_PAGE)->EnableWindow(m_nCurPage < m_nTotalPages);
 }
 
+<<<<<<< HEAD:SourceCode/Bond/Servo/AlarmDlg.cpp
 void CAlarmDlg::FillDataToListCtrl(CListCtrl* pListCtrl, const std::vector<AlarmData>& vecData)
+=======
+void CPageAlarm::FillDataToListCtrl(CListCtrl* pListCtrl, const std::vector<AlarmData>& vecData)
+>>>>>>> clh:SourceCode/Bond/Servo/PageAlarm.cpp
 {
 	if (pListCtrl == nullptr || pListCtrl->m_hWnd == nullptr) {
 		return;
@@ -135,7 +139,11 @@
 }
 
 static char* pszAlarmLevel[] = { "Warning", "Error" };
+<<<<<<< HEAD:SourceCode/Bond/Servo/AlarmDlg.cpp
 void CAlarmDlg::InsertAlarmData(CListCtrl* pListCtrl, const AlarmData& alarmData)
+=======
+void CPageAlarm::InsertAlarmData(CListCtrl* pListCtrl, const AlarmData& alarmData)
+>>>>>>> clh:SourceCode/Bond/Servo/PageAlarm.cpp
 {
 	if (pListCtrl == nullptr || pListCtrl->m_hWnd == nullptr) {
 		return;
@@ -160,7 +168,7 @@
 	pListCtrl->SetItemText(nNewItem, 7, alarmData.strDescription.c_str());              // 鎻忚堪
 }
 
-std::string CAlarmDlg::getCurrentTimeString()
+std::string CPageAlarm::getCurrentTimeString()
 {
 	auto now = std::chrono::system_clock::now();
 	auto time_t_now = std::chrono::system_clock::to_time_t(now);
@@ -173,7 +181,7 @@
 	return ss.str();
 }
 
-void CAlarmDlg::DoDataExchange(CDataExchange* pDX)
+void CPageAlarm::DoDataExchange(CDataExchange* pDX)
 {
 	DDX_Control(pDX, IDC_DATETIMEPICKER_START, m_dateTimeStart);
 	DDX_Control(pDX, IDC_DATETIMEPICKER_END, m_dateTimeEnd);
@@ -182,22 +190,30 @@
 }
 
 
-BEGIN_MESSAGE_MAP(CAlarmDlg, CDialogEx)
+BEGIN_MESSAGE_MAP(CPageAlarm, CDialogEx)
 	ON_WM_CTLCOLOR()
 	ON_WM_DESTROY()
 	ON_WM_CLOSE()
 	ON_WM_SIZE()
+<<<<<<< HEAD:SourceCode/Bond/Servo/AlarmDlg.cpp
 	ON_WM_TIMER()
 	ON_CBN_SELCHANGE(IDC_COMBO_DATETIME, &CAlarmDlg::OnCbnSelchangeComboDatetime)
 	ON_BN_CLICKED(IDC_BUTTON_SEARCH, &CAlarmDlg::OnBnClickedButtonSearch)
 	ON_BN_CLICKED(IDC_BUTTON_EXPORT, &CAlarmDlg::OnBnClickedButtonExport)
 	ON_BN_CLICKED(IDC_BUTTON_PREV_PAGE, &CAlarmDlg::OnBnClickedButtonPrevPage)
 	ON_BN_CLICKED(IDC_BUTTON_NEXT_PAGE, &CAlarmDlg::OnBnClickedButtonNextPage)
+=======
+	ON_CBN_SELCHANGE(IDC_COMBO_DATETIME, &CPageAlarm::OnCbnSelchangeComboDatetime)
+	ON_BN_CLICKED(IDC_BUTTON_SEARCH, &CPageAlarm::OnBnClickedButtonSearch)
+	ON_BN_CLICKED(IDC_BUTTON_EXPORT, &CPageAlarm::OnBnClickedButtonExport)
+	ON_BN_CLICKED(IDC_BUTTON_PREV_PAGE, &CPageAlarm::OnBnClickedButtonPrevPage)
+	ON_BN_CLICKED(IDC_BUTTON_NEXT_PAGE, &CPageAlarm::OnBnClickedButtonNextPage)
+>>>>>>> clh:SourceCode/Bond/Servo/PageAlarm.cpp
 END_MESSAGE_MAP()
 
 
 // CAlarmDlg 娑堟伅澶勭悊绋嬪簭
-BOOL CAlarmDlg::OnInitDialog()
+BOOL CPageAlarm::OnInitDialog()
 {
 	CDialogEx::OnInitDialog();
 	SetTimer(1, 3000, nullptr);
@@ -259,7 +275,7 @@
 	// 寮傚父: OCX 灞炴�ч〉搴旇繑鍥� FALSE
 }
 
-HBRUSH CAlarmDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
+HBRUSH CPageAlarm::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
 {
 	HBRUSH hbr = CDialogEx::OnCtlColor(pDC, pWnd, nCtlColor);
 
@@ -274,7 +290,7 @@
 	return m_hbrBkgnd;
 }
 
-void CAlarmDlg::OnDestroy()
+void CPageAlarm::OnDestroy()
 {
 	CDialogEx::OnDestroy();
 
@@ -302,19 +318,20 @@
 	}
 }
 
-void CAlarmDlg::OnClose()
+void CPageAlarm::OnClose()
 {
 	ShowWindow(SW_HIDE);
 	GetParent()->PostMessage(ID_MSG_ALARMDLG_HIDE, 0, 0);
 }
 
-void CAlarmDlg::OnSize(UINT nType, int cx, int cy)
+void CPageAlarm::OnSize(UINT nType, int cx, int cy)
 {
 	CDialogEx::OnSize(nType, cx, cy);
 	if (GetDlgItem(IDC_LIST_ALARM) == nullptr) return;
 	Resize();
 }
 
+<<<<<<< HEAD:SourceCode/Bond/Servo/AlarmDlg.cpp
 void CAlarmDlg::OnTimer(UINT_PTR nIDEvent)
 {
 	if (1 == nIDEvent) {
@@ -324,6 +341,9 @@
 }
 
 void CAlarmDlg::OnCbnSelchangeComboDatetime()
+=======
+void CPageAlarm::OnCbnSelchangeComboDatetime()
+>>>>>>> clh:SourceCode/Bond/Servo/PageAlarm.cpp
 {
 	CComboBox* pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_DATETIME);
 	int nIndex = pComboBox->GetCurSel();
@@ -332,7 +352,7 @@
 	m_dateTimeEnd.EnableWindow(nIndex == nCount - 1);
 }
 
-void CAlarmDlg::OnBnClickedButtonSearch()
+void CPageAlarm::OnBnClickedButtonSearch()
 {
 	// 鑾峰彇鍏抽敭瀛�
 	CString cstrKeyword;
@@ -392,7 +412,7 @@
 	UpdatePageData();  // 璋冪敤鍒嗛〉鏇存柊鍑芥暟
 }
 
-void CAlarmDlg::OnBnClickedButtonExport()
+void CPageAlarm::OnBnClickedButtonExport()
 {
 	CFileDialog fileDialog(FALSE, "csv", "", OFN_HIDEREADONLY, "csv.files(*.csv)|*.csv||");
 	if (fileDialog.DoModal() != IDOK) {
@@ -452,14 +472,14 @@
 	file.Close();
 }
 
-void CAlarmDlg::OnBnClickedButtonPrevPage()
+void CPageAlarm::OnBnClickedButtonPrevPage()
 {
 	// 鐐瑰嚮涓婁竴椤�
 	m_nCurPage--;
 	UpdatePageData();  // 璋冪敤鍒嗛〉鏇存柊鍑芥暟
 }
 
-void CAlarmDlg::OnBnClickedButtonNextPage()
+void CPageAlarm::OnBnClickedButtonNextPage()
 {
 	// 鐐瑰嚮涓嬩竴椤�
 	m_nCurPage++;
diff --git a/SourceCode/Bond/Servo/AlarmDlg.h b/SourceCode/Bond/Servo/PageAlarm.h
similarity index 89%
rename from SourceCode/Bond/Servo/AlarmDlg.h
rename to SourceCode/Bond/Servo/PageAlarm.h
index 0aae170..783ce29 100644
--- a/SourceCode/Bond/Servo/AlarmDlg.h
+++ b/SourceCode/Bond/Servo/PageAlarm.h
@@ -6,15 +6,15 @@
 
 #define ID_MSG_ALARMDLG_HIDE		WM_USER + 1024
 
-// CAlarmDlg 瀵硅瘽妗�
+// CPageAlarm 瀵硅瘽妗�
 
-class CAlarmDlg : public CDialogEx
+class CPageAlarm : public CDialogEx
 {
-	DECLARE_DYNAMIC(CAlarmDlg)
+	DECLARE_DYNAMIC(CPageAlarm)
 
 public:
-	CAlarmDlg(CWnd* pParent = nullptr);   // 鏍囧噯鏋勯�犲嚱鏁�
-	virtual ~CAlarmDlg();
+	CPageAlarm(CWnd* pParent = nullptr);   // 鏍囧噯鏋勯�犲嚱鏁�
+	virtual ~CPageAlarm();
 
 private:
 	void InitRxWindow();
diff --git a/SourceCode/Bond/Servo/LogDlg.cpp b/SourceCode/Bond/Servo/PageLog.cpp
similarity index 85%
rename from SourceCode/Bond/Servo/LogDlg.cpp
rename to SourceCode/Bond/Servo/PageLog.cpp
index 74fe0f2..7af3e51 100644
--- a/SourceCode/Bond/Servo/LogDlg.cpp
+++ b/SourceCode/Bond/Servo/PageLog.cpp
@@ -3,17 +3,17 @@
 
 #include "stdafx.h"
 #include "Servo.h"
-#include "LogDlg.h"
+#include "PageLog.h"
 #include "afxdialogex.h"
 #include "Common.h"
 #include <regex>
 
 
-// CLogDlg 对话框
+// CPageLog 对话框
 
-IMPLEMENT_DYNAMIC(CLogDlg, CDialogEx)
+IMPLEMENT_DYNAMIC(CPageLog, CDialogEx)
 
-CLogDlg::CLogDlg(CWnd* pParent /*=NULL*/)
+CPageLog::CPageLog(CWnd* pParent /*=NULL*/)
 	: CDialogEx(IDD_DIALOG_LOG, pParent)
 {
 	m_crBkgnd = LOGDLG_BACKGROUND_COLOR;
@@ -24,11 +24,11 @@
 	m_bIncludeRegex = FALSE;
 }
 
-CLogDlg::~CLogDlg()
+CPageLog::~CPageLog()
 {
 }
 
-void CLogDlg::DoDataExchange(CDataExchange* pDX)
+void CPageLog::DoDataExchange(CDataExchange* pDX)
 {
 	CDialogEx::DoDataExchange(pDX);
 	DDX_Control(pDX, IDC_BUTTON_LEVEL, m_btnLevel);
@@ -37,22 +37,22 @@
 }
 
 
-BEGIN_MESSAGE_MAP(CLogDlg, CDialogEx)
+BEGIN_MESSAGE_MAP(CPageLog, CDialogEx)
 	ON_WM_CTLCOLOR()
 	ON_WM_SIZE()
 	ON_WM_DESTROY()
 	ON_WM_CLOSE()
-	ON_NOTIFY(BLBUTTON_MENU_ITEM_CLICKED, IDC_BUTTON_LEVEL, &CLogDlg::OnButtonLevelMenuClicked)
-	ON_NOTIFY(BLBUTTON_MENU_ITEM_CLICKED, IDC_BUTTON_INCLUDE, &CLogDlg::OnButtonIncludeMenuClicked)
-	ON_EN_CHANGE(IDC_EDIT_INCLUDE, &CLogDlg::OnEnChangeEditInclude)
-	ON_BN_CLICKED(IDC_CHECK_REGEX, &CLogDlg::OnBnClickedCheckRegex)
+	ON_NOTIFY(BLBUTTON_MENU_ITEM_CLICKED, IDC_BUTTON_LEVEL, &CPageLog::OnButtonLevelMenuClicked)
+	ON_NOTIFY(BLBUTTON_MENU_ITEM_CLICKED, IDC_BUTTON_INCLUDE, &CPageLog::OnButtonIncludeMenuClicked)
+	ON_EN_CHANGE(IDC_EDIT_INCLUDE, &CPageLog::OnEnChangeEditInclude)
+	ON_BN_CLICKED(IDC_CHECK_REGEX, &CPageLog::OnBnClickedCheckRegex)
 END_MESSAGE_MAP()
 
 
 // CLogDlg 消息处理程序
 
 
-void CLogDlg::InitRxWindow()
+void CPageLog::InitRxWindow()
 {
 	/* code */
 	// 订阅数据
@@ -102,9 +102,10 @@
 	}
 }
 
-BOOL CLogDlg::OnInitDialog()
+BOOL CPageLog::OnInitDialog()
 {
 	CDialogEx::OnInitDialog();
+	InitRxWindow();
 
 
 	// 缓存
@@ -158,6 +159,7 @@
 	m_logEdit.SetLimitText(-1);
 
 
+<<<<<<< HEAD:SourceCode/Bond/Servo/LogDlg.cpp
 	std::thread([this]() {
 		constexpr int nMaxWaitMs = 3000;  // 最多等待 3 秒
 		constexpr int nStepMs = 1;		  // 每次等待 1ms
@@ -177,6 +179,8 @@
 	}).detach();
 
 
+=======
+>>>>>>> clh:SourceCode/Bond/Servo/PageLog.cpp
 	Resize();
 
 
@@ -184,21 +188,21 @@
 				  // 异常: OCX 属性页应返回 FALSE
 }
 
-void CLogDlg::OnSize(UINT nType, int cx, int cy)
+void CPageLog::OnSize(UINT nType, int cx, int cy)
 {
 	CDialogEx::OnSize(nType, cx, cy);
 	if (GetDlgItem(IDC_EDIT_LOG) == nullptr) return;
 	Resize();
 }
 
-void CLogDlg::Resize()
+void CPageLog::Resize()
 {
 	int x, y, y2, temp;
 	CRect rcClient, rcItem;
 	CWnd* pItem;
 	GetClientRect(&rcClient);
 
-	y = 0;
+	y = 12;
 	x = 8;
 	pItem = GetDlgItem(IDC_BUTTON_LEVEL);
 	pItem->GetWindowRect(&rcItem);
@@ -231,7 +235,7 @@
 	pItem->MoveWindow(x, y2, rcClient.Width() - 16, rcClient.Height() - 5 - y2);
 }
 
-void CLogDlg::OnDestroy()
+void CPageLog::OnDestroy()
 {
 	CDialogEx::OnDestroy();
 
@@ -259,7 +263,7 @@
 	}
 }
 
-HBRUSH CLogDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
+HBRUSH CPageLog::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
 {
 	HBRUSH hbr = CDialogEx::OnCtlColor(pDC, pWnd, nCtlColor);
 
@@ -274,13 +278,13 @@
 	return m_hbrBkgnd;
 }
 
-void CLogDlg::OnClose()
+void CPageLog::OnClose()
 {
 	ShowWindow(SW_HIDE);
 	GetParent()->PostMessage(ID_MSG_LOGDLG_HIDE, 0, 0);
 }
 
-BOOL CLogDlg::PreTranslateMessage(MSG* pMsg)
+BOOL CPageLog::PreTranslateMessage(MSG* pMsg)
 {
 	if (pMsg->wParam == VK_RETURN || pMsg->wParam == VK_ESCAPE) {
 		return TRUE;
@@ -289,7 +293,7 @@
 	return CDialogEx::PreTranslateMessage(pMsg);
 }
 
-void CLogDlg::AppendLog(int level, const char* pszText)
+void CPageLog::AppendLog(int level, const char* pszText)
 {
 	if (!::IsWindow(m_logEdit.m_hWnd)) {
 		return;
@@ -297,7 +301,7 @@
 	m_logEdit.AppendText(pszText);
 }
 
-void CLogDlg::OnButtonLevelMenuClicked(NMHDR* pNMHDR, LRESULT* pResult)
+void CPageLog::OnButtonLevelMenuClicked(NMHDR* pNMHDR, LRESULT* pResult)
 {
 	BLBUTTON_NMHDR* pblbNmhdr = reinterpret_cast<BLBUTTON_NMHDR*>(pNMHDR);
 	m_nLevel = (int)pblbNmhdr->dwData;
@@ -307,7 +311,7 @@
 	*pResult = 0;
 }
 
-void CLogDlg::OnButtonIncludeMenuClicked(NMHDR* pNMHDR, LRESULT* pResult)
+void CPageLog::OnButtonIncludeMenuClicked(NMHDR* pNMHDR, LRESULT* pResult)
 {
 	BLBUTTON_NMHDR* pblbNmhdr = reinterpret_cast<BLBUTTON_NMHDR*>(pNMHDR);
 	int position = (int)pblbNmhdr->dwData;
@@ -323,13 +327,13 @@
 	*pResult = 0;
 }
 
-void CLogDlg::OnEnChangeEditInclude()
+void CPageLog::OnEnChangeEditInclude()
 {
 	GetDlgItemText(IDC_EDIT_INCLUDE, m_strIncludeText);
 	theApp.m_model.m_configuration.setLogcatIncludeText(m_strIncludeText);
 }
 
-void CLogDlg::OnBnClickedCheckRegex()
+void CPageLog::OnBnClickedCheckRegex()
 {
 	CButton* pCheckBox = (CButton*)GetDlgItem(IDC_CHECK_REGEX);
 	m_bIncludeRegex = pCheckBox->GetCheck();
diff --git a/SourceCode/Bond/Servo/LogDlg.h b/SourceCode/Bond/Servo/PageLog.h
similarity index 88%
rename from SourceCode/Bond/Servo/LogDlg.h
rename to SourceCode/Bond/Servo/PageLog.h
index 29acf5a..391f64d 100644
--- a/SourceCode/Bond/Servo/LogDlg.h
+++ b/SourceCode/Bond/Servo/PageLog.h
@@ -7,15 +7,15 @@
 
 #define ID_MSG_LOGDLG_HIDE		WM_USER + 1023
 
-// CLogDlg 对话框
+// CPageLog 对话框
 
-class CLogDlg : public CDialogEx
+class CPageLog : public CDialogEx
 {
-	DECLARE_DYNAMIC(CLogDlg)
+	DECLARE_DYNAMIC(CPageLog)
 
 public:
-	CLogDlg(CWnd* pParent = NULL);   // 标准构造函数
-	virtual ~CLogDlg();
+	CPageLog(CWnd* pParent = NULL);   // 标准构造函数
+	virtual ~CPageLog();
 
 
 private:
diff --git a/SourceCode/Bond/Servo/ProductionLogDlg.cpp b/SourceCode/Bond/Servo/ProductionLogDlg.cpp
index ee5d364..ef8546f 100644
--- a/SourceCode/Bond/Servo/ProductionLogDlg.cpp
+++ b/SourceCode/Bond/Servo/ProductionLogDlg.cpp
@@ -8,11 +8,19 @@
 #include "Common.h"
 #include <iomanip>
 
+<<<<<<< HEAD
 //#define PAGE_SIZE						100
 //#define PAGE_BACKGROUND_COLOR			RGB(252, 252, 255)
 //
 //// CProductionLogDlg 瀵硅瘽妗�
 //
+=======
+#define PAGE_SIZE						100
+#define PAGE_BACKGROUND_COLOR			RGB(252, 252, 255)
+
+// CProductionLogDlg 瀵硅瘽妗�
+
+>>>>>>> clh
 //IMPLEMENT_DYNAMIC(CProductionLogDlg, CDialogEx)
 //
 //CProductionLogDlg::CProductionLogDlg(CWnd* pParent /*=nullptr*/)
@@ -38,7 +46,11 @@
 //	m_szTimeStart[0] = '\0';
 //	m_szTimeEnd[0] = '\0';
 //}
+<<<<<<< HEAD
 //
+=======
+
+>>>>>>> clh
 //CProductionLogDlg::~CProductionLogDlg()
 //{
 //}
@@ -69,6 +81,7 @@
 //		theApp.m_model.getObservable()->observeOn(pRxWindows->mainThread())->subscribe(m_pObserver);
 //	}
 //}
+<<<<<<< HEAD
 //
 //void CProductionLogDlg::Resize()
 //{
@@ -461,4 +474,401 @@
 //	// 鐐瑰嚮涓嬩竴椤�
 //	m_nCurPage++;
 //	UpdatePageData();  // 璋冪敤鍒嗛〉鏇存柊鍑芥暟
-//}
\ No newline at end of file
+//}
+=======
+
+/*
+void CProductionLogDlg::Resize()
+{
+	CRect rcClient;
+	GetClientRect(&rcClient);
+
+	m_listCtrl.MoveWindow(12, 58, rcClient.Width() - 24, rcClient.Height() - 64);
+}
+
+void CProductionLogDlg::UpdatePageData()
+{
+	// 鏍规嵁杩囨护鏉′欢鍔犺浇鏁版嵁锛堟敮鎸佸垎椤点�佹ā绯婃煡璇€�佹椂闂磋寖鍥达級
+	auto vecData = ProductionLogManager::getInstance().getFilteredSteps(
+		m_strProductId,         // 浜у搧ID
+		m_strBatchNo,           // 鎵规鍙�
+		m_strDeviceId,          // 璁惧ID
+		m_strOperatorName,      // 鎿嶄綔鍛�
+		m_strStatus,            // 鐘舵��
+		m_szTimeStart,          // 璧峰鏃堕棿
+		m_szTimeEnd,            // 缁撴潫鏃堕棿
+		m_nCurPage,             // 褰撳墠椤电爜
+		PAGE_SIZE               // 姣忛〉鏉℃暟
+	);
+
+	// 濉厖鏁版嵁鍒板垪琛ㄦ帶浠�
+	FillDataToListCtrl(&m_listCtrl, vecData);
+
+	// 鏇存柊鍒嗛〉鎺т欢
+	UpdatePageControls();
+}
+
+void CProductionLogDlg::UpdatePageControls()
+{
+	// 鏇存柊鍒嗛〉淇℃伅
+	CString strPage;
+	strPage.Format(_T("绗� %d 椤�"), m_nCurPage);
+	SetDlgItemText(IDC_LABEL_PAGE_NUMBER, strPage);
+
+	// 鍚敤/绂佺敤缈婚〉鎸夐挳
+	GetDlgItem(IDC_BUTTON_PREV_PAGE)->EnableWindow(m_nCurPage > 1);
+	GetDlgItem(IDC_BUTTON_NEXT_PAGE)->EnableWindow(m_nCurPage < m_nTotalPages);
+}
+
+void CProductionLogDlg::FillDataToListCtrl(CListCtrl* pListCtrl, const std::vector<ProductionStep>& vecSteps)
+{
+	if (pListCtrl == nullptr || pListCtrl->m_hWnd == nullptr) {
+		return;
+	}
+
+	// 娓呯┖褰撳墠CListCtrl涓殑鎵�鏈夐」
+	pListCtrl->DeleteAllItems();
+
+	// 閬嶅巻鏁版嵁骞舵彃鍏ュ埌CListCtrl涓�
+	for (const auto& step : vecSteps) {
+		InsertStepData(pListCtrl, step);
+	}
+
+	// 鑾峰彇鍒楁暟
+	int nColCount = pListCtrl->GetHeaderCtrl()->GetItemCount();
+	pListCtrl->SetColumnWidth(nColCount - 1, LVSCW_AUTOSIZE_USEHEADER);
+}
+
+void CProductionLogDlg::InsertStepData(CListCtrl* pListCtrl, const ProductionStep& step)
+{
+	if (pListCtrl == nullptr || pListCtrl->m_hWnd == nullptr) {
+		return;
+	}
+
+	int nRowCount = pListCtrl->GetItemCount();
+	if (nRowCount >= PAGE_SIZE) {
+		pListCtrl->DeleteItem(nRowCount - 1);
+	}
+
+	CString str;
+	int nNewItem = pListCtrl->InsertItem(0, _T(""));
+	str.Format(_T("%d"), step.nStepId);		  pListCtrl->SetItemText(nNewItem, 1, str);
+	pListCtrl->SetItemText(nNewItem, 2, step.strProductId.c_str());
+	pListCtrl->SetItemText(nNewItem, 3, step.strBatchNo.c_str());
+	str.Format(_T("%d"), step.nDeviceId);     pListCtrl->SetItemText(nNewItem, 4, str);
+	pListCtrl->SetItemText(nNewItem, 5, step.strOperator.c_str());
+	pListCtrl->SetItemText(nNewItem, 6, step.strStartTime.c_str());
+	pListCtrl->SetItemText(nNewItem, 7, step.strEndTime.c_str());
+	str.Format(_T("%d"), step.nYield);        pListCtrl->SetItemText(nNewItem, 8, str);
+	str.Format(_T("%d"), step.nGoodCount);    pListCtrl->SetItemText(nNewItem, 9, str);
+	str.Format(_T("%d"), step.nBadCount);     pListCtrl->SetItemText(nNewItem, 10, str);
+	pListCtrl->SetItemText(nNewItem, 11, step.strStatus.c_str());
+}
+
+std::string CProductionLogDlg::getCurrentTimeString()
+{
+	auto now = std::chrono::system_clock::now();
+	auto time_t_now = std::chrono::system_clock::to_time_t(now);
+
+	std::tm tm_now = {};
+	localtime_s(&tm_now, &time_t_now);
+
+	std::stringstream ss;
+	ss << std::put_time(&tm_now, "%Y-%m-%d %H:%M:%S");
+	return ss.str();
+}
+
+void CProductionLogDlg::DoDataExchange(CDataExchange* pDX)
+{
+	DDX_Control(pDX, IDC_DATETIMEPICKER_START, m_dateTimeStart);
+	DDX_Control(pDX, IDC_DATETIMEPICKER_END, m_dateTimeEnd);
+	DDX_Control(pDX, IDC_LIST_PRODUCTION_LOG, m_listCtrl);
+	CDialogEx::DoDataExchange(pDX);
+}
+
+BEGIN_MESSAGE_MAP(CProductionLogDlg, CDialogEx)
+	ON_WM_CTLCOLOR()
+	ON_WM_DESTROY()
+	ON_WM_CLOSE()
+	ON_WM_SIZE()
+	ON_CBN_SELCHANGE(IDC_COMBO_DATETIME, &CProductionLogDlg::OnCbnSelchangeComboDatetime)
+	ON_BN_CLICKED(IDC_BUTTON_SEARCH, &CProductionLogDlg::OnBnClickedButtonSearch)
+	ON_BN_CLICKED(IDC_BUTTON_EXPORT, &CProductionLogDlg::OnBnClickedButtonExport)
+	ON_BN_CLICKED(IDC_BUTTON_PREV_PAGE, &CProductionLogDlg::OnBnClickedButtonPrevPage)
+	ON_BN_CLICKED(IDC_BUTTON_NEXT_PAGE, &CProductionLogDlg::OnBnClickedButtonNextPage)
+END_MESSAGE_MAP()
+
+// CProductionLogDlg 娑堟伅澶勭悊绋嬪簭
+BOOL CProductionLogDlg::OnInitDialog()
+{
+	CDialogEx::OnInitDialog();
+	InitRxWindow();
+
+	// 鍒濆鍖栨椂闂磋寖鍥撮�夋嫨
+	CComboBox* pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_DATETIME);
+	pComboBox->AddString(_T("涓嶉檺"));
+	pComboBox->AddString(_T("浠婂ぉ"));
+	pComboBox->AddString(_T("涓冨ぉ鍐�"));
+	pComboBox->AddString(_T("鏈湀"));
+	pComboBox->AddString(_T("浠婂勾"));
+	pComboBox->AddString(_T("鑷畾涔�"));
+	pComboBox->SetCurSel(0);
+
+	m_dateTimeStart.EnableWindow(FALSE);
+	m_dateTimeEnd.EnableWindow(FALSE);
+
+	// 璇诲彇鍒楀閰嶇疆
+	CString strIniFile, strItem;
+	strIniFile.Format(_T("%s\\configuration.ini"), (LPCTSTR)theApp.m_strAppDir);
+	int width[12] = { 0, 60, 100, 100, 70, 100, 140, 140, 60, 60, 60, 80 };
+	for (int i = 0; i < 12; ++i) {
+		strItem.Format(_T("Col_%d_Width"), i);
+		width[i] = GetPrivateProfileInt("ProductionListCtrl", strItem, width[i], strIniFile);
+	}
+
+	// 鍒濆鍖栧垪琛ㄦ帶浠�
+	CListCtrl* pListCtrl = (CListCtrl*)GetDlgItem(IDC_LIST_PRODUCTION_LOG);
+	DWORD dwStyle = pListCtrl->GetExtendedStyle();
+	dwStyle |= LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES;
+	pListCtrl->SetExtendedStyle(dwStyle);
+
+	HIMAGELIST imageList = ImageList_Create(24, 24, ILC_COLOR24, 1, 1);
+	ListView_SetImageList(pListCtrl->GetSafeHwnd(), imageList, LVSIL_SMALL);
+
+	pListCtrl->InsertColumn(0, _T(""), LVCFMT_RIGHT, width[0]);
+	pListCtrl->InsertColumn(1, _T("姝ラID"), LVCFMT_LEFT, width[1]);
+	pListCtrl->InsertColumn(2, _T("浜у搧ID"), LVCFMT_LEFT, width[2]);
+	pListCtrl->InsertColumn(3, _T("鎵规鍙�"), LVCFMT_LEFT, width[3]);
+	pListCtrl->InsertColumn(4, _T("璁惧ID"), LVCFMT_LEFT, width[4]);
+	pListCtrl->InsertColumn(5, _T("鎿嶄綔鍛�"), LVCFMT_LEFT, width[5]);
+	pListCtrl->InsertColumn(6, _T("寮�濮嬫椂闂�"), LVCFMT_LEFT, width[6]);
+	pListCtrl->InsertColumn(7, _T("缁撴潫鏃堕棿"), LVCFMT_LEFT, width[7]);
+	pListCtrl->InsertColumn(8, _T("浜ч噺"), LVCFMT_LEFT, width[8]);
+	pListCtrl->InsertColumn(9, _T("鑹搧鏁�"), LVCFMT_LEFT, width[9]);
+	pListCtrl->InsertColumn(10, _T("涓嶈壇鍝佹暟"), LVCFMT_LEFT, width[10]);
+	pListCtrl->InsertColumn(11, _T("鐘舵��"), LVCFMT_LEFT, width[11]);
+
+	// 鍒濆鍖栧垎椤垫暟鎹�
+	int totalRecords = ProductionLogManager::getInstance().getTotalStepCount(
+		m_strProductId, m_strBatchNo, m_strDeviceId, m_strOperatorName,
+		m_strStatus, m_szTimeStart, m_szTimeEnd);
+	m_nTotalPages = (totalRecords + PAGE_SIZE - 1) / PAGE_SIZE;
+	m_nCurPage = 1;
+
+	Resize();
+	UpdatePageData();
+
+	return TRUE;  // return TRUE unless you set the focus to a control
+	// 寮傚父: OCX 灞炴�ч〉搴旇繑鍥� FALSE
+}
+
+HBRUSH CProductionLogDlg::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 CProductionLogDlg::OnDestroy()
+{
+	CDialogEx::OnDestroy();
+
+	// 淇濆瓨鍒楀
+	CString strIniFile, strItem, strTemp;
+	strIniFile.Format(_T("%s\\configuration.ini"), (LPCTSTR)theApp.m_strAppDir);
+	CHeaderCtrl* pHeader = m_listCtrl.GetHeaderCtrl();
+	for (int i = 0; i < pHeader->GetItemCount(); ++i) {
+		RECT rect;
+		pHeader->GetItemRect(i, &rect);
+		strItem.Format(_T("Col_%d_Width"), i);
+		strTemp.Format(_T("%d"), rect.right - rect.left);
+		WritePrivateProfileString("ProductionListCtrl", strItem, strTemp, strIniFile);
+	}
+
+	if (m_hbrBkgnd != nullptr) {
+		::DeleteObject(m_hbrBkgnd);
+	}
+
+	if (m_pObserver != NULL) {
+		m_pObserver->unsubscribe();
+		m_pObserver = NULL;
+	}
+}
+
+void CProductionLogDlg::OnClose()
+{
+	ShowWindow(SW_HIDE);
+	//GetParent()->PostMessage(ID_MSG_ALARMDLG_HIDE, 0, 0);
+	CDialogEx::OnClose();
+}
+
+void CProductionLogDlg::OnSize(UINT nType, int cx, int cy)
+{
+	CDialogEx::OnSize(nType, cx, cy);
+	if (GetDlgItem(IDC_LIST_PRODUCTION_LOG) == nullptr) return;
+	Resize();
+}
+
+void CProductionLogDlg::OnCbnSelchangeComboDatetime()
+{
+	CComboBox* pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_DATETIME);
+	int nIndex = pComboBox->GetCurSel();
+	int nCount = pComboBox->GetCount();
+	m_dateTimeStart.EnableWindow(nIndex == nCount - 1);
+	m_dateTimeEnd.EnableWindow(nIndex == nCount - 1);
+}
+
+void CProductionLogDlg::OnBnClickedButtonSearch()
+{
+	// 鑾峰彇鍏抽敭瀛�
+	CString cstrKeyword;
+	GetDlgItemText(IDC_EDIT_KEYWORD, cstrKeyword);
+	m_strKeyword = CT2A(cstrKeyword);
+
+	// 鑾峰彇鏃ユ湡
+	CComboBox* pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_DATETIME);
+	m_nDateTimeFlag = pComboBox->GetCurSel();
+	if (m_nDateTimeFlag == 0) {
+		memset(m_szTimeStart, 0, sizeof(m_szTimeStart));
+		memset(m_szTimeEnd, 0, sizeof(m_szTimeEnd));
+		m_szTimeStart[0] = '\0';
+		m_szTimeEnd[0] = '\0';
+	}
+	else {
+		CTime time = CTime::GetCurrentTime();
+		if (m_nDateTimeFlag == 1) {
+			// 浠婂ぉ
+			sprintf_s(m_szTimeStart, 64, "%d-%02d-%02d 00:00:00", time.GetYear(), time.GetMonth(), time.GetDay());
+			sprintf_s(m_szTimeEnd, 64, "%d-%02d-%02d 23:59:59", time.GetYear(), time.GetMonth(), time.GetDay());
+		}
+		else if (m_nDateTimeFlag == 2) {
+			// 7澶╁唴
+			CTime time2 = time - CTimeSpan(7, 0, 0, 0);
+			sprintf_s(m_szTimeStart, 64, "%d-%02d-%02d 00:00:00", time2.GetYear(), time2.GetMonth(), time2.GetDay());
+			sprintf_s(m_szTimeEnd, 64, "%d-%02d-%02d 23:59:59", time.GetYear(), time.GetMonth(), time.GetDay());
+		}
+		else if (m_nDateTimeFlag == 3) {
+			// 鏈湀
+			sprintf_s(m_szTimeStart, 64, "%d-%02d-01 00:00:00", time.GetYear(), time.GetMonth());
+			sprintf_s(m_szTimeEnd, 64, "%d-%02d-%02d 23:59:59", time.GetYear(), time.GetMonth(), time.GetDay());
+		}
+		else if (m_nDateTimeFlag == 4) {
+			// 浠婂勾
+			sprintf_s(m_szTimeStart, 64, "%d-01-01 00:00:00", time.GetYear());
+			sprintf_s(m_szTimeEnd, 64, "%d-12-31 23:59:59", time.GetYear());
+		}
+		else if (m_nDateTimeFlag == 5) {
+			// 鑷畾涔�
+			SYSTEMTIME t1, t2;
+			m_dateTimeStart.GetTime(&t1);
+			m_dateTimeEnd.GetTime(&t2);
+
+			sprintf_s(m_szTimeStart, 64, "%d-%02d-%02d %02d:%02d:%02d",
+				t1.wYear, t1.wMonth, t1.wDay, t1.wHour, t1.wMinute, t1.wSecond);
+			sprintf_s(m_szTimeEnd, 64, "%d-%02d-%02d %02d:%02d:%02d",
+				t2.wYear, t2.wMonth, t2.wDay, t2.wHour, t2.wMinute, t2.wSecond);
+		}
+	}
+
+	// 璁$畻鎬婚〉鏁�
+	int totalRecords = ProductionLogManager::getInstance().getTotalStepCount(
+		m_strProductId, m_strBatchNo, m_strDeviceId, m_strOperatorName,
+		m_strStatus, m_szTimeStart, m_szTimeEnd);
+	m_nTotalPages = (totalRecords + PAGE_SIZE - 1) / PAGE_SIZE;
+	m_nCurPage = 1;
+
+	UpdatePageData();  // 璋冪敤鍒嗛〉鏇存柊鍑芥暟
+}
+
+void CProductionLogDlg::OnBnClickedButtonExport()
+{
+	CFileDialog fileDialog(FALSE, "csv", "", OFN_HIDEREADONLY, "CSV Files (*.csv)|*.csv||");
+	if (fileDialog.DoModal() != IDOK) {
+		return;
+	}
+
+	CStdioFile file;
+	if (!file.Open(fileDialog.GetPathName(), CFile::modeCreate | CFile::modeWrite | CFile::typeText)) {
+		CString err;
+		err.Format(_T("鏃犳硶鍒涘缓鏂囦欢: %s"), fileDialog.GetPathName());
+		AfxMessageBox(err);
+		return;
+	}
+
+	const int MAX_COLS = 32;
+	char szItem[256] = { 0 };
+	HDITEM hdItem[MAX_COLS];
+
+	for (int i = 0; i < MAX_COLS; i++) {
+		hdItem[i].pszText = szItem;
+		hdItem[i].cchTextMax = 256;
+		hdItem[i].mask = HDI_TEXT | HDI_WIDTH;
+	}
+
+	// 鑾峰彇鍒楁暟
+	CHeaderCtrl* pHeader = m_listCtrl.GetHeaderCtrl();
+	int nSubItemCount = min(pHeader->GetItemCount(), MAX_COLS);
+
+	// 琛ㄥご
+	CString strHeader;
+	for (int i = 0; i < nSubItemCount; i++) {
+		pHeader->GetItem(i, &hdItem[i]);
+		if (hdItem[i].cxy > 0) {
+			if (!strHeader.IsEmpty()) strHeader += ",";
+			strHeader += CString(hdItem[i].pszText);
+		}
+	}
+	strHeader += "\n";
+	file.WriteString(strHeader);
+
+	// 琛ㄦ牸鍐呭
+	int nItemCount = m_listCtrl.GetItemCount();
+	for (int i = 0; i < nItemCount; i++) {
+		CStringArray arrRow;
+		for (int j = 0; j < nSubItemCount; j++) {
+			if (hdItem[j].cxy > 0) {
+				CString strText = m_listCtrl.GetItemText(i, j);
+				strText.Replace(_T("* "), _T(""));
+				// 濡傛灉瀛楁涓惈閫楀彿锛屽寘瑁瑰弻寮曞彿
+				if (strText.Find(',') != -1) {
+					strText = _T("\"") + strText + _T("\"");
+				}
+				arrRow.Add(strText);
+			}
+		}
+
+		CString strRow;
+		for (int k = 0; k < arrRow.GetCount(); ++k) {
+			if (k > 0) strRow += ",";
+			strRow += arrRow[k];
+		}
+		strRow += "\n";
+		file.WriteString(strRow);
+	}
+
+	file.Close();
+}
+
+void CProductionLogDlg::OnBnClickedButtonPrevPage()
+{
+	// 鐐瑰嚮涓婁竴椤�
+	m_nCurPage--;
+	UpdatePageData();  // 璋冪敤鍒嗛〉鏇存柊鍑芥暟
+}
+
+void CProductionLogDlg::OnBnClickedButtonNextPage()
+{
+	// 鐐瑰嚮涓嬩竴椤�
+	m_nCurPage++;
+	UpdatePageData();  // 璋冪敤鍒嗛〉鏇存柊鍑芥暟
+}
+*/
+>>>>>>> clh
diff --git a/SourceCode/Bond/Servo/ProductionLogDlg.h b/SourceCode/Bond/Servo/ProductionLogDlg.h
index 552e582..a4e455e 100644
--- a/SourceCode/Bond/Servo/ProductionLogDlg.h
+++ b/SourceCode/Bond/Servo/ProductionLogDlg.h
@@ -5,6 +5,7 @@
 
 
 // CProductionLogDlg 瀵硅瘽妗�
+<<<<<<< HEAD
 
 //class CProductionLogDlg : public CDialogEx
 //{
@@ -69,3 +70,70 @@
 //	afx_msg void OnBnClickedButtonNextPage();
 //	DECLARE_MESSAGE_MAP()
 //};
+=======
+/*
+class CProductionLogDlg : public CDialogEx
+{
+	DECLARE_DYNAMIC(CProductionLogDlg)
+
+public:
+	CProductionLogDlg(CWnd* pParent = nullptr);   // 鏍囧噯鏋勯�犲嚱鏁�
+	virtual ~CProductionLogDlg();
+
+private:
+	void InitRxWindow();
+	void Resize();
+	void UpdatePageData();
+	void UpdatePageControls();
+	void FillDataToListCtrl(CListCtrl* pListCtrl, const std::vector<ProductionStep>& vecSteps);
+	void InsertStepData(CListCtrl* pListCtrl, const ProductionStep& step);
+	std::string getCurrentTimeString();
+
+private:
+	COLORREF m_crBkgnd;
+	HBRUSH m_hbrBkgnd;
+	IObserver* m_pObserver;
+
+	// 鎼滅储鍏抽敭瀛�
+	std::string m_strKeyword;
+	std::string m_strProductId;
+	std::string m_strBatchNo;
+	std::string m_strDeviceId;
+	std::string m_strOperatorName;
+	std::string m_strStatus;
+
+	// 椤电爜
+	int m_nCurPage;
+	int m_nTotalPages;
+
+	// 鏃ユ湡
+	int m_nDateTimeFlag;
+	char m_szTimeStart[64];
+	char m_szTimeEnd[64];
+
+	// 鎺т欢
+	CDateTimeCtrl m_dateTimeStart;
+	CDateTimeCtrl m_dateTimeEnd;
+	CListCtrlEx m_listCtrl;
+
+// 瀵硅瘽妗嗘暟鎹�
+#ifdef AFX_DESIGN_TIME
+	enum { IDD = IDD_DIALOG_PRODUCTION_LOG };
+#endif
+
+protected:
+	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 鏀寔
+	virtual BOOL OnInitDialog();
+	afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor);
+	afx_msg void OnDestroy();
+	afx_msg void OnClose();
+	afx_msg void OnSize(UINT nType, int cx, int cy);
+	afx_msg void OnCbnSelchangeComboDatetime();
+	afx_msg void OnBnClickedButtonSearch();
+	afx_msg void OnBnClickedButtonExport();
+	afx_msg void OnBnClickedButtonPrevPage();
+	afx_msg void OnBnClickedButtonNextPage();
+	DECLARE_MESSAGE_MAP()
+};
+*/
+>>>>>>> clh
diff --git a/SourceCode/Bond/Servo/Servo.cpp b/SourceCode/Bond/Servo/Servo.cpp
index c3d5bce..5866c64 100644
--- a/SourceCode/Bond/Servo/Servo.cpp
+++ b/SourceCode/Bond/Servo/Servo.cpp
@@ -130,18 +130,18 @@
 
 
 	// 初始化生产履历管理器
-	//try {
-	//	if (!ProductionLogManager::getInstance().initProductionTable()) {
-	//		AfxMessageBox("初始化生产履历管理器失败!");
-	//		return FALSE;
-	//	}
-	//}
-	//catch (const std::exception& ex) {
-	//	CString errorMsg;
-	//	errorMsg.Format(_T("初始化生产履历管理器失败:%s"), CString(ex.what()));
-	//	AfxMessageBox(errorMsg, MB_ICONERROR);
-	//	return FALSE;
-	//}
+	try {
+		if (!ProductionLogManager::getInstance().initProductionTable()) {
+			AfxMessageBox("初始化生产履历管理器失败!");
+			return FALSE;
+		}
+	}
+	catch (const std::exception& ex) {
+		CString errorMsg;
+		errorMsg.Format(_T("初始化生产履历管理器失败:%s"), CString(ex.what()));
+		AfxMessageBox(errorMsg, MB_ICONERROR);
+		return FALSE;
+	}
 
 
 	// 初始化SECS运行设置管理库
diff --git a/SourceCode/Bond/Servo/Servo.rc b/SourceCode/Bond/Servo/Servo.rc
index 9b06b67..0233b72 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 648de13..1abbf4b 100644
--- a/SourceCode/Bond/Servo/Servo.vcxproj
+++ b/SourceCode/Bond/Servo/Servo.vcxproj
@@ -133,10 +133,7 @@
       <AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
     </ResourceCompile>
     <PostBuildEvent>
-      <Command>if exist "\\DESKTOP-IODBVIQ\Servo\Debug\" (
-    xcopy /Y /D "$(OutDir)*.exe" "\\DESKTOP-IODBVIQ\Servo\Debug\"
-    xcopy /Y /D "$(OutDir)*.pdb" "\\DESKTOP-IODBVIQ\Servo\Debug\"
-)</Command>
+      <Command>copy "$(TargetDir)$(ProjectName).exe" "\\DESKTOP-IODBVIQ\Servo\Debug\$(ProjectName).exe"</Command>
     </PostBuildEvent>
   </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
@@ -198,11 +195,13 @@
     <Text Include="ReadMe.txt" />
   </ItemGroup>
   <ItemGroup>
-    <ClInclude Include="AlarmDlg.h" />
+    <ClInclude Include="PageAlarm.h" />
     <ClInclude Include="AlarmManager.h" />
     <ClInclude Include="ApredTreeCtrl2.h" />
     <ClInclude Include="BlButton.h" />
     <ClInclude Include="CAligner.h" />
+    <ClInclude Include="CArm.h" />
+    <ClInclude Include="CArmTray.h" />
     <ClInclude Include="CAttribute.h" />
     <ClInclude Include="CAttributeVector.h" />
     <ClInclude Include="CBakeCooling.h" />
@@ -272,7 +271,7 @@
     <ClInclude Include="Intent.h" />
     <ClInclude Include="ListCtrlEx.h" />
     <ClInclude Include="Log.h" />
-    <ClInclude Include="LogDlg.h" />
+    <ClInclude Include="PageLog.h" />
     <ClInclude Include="LogEdit.h" />
     <ClInclude Include="MapPosWnd.h" />
     <ClInclude Include="Model.h" />
@@ -291,11 +290,13 @@
     <ClInclude Include="VerticalLine.h" />
   </ItemGroup>
   <ItemGroup>
-    <ClCompile Include="AlarmDlg.cpp" />
+    <ClCompile Include="PageAlarm.cpp" />
     <ClCompile Include="AlarmManager.cpp" />
     <ClCompile Include="ApredTreeCtrl2.cpp" />
     <ClCompile Include="BlButton.cpp" />
     <ClCompile Include="CAligner.cpp" />
+    <ClCompile Include="CArm.cpp" />
+    <ClCompile Include="CArmTray.cpp" />
     <ClCompile Include="CAttribute.cpp" />
     <ClCompile Include="CAttributeVector.cpp" />
     <ClCompile Include="CBakeCooling.cpp" />
@@ -364,7 +365,7 @@
     <ClCompile Include="Intent.cpp" />
     <ClCompile Include="ListCtrlEx.cpp" />
     <ClCompile Include="Log.cpp" />
-    <ClCompile Include="LogDlg.cpp" />
+    <ClCompile Include="PageLog.cpp" />
     <ClCompile Include="LogEdit.cpp" />
     <ClCompile Include="MapPosWnd.cpp" />
     <ClCompile Include="Model.cpp" />
diff --git a/SourceCode/Bond/Servo/Servo.vcxproj.filters b/SourceCode/Bond/Servo/Servo.vcxproj.filters
index df691ac..645cae7 100644
--- a/SourceCode/Bond/Servo/Servo.vcxproj.filters
+++ b/SourceCode/Bond/Servo/Servo.vcxproj.filters
@@ -14,7 +14,7 @@
     <ClCompile Include="HsmsAction.cpp" />
     <ClCompile Include="HsmsPassive.cpp" />
     <ClCompile Include="Log.cpp" />
-    <ClCompile Include="LogDlg.cpp" />
+    <ClCompile Include="PageLog.cpp" />
     <ClCompile Include="LogEdit.cpp" />
     <ClCompile Include="Model.cpp" />
     <ClCompile Include="SecsTestDlg.cpp" />
@@ -40,7 +40,7 @@
     <ClCompile Include="CEqModeStep.cpp" />
     <ClCompile Include="CEqStatusStep.cpp" />
     <ClCompile Include="CEqAlarmStep.cpp" />
-    <ClCompile Include="AlarmDlg.cpp" />
+    <ClCompile Include="PageAlarm.cpp" />
     <ClCompile Include="CEqProcessStep.cpp" />
     <ClCompile Include="CAttribute.cpp" />
     <ClCompile Include="CAttributeVector.cpp" />
@@ -97,6 +97,8 @@
     <ClCompile Include="CEqReadStep.cpp" />
     <ClCompile Include="CRecipesManager.cpp" />
     <ClCompile Include="CRecipeList.cpp" />
+    <ClCompile Include="CArm.cpp" />
+    <ClCompile Include="CArmTray.cpp" />
     <ClCompile Include="ProductionLogDlg.cpp" />
     <ClCompile Include="ProductionLogManager.cpp" />
   </ItemGroup>
@@ -109,7 +111,7 @@
     <ClInclude Include="HsmsAction.h" />
     <ClInclude Include="HsmsPassive.h" />
     <ClInclude Include="Log.h" />
-    <ClInclude Include="LogDlg.h" />
+    <ClInclude Include="PageLog.h" />
     <ClInclude Include="LogEdit.h" />
     <ClInclude Include="Model.h" />
     <ClInclude Include="Resource.h" />
@@ -137,7 +139,7 @@
     <ClInclude Include="CEqModeStep.h" />
     <ClInclude Include="CEqStatusStep.h" />
     <ClInclude Include="CEqAlarmStep.h" />
-    <ClInclude Include="AlarmDlg.h" />
+    <ClInclude Include="PageAlarm.h" />
     <ClInclude Include="CEqProcessStep.h" />
     <ClInclude Include="CAttribute.h" />
     <ClInclude Include="CAttributeVector.h" />
@@ -194,6 +196,8 @@
     <ClInclude Include="CEqReadStep.h" />
     <ClInclude Include="CRecipesManager.h" />
     <ClInclude Include="CRecipeList.h" />
+    <ClInclude Include="CArm.h" />
+    <ClInclude Include="CArmTray.h" />
     <ClInclude Include="ProductionLogDlg.h" />
     <ClInclude Include="ProductionLogManager.h" />
   </ItemGroup>
diff --git a/SourceCode/Bond/Servo/Servo.vcxproj.user b/SourceCode/Bond/Servo/Servo.vcxproj.user
index a76706f..405156d 100644
--- a/SourceCode/Bond/Servo/Servo.vcxproj.user
+++ b/SourceCode/Bond/Servo/Servo.vcxproj.user
@@ -4,8 +4,8 @@
     <RESOURCE_FILE>Servo.rc</RESOURCE_FILE>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <RemoteDebuggerCommand>\\DESKTOP-IODBVIQ\Servo\Debug\Servo.exe</RemoteDebuggerCommand>
-    <RemoteDebuggerWorkingDirectory>\\DESKTOP-IODBVIQ\Servo\Debug</RemoteDebuggerWorkingDirectory>
+    <RemoteDebuggerCommand>D:\Servo\Debug\Servo.exe</RemoteDebuggerCommand>
+    <RemoteDebuggerWorkingDirectory>D:\Servo\Debug\</RemoteDebuggerWorkingDirectory>
     <RemoteDebuggerServerName>DESKTOP-IODBVIQ</RemoteDebuggerServerName>
     <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
   </PropertyGroup>
diff --git a/SourceCode/Bond/Servo/ServoDlg.cpp b/SourceCode/Bond/Servo/ServoDlg.cpp
index 0a15903..3bf1852 100644
--- a/SourceCode/Bond/Servo/ServoDlg.cpp
+++ b/SourceCode/Bond/Servo/ServoDlg.cpp
@@ -9,7 +9,6 @@
 #include "Common.h"
 #include "Log.h"
 #include "SecsTestDlg.h"
-#include "AlarmDlg.h"
 #include <chrono>
 #include <thread>
 #include <cmath>
@@ -68,10 +67,6 @@
 	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
 	m_crBkgnd = APPDLG_BACKGROUND_COLOR;
 	m_hbrBkgnd = nullptr;
-	//m_bShowLogWnd = FALSE;
-	//m_bShowAlarmWnd = FALSE;
-	//m_pLogDlg = nullptr;
-	//m_pAlarmDlg = nullptr;
 	m_pTerminalDisplayDlg = nullptr;
 	m_pObserver = nullptr;
 	m_pPanelMaster = nullptr;
@@ -79,15 +74,15 @@
 	m_pPanelAttributes = nullptr;
 	m_pPageGraph1 = nullptr;
 	m_pPageGraph2 = nullptr;
-	m_pPageGraph3 = nullptr;
-	m_pPageGraph4 = nullptr;
+	m_pPageAlarm = nullptr;
+	m_pPageLog = nullptr;
 }
 
 void CServoDlg::DoDataExchange(CDataExchange* pDX)
 {
 	CDialogEx::DoDataExchange(pDX);
-	//DDX_Control(pDX, IDC_BUTTON_LOG, m_btnLog);
-	//DDX_Control(pDX, IDC_BUTTON_ALARM, m_btnAlarm);
+	DDX_Control(pDX, IDC_BUTTON_LOG, m_btnLog);
+	DDX_Control(pDX, IDC_BUTTON_ALARM, m_btnAlarm);
 }
 
 BEGIN_MESSAGE_MAP(CServoDlg, CDialogEx)
@@ -98,11 +93,8 @@
 	ON_BN_CLICKED(IDCANCEL, &CServoDlg::OnBnClickedCancel)
 	ON_WM_CTLCOLOR()
 	ON_WM_DESTROY()
-	//ON_BN_CLICKED(IDC_BUTTON_LOG, &CServoDlg::OnBnClickedButtonLog)
 	ON_WM_SIZE()
 	ON_WM_CLOSE()
-	//ON_MESSAGE(ID_MSG_LOGDLG_HIDE, &CServoDlg::OnLogDlgHide)
-	//ON_MESSAGE(ID_MSG_ALARMDLG_HIDE, &CServoDlg::OnAlarmDlgHide)
 	ON_WM_MOVING()
 	ON_WM_MOVE()
 	ON_COMMAND(ID_MENU_FILE_EXIT, &CServoDlg::OnMenuFileExit)
@@ -111,10 +103,6 @@
 	ON_UPDATE_COMMAND_UI(ID_MENU_FILE_SETTINGS, &CServoDlg::OnUpdateMenuFileSettings)
 	ON_COMMAND(ID_MENU_FILE_SECSTEST, &CServoDlg::OnMenuFileSecsTest)
 	ON_UPDATE_COMMAND_UI(ID_MENU_FILE_SECSTEST, &CServoDlg::OnUpdateMenuFileSecsTest)
-	//ON_COMMAND(ID_MENU_WND_LOG, &CServoDlg::OnMenuWndLog)
-	//ON_UPDATE_COMMAND_UI(ID_MENU_WND_LOG, &CServoDlg::OnUpdateMenuWndLog)
-	//ON_COMMAND(ID_MENU_WND_ALARM, &CServoDlg::OnMenuWndAlarm)
-	//ON_UPDATE_COMMAND_UI(ID_MENU_WND_ALARM, &CServoDlg::OnUpdateMenuWndAlarm)
 	ON_COMMAND(ID_MENU_TEST_MESSAGE_SET, &CServoDlg::OnMenuTestMessageSet)
 	ON_UPDATE_COMMAND_UI(ID_MENU_TEST_MESSAGE_SET, &CServoDlg::OnUpdateMenuTestMessageSet)
 	ON_COMMAND(ID_MENU_TEST_MESSAGE_CLEAR, &CServoDlg::OnMenuTestMessageClear)
@@ -122,7 +110,6 @@
 	ON_COMMAND(ID_MENU_HELP_ABOUT, &CServoDlg::OnMenuHelpAbout)
 	ON_WM_INITMENUPOPUP()
 	ON_WM_TIMER()
-	//ON_BN_CLICKED(IDC_BUTTON_ALARM, &CServoDlg::OnBnClickedButtonAlarm)
 	ON_MESSAGE(ID_MSG_PANEL_RESIZE, OnPanelResize)
 	ON_NOTIFY(BYHMTAB_SEL_CHANGED, IDC_TAB1, &CServoDlg::OnTabSelChanged)
 END_MESSAGE_MAP()
@@ -230,10 +217,10 @@
 	m_pPageGraph1->Create(IDD_PAGE_GRAPH1, this);
 	m_pPageGraph2 = new CPageGraph2();
 	m_pPageGraph2->Create(IDD_PAGE_GRAPH2, this);
-	m_pPageGraph3 = new CAlarmDlg();
-	m_pPageGraph3->Create(IDD_DIALOG_ALARM, this);
-	m_pPageGraph4 = new CLogDlg();
-	m_pPageGraph4->Create(IDD_DIALOG_LOG, this);
+	m_pPageAlarm = new CPageAlarm();
+	m_pPageAlarm->Create(IDD_DIALOG_ALARM, this);
+	m_pPageLog = new CPageLog();
+	m_pPageLog->Create(IDD_DIALOG_LOG, this);
 
 	CHmTab* m_pTab = CHmTab::Hook(GetDlgItem(IDC_TAB1)->m_hWnd);
 	m_pTab->SetPaddingLeft(20);
@@ -270,9 +257,6 @@
 
 	SetTimer(TIMER_ID_CREATE_TERMINAL, 3000, nullptr);
 	InitRxWindows();
-	//OnBnClickedButtonLog();
-	//UpdateLogBtn();
-	//UpdateAlarmBtn();
 	Resize();
 
 
@@ -428,26 +412,6 @@
 	pCmdUI->Enable(TRUE);
 }
 
-//void CServoDlg::OnMenuWndLog()
-//{
-//	OnBnClickedButtonLog();
-//}
-
-//void CServoDlg::OnUpdateMenuWndLog(CCmdUI* pCmdUI)
-//{
-//	pCmdUI->SetCheck(m_bShowLogWnd);
-//}
-
-//void CServoDlg::OnMenuWndAlarm()
-//{
-//	OnBnClickedButtonAlarm();
-//}
-
-//void CServoDlg::OnUpdateMenuWndAlarm(CCmdUI* pCmdUI)
-//{
-//	pCmdUI->SetCheck(m_bShowAlarmWnd);
-//}
-
 void CServoDlg::OnMenuFileExit()
 {
 	PostMessage(WM_CLOSE);
@@ -525,17 +489,6 @@
 {
 	CDialogEx::OnDestroy();
 
-	//if (m_pLogDlg != nullptr) {
-	//	m_pLogDlg->DestroyWindow();
-	//	delete m_pLogDlg;
-	//	m_pLogDlg = nullptr;
-	//}
-
-	//if (m_pAlarmDlg != nullptr) {
-	//	m_pAlarmDlg->DestroyWindow();
-	//	delete m_pAlarmDlg;
-	//	m_pAlarmDlg = nullptr;
-	//}
 
 	if (m_pTerminalDisplayDlg != nullptr) {
 		m_pTerminalDisplayDlg->DestroyWindow();
@@ -573,16 +526,16 @@
 		m_pPageGraph2 = nullptr;
 	}
 
-	if (m_pPageGraph3 != nullptr) {
-		m_pPageGraph3->DestroyWindow();
-		delete m_pPageGraph3;
-		m_pPageGraph3 = nullptr;
+	if (m_pPageAlarm != nullptr) {
+		m_pPageAlarm->DestroyWindow();
+		delete m_pPageAlarm;
+		m_pPageAlarm = nullptr;
 	}
 
-	if (m_pPageGraph4 != nullptr) {
-		m_pPageGraph4->DestroyWindow();
-		delete m_pPageGraph4;
-		m_pPageGraph4 = nullptr;
+	if (m_pPageLog != nullptr) {
+		m_pPageLog->DestroyWindow();
+		delete m_pPageLog;
+		m_pPageLog = nullptr;
 	}
 
 	if (m_hbrBkgnd != nullptr) {
@@ -596,94 +549,14 @@
 
 }
 
-//void CServoDlg::OnBnClickedButtonAlarm()
-//{
-//	m_bShowAlarmWnd = !m_bShowAlarmWnd;
-//
-//	// 如果要显示报警窗口,则隐藏日志窗口
-//	if (m_bShowLogWnd) {
-//		m_bShowLogWnd = false;
-//		if (m_pLogDlg != nullptr) {
-//			m_pLogDlg->ShowWindow(SW_HIDE);
-//			UpdateLogBtn();
-//		}
-//	}
-//
-//	if (m_pAlarmDlg == nullptr) {
-//		m_pAlarmDlg = new CAlarmDlg();
-//		m_pAlarmDlg->Create(IDD_DIALOG_ALARM, this);
-//
-//		CRect rcWnd;
-//		GetWindowRect(&rcWnd);
-//		int nHeight = GetSystemMetrics(SM_CYSCREEN) - rcWnd.bottom - 38;
-//		if (nHeight < 280) nHeight = 280;
-//		m_pAlarmDlg->MoveWindow(rcWnd.left, rcWnd.bottom - 8, rcWnd.Width(), nHeight);
-//	}
-//	ASSERT(m_pAlarmDlg);
-//	m_pAlarmDlg->ShowWindow(m_bShowAlarmWnd ? SW_SHOW : SW_HIDE);
-//
-//	UpdateAlarmBtn();
-//}
-
-//void CServoDlg::OnBnClickedButtonLog()
-//{
-//	m_bShowLogWnd = !m_bShowLogWnd;
-//
-//	// 如果要显示日志窗口,则隐藏报警窗口
-//	if (m_bShowLogWnd) {
-//		m_bShowAlarmWnd = false;
-//		if (m_pAlarmDlg != nullptr) {
-//			m_pAlarmDlg->ShowWindow(SW_HIDE);
-//			UpdateAlarmBtn();
-//		}
-//	}
-//
-//	if (m_pLogDlg == nullptr) {
-//		m_pLogDlg = new CLogDlg();
-//		m_pLogDlg->Create(IDD_DIALOG_LOG, this);
-//
-//		CRect rcWnd;
-//		GetWindowRect(&rcWnd);
-//		int nHeight = GetSystemMetrics(SM_CYSCREEN) - rcWnd.bottom - 38;
-//		if (nHeight < 280) nHeight = 280;
-//		m_pLogDlg->MoveWindow(rcWnd.left, rcWnd.bottom - 8, rcWnd.Width(), nHeight);
-//	}
-//	ASSERT(m_pLogDlg);
-//	m_pLogDlg->ShowWindow(m_bShowLogWnd ? SW_SHOW : SW_HIDE);
-//	
-//	UpdateLogBtn();
-//}
-
-//void CServoDlg::UpdateLogBtn()
-//{
-//	m_btnLog.SetFrameColor(BS_NORMAL, BTN_LOG_FRAME_NORMAL);
-//	m_btnLog.SetFrameColor(BS_HOVER, BTN_LOG_FRAME_HOVER);
-//	m_btnLog.SetFrameColor(BS_PRESS, BTN_LOG_FRAME_PRESS);
-//	m_btnLog.SetBkgndColor(BS_NORMAL, m_bShowLogWnd ? BTN_LOG_BKGND_PRESS : BTN_LOG_BKGND_NORMAL);
-//	m_btnLog.SetBkgndColor(BS_HOVER, BTN_LOG_BKGND_HOVER);
-//	m_btnLog.SetBkgndColor(BS_PRESS, BTN_LOG_BKGND_PRESS);
-//	m_btnLog.Invalidate();
-//}
-
-//void CServoDlg::UpdateAlarmBtn()
-//{
-//	m_btnAlarm.SetFrameColor(BS_NORMAL, BTN_ALARM_FRAME_NORMAL);
-//	m_btnAlarm.SetFrameColor(BS_HOVER, BTN_ALARM_FRAME_HOVER);
-//	m_btnAlarm.SetFrameColor(BS_PRESS, BTN_ALARM_FRAME_PRESS);
-//	m_btnAlarm.SetBkgndColor(BS_NORMAL, m_bShowAlarmWnd ? BTN_ALARM_BKGND_PRESS : BTN_ALARM_BKGND_NORMAL);
-//	m_btnAlarm.SetBkgndColor(BS_HOVER, BTN_ALARM_BKGND_HOVER);
-//	m_btnAlarm.SetBkgndColor(BS_PRESS, BTN_ALARM_BKGND_PRESS);
-//	m_btnAlarm.Invalidate();
-//}
-
 void CServoDlg::OnSize(UINT nType, int cx, int cy)
 {
 	CDialogEx::OnSize(nType, cx, cy);
 	if (GetDlgItem(IDC_TAB1) == nullptr) return;
 	if (m_pPageGraph1 == nullptr) return;
 	if (m_pPageGraph2 == nullptr) return;
-	if (m_pPageGraph3 == nullptr) return;
-	if (m_pPageGraph4 == nullptr) return;
+	if (m_pPageAlarm == nullptr) return;
+	if (m_pPageLog == nullptr) return;
 	
 	Resize();
 	Invalidate();
@@ -724,23 +597,10 @@
 	y += rcItem.Height();
 
 
-	m_pPageGraph1->MoveWindow(x, y, rcClient.Width() - x, rcClient.Height());
-	m_pPageGraph2->MoveWindow(x, y, rcClient.Width() - x, rcClient.Height());
-	m_pPageGraph3->MoveWindow(x, y, rcClient.Width() - x, rcClient.Height());
-	m_pPageGraph4->MoveWindow(x, y, rcClient.Width() - x, rcClient.Height());
-
-
-	//x = rcClient.right - 8;
-	//pItem = GetDlgItem(IDC_BUTTON_LOG);
-	//pItem->GetClientRect(&rcItem);
-	//x -= rcItem.Width();
-	//pItem->MoveWindow(x, rcClient.bottom - 8 - rcItem.Height(), rcItem.Width(), rcItem.Height());
-	//x -= 8;
-
-	//pItem = GetDlgItem(IDC_BUTTON_ALARM);
-	//pItem->GetClientRect(&rcItem);
-	//x -= rcItem.Width();
-	//pItem->MoveWindow(x, rcClient.bottom - 8 - rcItem.Height(), rcItem.Width(), 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_pPageAlarm->MoveWindow(x, y, rcClient.Width() - x, rcClient.Height() - y);
+	m_pPageLog->MoveWindow(x, y, rcClient.Width() - x, rcClient.Height() - y);
 }
 
 void CServoDlg::OnClose()
@@ -750,32 +610,6 @@
 	CDialogEx::OnClose();
 }
 
-//LRESULT CServoDlg::OnLogDlgHide(WPARAM wParam, LPARAM lParam)
-//{
-//	m_bShowLogWnd = FALSE;
-//	UpdateLogBtn();
-//	LOGE("OnLogDlgHide");
-//
-//	unsigned int DATAID, RPTID;
-//	DATAID = 111;
-//	RPTID = 1001;
-//	std::vector<std::string> v;
-//	v.push_back("abc");
-//	v.push_back("def");
-//	theApp.m_model.m_hsmsPassive.requestEventReportSend(DATAID, RPTID, v);
-//
-//	return 0;
-//}
-
-//LRESULT CServoDlg::OnAlarmDlgHide(WPARAM wParam, LPARAM lParam)
-//{
-//	m_bShowAlarmWnd = FALSE;
-//	UpdateAlarmBtn();
-//	LOGE("OnAlarmDlgHide");
-//
-//	return 0;
-//}
-
 void CServoDlg::OnMoving(UINT fwSide, LPRECT pRect)
 {
 	CDialogEx::OnMoving(fwSide, pRect);
@@ -783,17 +617,6 @@
 
 void CServoDlg::OnMove(int x, int y)
 {
-	//if (m_pLogDlg != nullptr && !m_pLogDlg->IsZoomed()) {
-	//	CRect rcWnd;
-	//	GetWindowRect(&rcWnd);
-	//	m_pLogDlg->SetWindowPos(nullptr, rcWnd.left, rcWnd.bottom - 8, 0, 0, SWP_NOSIZE);
-	//}
-
-	//if (m_pAlarmDlg != nullptr && !m_pAlarmDlg->IsZoomed()) {
-	//	CRect rcWnd;
-	//	GetWindowRect(&rcWnd);
-	//	m_pAlarmDlg->SetWindowPos(nullptr, rcWnd.left, rcWnd.bottom - 8, 0, 0, SWP_NOSIZE);
-	//}
 
 	CDialogEx::OnMove(x, y);
 }
@@ -821,7 +644,7 @@
 
 LRESULT CServoDlg::OnPanelResize(WPARAM wParam, LPARAM lParam)
 {
-	int width = wParam;
+	int width = (int)wParam;
 	// m_pPanel->SetPanelWidth(width);
 	Resize();
 
@@ -839,7 +662,7 @@
 void CServoDlg::ShowChildPage(int index)
 {
 	ASSERT(0 <= index && index < 4);
-	static CWnd* pPages[] = { m_pPageGraph1, m_pPageGraph2, m_pPageGraph3, m_pPageGraph4 };
+	static CWnd* pPages[] = { m_pPageGraph1, m_pPageGraph2, m_pPageAlarm, m_pPageLog };
 	for (int i = 0; i < 4; i++) {
 		pPages[i]->ShowWindow(i == index ? SW_SHOW : SW_HIDE);
 	}
diff --git a/SourceCode/Bond/Servo/ServoDlg.h b/SourceCode/Bond/Servo/ServoDlg.h
index ec38640..9ff5766 100644
--- a/SourceCode/Bond/Servo/ServoDlg.h
+++ b/SourceCode/Bond/Servo/ServoDlg.h
@@ -4,8 +4,8 @@
 
 #pragma once
 #include "BlButton.h"
-#include "LogDlg.h"
-#include "AlarmDlg.h"
+#include "PageLog.h"
+#include "PageAlarm.h"
 #include "TerminalDisplayDlg.h"
 #include "CPanelMaster.h"
 #include "CPanelEquipment.h"
@@ -28,22 +28,16 @@
 private:
 	void InitRxWindows();
 	void Resize();
-	//void UpdateLogBtn();
-	//void UpdateAlarmBtn();
 	void ShowChildPage(int index);
 
 
 private:
 	IObserver* m_pObserver;
-	//BOOL m_bShowLogWnd;
-	//BOOL m_bShowAlarmWnd;
-	//CLogDlg* m_pLogDlg;
-	//CAlarmDlg* m_pAlarmDlg;
 	CTerminalDisplayDlg* m_pTerminalDisplayDlg;
 	CPageGraph1* m_pPageGraph1;
 	CPageGraph2* m_pPageGraph2;
-	CAlarmDlg*	 m_pPageGraph3;
-	CLogDlg*	 m_pPageGraph4;
+	CPageAlarm*	 m_pPageAlarm;
+	CPageLog*	 m_pPageLog;
 
 
 // 对话框数据
@@ -60,8 +54,8 @@
 	HICON m_hIcon;
 	COLORREF m_crBkgnd;
 	HBRUSH m_hbrBkgnd;
-	//CBlButton m_btnLog;
-	//CBlButton m_btnAlarm;
+	CBlButton m_btnLog;
+	CBlButton m_btnAlarm;
 	CPanelMaster* m_pPanelMaster;
 	CPanelEquipment* m_pPanelEquipment;
 	CPanelAttributes* m_pPanelAttributes;
@@ -77,11 +71,8 @@
 	afx_msg void OnBnClickedCancel();
 	afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor);
 	afx_msg void OnDestroy();
-	//afx_msg void OnBnClickedButtonLog();
 	afx_msg void OnSize(UINT nType, int cx, int cy);
 	afx_msg void OnClose();
-	//afx_msg LRESULT OnLogDlgHide(WPARAM wParam, LPARAM lParam);
-	//afx_msg LRESULT OnAlarmDlgHide(WPARAM wParam, LPARAM lParam);
 	afx_msg void OnMoving(UINT fwSide, LPRECT pRect);
 	afx_msg void OnMove(int x, int y);
 	afx_msg void OnInitMenuPopup(CMenu* pPopupMenu, UINT nIndex, BOOL bSysMenu);
@@ -89,10 +80,6 @@
 	afx_msg void OnUpdateMenuFileSettings(CCmdUI* pCmdUI);
 	afx_msg void OnMenuFileSecsTest();
 	afx_msg void OnUpdateMenuFileSecsTest(CCmdUI* pCmdUI);
-	//afx_msg void OnMenuWndLog();
-	//afx_msg void OnUpdateMenuWndLog(CCmdUI* pCmdUI);
-	//afx_msg void OnMenuWndAlarm();
-	//afx_msg void OnUpdateMenuWndAlarm(CCmdUI* pCmdUI);
 	afx_msg void OnMenuFileExit();
 	afx_msg void OnUpdateMenuFileExit(CCmdUI* pCmdUI);
 	afx_msg void OnMenuTestMessageSet();
@@ -101,7 +88,6 @@
 	afx_msg void OnUpdateMenuTestMessageClear(CCmdUI* pCmdUI);
 	afx_msg void OnMenuHelpAbout();
 	afx_msg void OnTimer(UINT_PTR nIDEvent);
-	//afx_msg void OnBnClickedButtonAlarm();
 	afx_msg LRESULT OnPanelResize(WPARAM wParam, LPARAM lParam);
 	afx_msg void OnTabSelChanged(NMHDR* nmhdr, LRESULT* result);
 };

--
Gitblit v1.9.3