From f5c4a7f3bce165fe2c8c6d934f0f49a363a2ea60 Mon Sep 17 00:00:00 2001
From: LAPTOP-T815PCOQ\25526 <mr.liuyang@126.com>
Date: 星期五, 15 十一月 2024 09:19:31 +0800
Subject: [PATCH] Merge branch 'master' into liuyang

---
 SourceCode/Bond/BondEq/BondEq.cpp                                              |   12 
 SourceCode/Bond/BondEq/EQState.cpp                                             |  109 
 SourceCode/Bond/McLibrarySDK/McDemo/McDemo/McDemo.sln                          |   31 
 SourceCode/Bond/McLibrarySDK/McDemo/McDemo/McDemo/stdafx.cpp                   |    8 
 SourceCode/Bond/McLibrarySDK/McDemo/McDemo/McDemo/McDemo.vcxproj.filters       |   75 
 SourceCode/Bond/McLibrarySDK/McDemo/readme.txt                                 |   67 
 SourceCode/Bond/BEQLibrary/Unit.h                                              |    7 
 SourceCode/Bond/McLibrarySDK/include/IMcChannel.h                              |  131 
 SourceCode/Bond/BEQLibrary/Equipment.cpp                                       |   26 
 SourceCode/Bond/BondEq/Context.cpp                                             |  157 +
 SourceCode/Bond/McLibrarySDK/include/McLib.h                                   |   84 
 SourceCode/Bond/BondEq/McItem.h                                                |    8 
 SourceCode/Bond/McLibrarySDK/McDemo/McDemo/McDemo/targetver.h                  |    8 
 SourceCode/Bond/McLibrarySDK/McDemo/McDemoDlg.h                                |   57 
 SourceCode/Bond/BondEq/LoadMonitor.h                                           |   49 
 SourceCode/Bond/McLibrarySDK/McDemo/McDemo/McDemo/res/application.exe.manifest |   20 
 SourceCode/Bond/BondEq/AlarmMonitor.cpp                                        |  176 +
 SourceCode/Bond/BondEq/CPLC.h                                                  |   88 
 SourceCode/Bond/McLibrarySDK/McDemo/stdafx.h                                   |   54 
 SourceCode/Bond/BondEq/AlarmMonitor.h                                          |   40 
 SourceCode/Bond/BondEq/Component.h                                             |   57 
 SourceCode/Bond/McLibrarySDK/McDemo/stdafx.cpp                                 |    8 
 SourceCode/Bond/BEQLibrarySDK/Include/IUnit.h                                  |    1 
 SourceCode/Bond/BondEq/BondEqDlg.cpp                                           |    5 
 SourceCode/Bond/BondEq/McBool.h                                                |   12 
 SourceCode/Bond/BondEq/CParam.cpp                                              |   90 
 SourceCode/Bond/BondEq/McInt.h                                                 |   12 
 SourceCode/Bond/BEQLibrary/IUnit.h                                             |    1 
 SourceCode/Bond/BondEq/CDataMonitor1.h                                         |   44 
 SourceCode/Bond/BondEq/CBonder.h                                               |  117 
 SourceCode/Bond/BondEq/CPanel.h                                                |  101 
 SourceCode/Bond/BondEq/CDataMonitor1.cpp                                       |  412 ++
 SourceCode/Bond/BondEq/CParam.h                                                |   34 
 Document/Bond软件开发进度表.xlsx                                                      |    0 
 SourceCode/Bond/BondEq/LoadMonitor.cpp                                         |  419 +++
 SourceCode/Bond/McLibrarySDK/McDemo/McDemo/McDemo/mcdemo.cpp                   |  121 
 SourceCode/Bond/McLibrarySDK/McDemo/McDemo/McDemo/mcdemodlg.h                  |   56 
 SourceCode/Bond/BondEq/Intent.cpp                                              |   51 
 SourceCode/Bond/BondEq/EQState.h                                               |   39 
 SourceCode/Bond/McLibrarySDK/McDemo/mcdemo.vcxproj                             |  226 +
 SourceCode/Bond/BEQLibrary/Unit.cpp                                            |   17 
 SourceCode/Bond/BondEq/Recipe.cpp                                              |   28 
 SourceCode/Bond/McLibrarySDK/McDemo/McDemo.h                                   |   34 
 SourceCode/Bond/BondEq/BondEq.vcxproj                                          |   38 
 SourceCode/Bond/McLibrarySDK/McDemo/McDemo/McDemo/stdafx.h                     |   54 
 SourceCode/Bond/BondEq/Model.h                                                 |    2 
 SourceCode/Bond/BondEq/TopToolbar.h                                            |    1 
 SourceCode/Bond/BondEq/EQStateMonitor.cpp                                      |  155 +
 SourceCode/Bond/McLibrarySDK/Readme.pdf                                        |    0 
 SourceCode/Bond/BondEq/CPLC.cpp                                                |  314 ++
 SourceCode/Bond/McLibrarySDK/McDemo/McDemo/McDemo/res/McDemo.ico               |    0 
 SourceCode/Bond/BondEq/McItem.cpp                                              |   12 
 SourceCode/Bond/McLibrarySDK/McDemo/McDemo/McDemo/mcdemodlg.cpp                |  769 +++++
 SourceCode/Bond/BondEq/McBool.cpp                                              |   14 
 SourceCode/Bond/McLibrarySDK/McDemo/McDemo/McDemo/res/McDemo.rc2               |    0 
 SourceCode/Bond/McLibrarySDK/McDemo/targetver.h                                |    8 
 SourceCode/Bond/BondEq/Alarm.cpp                                               |   96 
 SourceCode/Bond/BondEq/TopToolbar.cpp                                          |    5 
 SourceCode/Bond/BondEq/Common.h                                                |   23 
 Document/Bander开发文档.xlsx                                                       |    0 
 SourceCode/Bond/BondEq/CBonder.cpp                                             | 1044 +++++++
 SourceCode/Bond/BEQLibrary/Equipment.h                                         |    1 
 SourceCode/Bond/BondEq/McInt.cpp                                               |   14 
 SourceCode/Bond/BondEq/Context.h                                               |   44 
 SourceCode/Bond/BondEq/stdafx.h                                                |    1 
 SourceCode/Bond/McLibrarySDK/McDemo/McDemo/McDemo/McDemo.rc                    |    0 
 SourceCode/Bond/McLibrarySDK/McDemo/res/application.exe.manifest               |   20 
 SourceCode/Bond/BondEq/Recipe.h                                                |   17 
 SourceCode/Bond/McLibrarySDK/McDemo/McDemo/McDemo/mcdemo.vcxproj               |  226 +
 SourceCode/Bond/BondEq/Component.cpp                                           |  126 
 SourceCode/Bond/McLibrarySDK/McDemo/resource.h                                 |    0 
 SourceCode/Bond/McLibrarySDK/McDemo/McDemoDlg.cpp                              |  794 +++++
 /dev/null                                                                      |   11 
 SourceCode/Bond/BondEq/Intent.h                                                |   25 
 SourceCode/Bond/BondEq/CPanel.cpp                                              | 1006 +++++++
 SourceCode/Bond/McLibrarySDK/McDemo/McDemo/McDemo/resource.h                   |    0 
 SourceCode/Bond/McLibrarySDK/McDemo/res/McDemo.ico                             |    0 
 SourceCode/Bond/McLibrarySDK/McDemo/McDemo.vcxproj.filters                     |   75 
 SourceCode/Bond/BEQLibrary/BEQCommon.h                                         |    1 
 SourceCode/Bond/BondEq/McString.h                                              |   15 
 SourceCode/Bond/McLibrarySDK/McDemo/res/McDemo.rc2                             |    0 
 SourceCode/Bond/McLibrarySDK/McDemo/McDemo/McDemo/McDemo.h                     |   34 
 SourceCode/Bond/McLibrarySDK/McDemo/mcdemo.cpp                                 |  121 
 SourceCode/Bond/McLibrarySDK/Readme.docx                                       |    0 
 SourceCode/Bond/McLibrarySDK/McDemo/McDemo/McDemo/readme.txt                   |   67 
 SourceCode/Bond/BondEq/Alarm.h                                                 |   31 
 SourceCode/Bond/McLibrarySDK/McDemo/McDemo.rc                                  |    0 
 SourceCode/Bond/BondEq/EQStateMonitor.h                                        |   40 
 SourceCode/Bond/BondEq/McString.cpp                                            |   14 
 89 files changed, 8,293 insertions(+), 17 deletions(-)

diff --git "a/Document/Bander\345\274\200\345\217\221\346\226\207\346\241\243.xlsx" "b/Document/Bander\345\274\200\345\217\221\346\226\207\346\241\243.xlsx"
new file mode 100644
index 0000000..79db026
--- /dev/null
+++ "b/Document/Bander\345\274\200\345\217\221\346\226\207\346\241\243.xlsx"
Binary files differ
diff --git "a/Document/Bond\350\275\257\344\273\266\345\274\200\345\217\221\350\277\233\345\272\246\350\241\250.xlsx" "b/Document/Bond\350\275\257\344\273\266\345\274\200\345\217\221\350\277\233\345\272\246\350\241\250.xlsx"
new file mode 100644
index 0000000..6a86957
--- /dev/null
+++ "b/Document/Bond\350\275\257\344\273\266\345\274\200\345\217\221\350\277\233\345\272\246\350\241\250.xlsx"
Binary files differ
diff --git a/SourceCode/Bond/BEQLibrary/BEQCommon.h b/SourceCode/Bond/BEQLibrary/BEQCommon.h
index 0adb8fa..615be11 100644
--- a/SourceCode/Bond/BEQLibrary/BEQCommon.h
+++ b/SourceCode/Bond/BEQLibrary/BEQCommon.h
@@ -80,5 +80,6 @@
 
 
 /* EVENT */
+#define EVENT_NOTREADY			_T("NOTREADY")
 #define EVENT_LOAD				_T("LOAD")
 #define EVENT_UNLOAD			_T("UNLOAD")
diff --git a/SourceCode/Bond/BEQLibrary/Equipment.cpp b/SourceCode/Bond/BEQLibrary/Equipment.cpp
index 144c390..d956042 100644
--- a/SourceCode/Bond/BEQLibrary/Equipment.cpp
+++ b/SourceCode/Bond/BEQLibrary/Equipment.cpp
@@ -144,6 +144,11 @@
 				repData(m_pActiveClient, (CUnit*)pUnit, AS_MC_INFO_REP);
 			}
 		};
+		listener.onReqNotReady = [&](void* pUnit, int layer) -> void {
+			if (m_pActiveClient != nullptr) {
+				repNotReady(m_pActiveClient, (CUnit*)pUnit, layer, AS_SEND_EVENT_REP);
+			}
+		};
 		listener.onReqLoad = [&](void* pUnit, int layer) -> void {
 			if (m_pActiveClient != nullptr) {
 				repLoad(m_pActiveClient, (CUnit*)pUnit, layer, AS_SEND_EVENT_REP);
@@ -836,6 +841,27 @@
 		return 0;
 	}
 
+	void CEquipment::repNotReady(CAcceptClient* pClient, CUnit* pUnit, int layer, const char* pszReply)
+	{
+		ASSERT(pClient != nullptr);
+		CString strReply;
+		if (pUnit->getLayerCount() == 1) {
+			strReply.Format(_T("%s@%s=%s/%s=%s/%s=%s#"), pszReply,
+				PARAM_EQID, m_strName.c_str(),
+				PARAM_UNIT, pUnit->getName().c_str(),
+				PARAM_EVENT, EVENT_NOTREADY);
+		}
+		else {
+			strReply.Format(_T("%s@%s=%s/%s=%s%d/%s=%s#"), pszReply,
+				PARAM_EQID, m_strName.c_str(),
+				PARAM_UNIT, pUnit->getName().c_str(), layer,
+				PARAM_EVENT, EVENT_NOTREADY);
+		}
+
+
+		pClient->Send((LPTSTR)(LPCTSTR)strReply, strReply.GetLength());
+	}
+
 	void CEquipment::repLoad(CAcceptClient* pClient, CUnit* pUnit, int layer, const char* pszReply)
 	{
 		ASSERT(pClient != nullptr);
diff --git a/SourceCode/Bond/BEQLibrary/Equipment.h b/SourceCode/Bond/BEQLibrary/Equipment.h
index 09e9c95..1240457 100644
--- a/SourceCode/Bond/BEQLibrary/Equipment.h
+++ b/SourceCode/Bond/BEQLibrary/Equipment.h
@@ -48,6 +48,7 @@
 		void repData(CAcceptClient* pClient, CUnit* pUnit, const char* pszReply);
 		void repRecipeList(CAcceptClient* pClient, CUnit* pUnit, const char* pszReply);
 		void repRunRecipe(CAcceptClient* pClient, CUnit* pUnit, int id, const char* pszName, const char* pszReply);
+		void repNotReady(CAcceptClient* pClient, CUnit* pUnit, int layer, const char* pszReply);
 		void repLoadReady(CAcceptClient* pClient, CUnit* pUnit, const char* pszUnitName, const char* pszMaterielId, const char* pszRecipeId, const char* pszReply);
 		void repLoad(CAcceptClient* pClient, CUnit* pUnit, int layer, const char* pszReply);
 		void repUnload(CAcceptClient* pClient, CUnit* pUnit, int layer, const char* pszReply);
diff --git a/SourceCode/Bond/BEQLibrary/IUnit.h b/SourceCode/Bond/BEQLibrary/IUnit.h
index 2a49a4e..75d003e 100644
--- a/SourceCode/Bond/BEQLibrary/IUnit.h
+++ b/SourceCode/Bond/BEQLibrary/IUnit.h
@@ -49,6 +49,7 @@
 		virtual unsigned long long getDataTime() = 0;
 		virtual void addData(const char* pszName, const char* pszDataText, bool bComplete) = 0;
 		virtual void addRecipe(int id, const char* pszName, bool bComplete) = 0;
+		virtual int reqNotReady(int layer) = 0;
 		virtual int reqLoad(int layer) = 0;
 		virtual int reqUnload(int layer) = 0;
 	};
diff --git a/SourceCode/Bond/BEQLibrary/Unit.cpp b/SourceCode/Bond/BEQLibrary/Unit.cpp
index df10698..a5e49e2 100644
--- a/SourceCode/Bond/BEQLibrary/Unit.cpp
+++ b/SourceCode/Bond/BEQLibrary/Unit.cpp
@@ -62,6 +62,7 @@
 		m_listener.onRemoveAlarm = listener.onRemoveAlarm;
 		m_listener.onStepChanged = listener.onStepChanged;
 		m_listener.onDataChanged = listener.onDataChanged;
+		m_listener.onReqNotReady = listener.onReqNotReady;
 		m_listener.onReqLoad = listener.onReqLoad;
 		m_listener.onReqUnload = listener.onReqUnload;
 	}
@@ -212,6 +213,22 @@
 		return m_strAlarmText;
 	}
 
+	int CUnit::reqNotReady(int layer)
+	{
+		ASSERT(m_listener.onReqNotReady);
+		if (layer <= 0) return -1;
+		if (layer > m_nLayerCount) return -2;
+
+		// 状态改变才回调到上层
+		if (m_nLayerLoadState[layer - 1] != LAYER_NOT_READY) {
+			m_nLayerLoadState[layer - 1] = LAYER_NOT_READY;
+			m_listener.onReqNotReady(this, layer);
+			return 0;
+		}
+
+		return -3;
+	}
+
 	int CUnit::reqLoad(int layer)
 	{
 		ASSERT(m_listener.onReqLoad);
diff --git a/SourceCode/Bond/BEQLibrary/Unit.h b/SourceCode/Bond/BEQLibrary/Unit.h
index 9bc540d..90708c9 100644
--- a/SourceCode/Bond/BEQLibrary/Unit.h
+++ b/SourceCode/Bond/BEQLibrary/Unit.h
@@ -6,8 +6,9 @@
 
 
 #define LAYER_LOAD_INIT		0
-#define LAYER_LOAD_REQ		1
-#define LAYER_UNLOAD_REQ	2
+#define LAYER_NOT_READY		1
+#define LAYER_LOAD_REQ		2
+#define LAYER_UNLOAD_REQ	3
 
 namespace BEQ {
 	typedef std::function<void(void* pUnit, EQ_STATE)> ONSTATECHANGED;
@@ -25,6 +26,7 @@
 		ONALARM				onRemoveAlarm;
 		ONSTEPCHANGED		onStepChanged;
 		ONDATACHANGED		onDataChanged;
+		ONREQLOAD			onReqNotReady;
 		ONREQLOAD			onReqLoad;
 		ONREQLOAD			onReqUnload;
 	} UnitListener;
@@ -63,6 +65,7 @@
 		virtual unsigned long long getDataTime();
 		virtual void addData(const char* pszName, const char* pszDataText, bool bComplete);
 		virtual void addRecipe(int id, const char* pszName, bool bComplete);
+		virtual int reqNotReady(int layer);
 		virtual int reqLoad(int layer);
 		virtual int reqUnload(int layer);
 		
diff --git a/SourceCode/Bond/BEQLibrarySDK/Include/IUnit.h b/SourceCode/Bond/BEQLibrarySDK/Include/IUnit.h
index 2a49a4e..75d003e 100644
--- a/SourceCode/Bond/BEQLibrarySDK/Include/IUnit.h
+++ b/SourceCode/Bond/BEQLibrarySDK/Include/IUnit.h
@@ -49,6 +49,7 @@
 		virtual unsigned long long getDataTime() = 0;
 		virtual void addData(const char* pszName, const char* pszDataText, bool bComplete) = 0;
 		virtual void addRecipe(int id, const char* pszName, bool bComplete) = 0;
+		virtual int reqNotReady(int layer) = 0;
 		virtual int reqLoad(int layer) = 0;
 		virtual int reqUnload(int layer) = 0;
 	};
diff --git a/SourceCode/Bond/BondEq/Alarm.cpp b/SourceCode/Bond/BondEq/Alarm.cpp
new file mode 100644
index 0000000..eaa30ad
--- /dev/null
+++ b/SourceCode/Bond/BondEq/Alarm.cpp
@@ -0,0 +1,96 @@
+#include "stdafx.h"
+#include "Alarm.h"
+#include "ToolUnits.h"
+
+
+CAlarm::CAlarm()
+{
+}
+
+CAlarm::CAlarm(int unitId, int status, int id, int level, const char* pszText)
+{
+	m_nUnitId = unitId;
+	m_nStatus = status;
+	m_time = CToolUnits::getTimestamp();
+	m_nId = id;
+	m_nLevel = level;
+	m_strText = pszText;
+}
+
+CAlarm::~CAlarm()
+{
+}
+
+std::string& CAlarm::getClassName()
+{
+	static std::string strName = "CAlarm";
+	return strName;
+}
+
+std::string CAlarm::toString()
+{
+	std::string strText;
+	strText += "CAlarm[";
+	strText += ("time:" + CToolUnits::timeToString2(m_time) + ";");
+	strText += ("m_nStatus:" + std::to_string(m_nStatus) + ";");
+	strText += ("m_nId:" + std::to_string(m_nId) + ";");
+	strText += ("m_nLevel:" + std::to_string(m_nLevel) + ";");
+	strText += ("m_strText:" + m_strText + ";");
+	strText += "]";
+
+	return strText;
+}
+
+int CAlarm::getUnitId()
+{
+	return m_nUnitId;
+}
+
+ULONGLONG CAlarm::getTime()
+{
+	return m_time;
+}
+
+int CAlarm::getId()
+{
+	return m_nId;
+}
+
+int CAlarm::getLevel()
+{
+	return m_nLevel;
+}
+
+int CAlarm::getStatus()
+{
+	return m_nStatus;
+}
+
+std::string& CAlarm::getText()
+{
+	return m_strText;
+}
+
+void CAlarm::Serialize(CArchive& ar)
+{
+	if (ar.IsStoring())
+	{
+		Lock();
+		ar << m_time;
+		ar << m_nStatus;
+		ar << m_nId;
+		ar << m_nLevel;
+		WriteString(ar, m_strText);
+		Unlock();
+	}
+	else
+	{
+		Lock();
+		ar >> m_time;
+		ar >> m_nStatus;
+		ar >> m_nId;
+		ar >> m_nLevel;
+		ReadString(ar, m_strText);
+		Unlock();
+	}
+}
diff --git a/SourceCode/Bond/BondEq/Alarm.h b/SourceCode/Bond/BondEq/Alarm.h
new file mode 100644
index 0000000..9b3a354
--- /dev/null
+++ b/SourceCode/Bond/BondEq/Alarm.h
@@ -0,0 +1,31 @@
+#pragma once
+#include "Context.h"
+
+class CAlarm :
+	public CContext
+{
+public:
+	CAlarm();
+	CAlarm(int unitId, int status, int id, int level, const char* pszText);
+	~CAlarm();
+
+public:
+	virtual std::string& getClassName();
+	virtual std::string toString();
+	int getUnitId();
+	ULONGLONG getTime();
+	int getId();
+	int getLevel();
+	int getStatus();
+	std::string& getText();
+	void Serialize(CArchive& ar);
+
+private:
+	int m_nUnitId;
+	ULONG64 m_time;
+	int m_nStatus;
+	int m_nId;
+	int m_nLevel;
+	std::string m_strText;
+};
+
diff --git a/SourceCode/Bond/BondEq/AlarmMonitor.cpp b/SourceCode/Bond/BondEq/AlarmMonitor.cpp
new file mode 100644
index 0000000..edf375d
--- /dev/null
+++ b/SourceCode/Bond/BondEq/AlarmMonitor.cpp
@@ -0,0 +1,176 @@
+#include "stdafx.h"
+#include "AlarmMonitor.h"
+#include "Common.h"
+#include "CBonder.h"
+#include "Log.h"
+
+#define ALARM_MAX		200
+
+CAlarmMonitor::CAlarmMonitor()
+{
+	m_nBeginAddr = 0;
+	m_nLastId = 0;
+	m_nLastLevel = 0;
+}
+
+
+CAlarmMonitor::~CAlarmMonitor()
+{
+
+}
+
+std::string& CAlarmMonitor::getClassName()
+{
+	static std::string strClassName = "CAlarmMonitor";
+	return strClassName;
+}
+
+void CAlarmMonitor::onRecvBroadcast(void* pSender, CIntent* pIntent)
+{
+
+}
+
+void CAlarmMonitor::onData(int id, const void* pData, int size)
+{
+	const char* pszData = (const char*)pData;
+	if (m_nIndex + 1 == id) {
+		int addr = m_nBeginAddr * 2;
+		int alarmId = (pszData[addr] & 0xff) | (pszData[addr + 1] & 0xff) << 8;
+		int alarmLevel = (pszData[addr + 2] & 0xff) | (pszData[addr + 3] & 0xff) << 8;
+		if (m_nLastId != alarmId) {
+			LOGI("<CAlarmMonitor-%d>AlarmId:%d, AlarmLevel:%d", m_nIndex, alarmId, alarmLevel);
+			Alarm(alarmId, alarmLevel);
+		}
+	}
+}
+
+int CAlarmMonitor::readAlarmListFromFile(const char* pszFilepath)
+{
+	CStdioFile file;
+	if (!file.Open(pszFilepath, CFile::modeRead)) {
+		return -1;
+	}
+
+	CString strLine, strNumber, strDescription;
+	while (file.ReadString(strLine)) {
+		int index = strLine.Find(",");
+		if (index <= 0) continue;
+
+		strNumber = strLine.Left(index).Trim();
+		strDescription = strLine.Right(strLine.GetLength() - index - 1).Trim();
+
+		int number = atoi(strNumber);
+		m_mapAlarmText[number] = std::string((LPTSTR)(LPCTSTR)strDescription);
+	}
+
+	file.Close();
+	return (int)m_mapAlarmText.size();
+}
+
+void CAlarmMonitor::init()
+{
+	CComponent::init();
+}
+
+void CAlarmMonitor::term()
+{
+	for (auto item : m_alarms) {
+		item->release();
+	}
+}
+
+void CAlarmMonitor::setBeginAddr(int nAddr)
+{
+	m_nBeginAddr = nAddr;
+}
+
+void CAlarmMonitor::OnTimer(UINT nTimerid)
+{
+
+}
+
+const char* CAlarmMonitor::getAlarmText(int nID)
+{
+	auto iter = m_mapAlarmText.find(nID);
+	if (iter == m_mapAlarmText.end()) return "";
+
+	return iter->second.c_str();
+}
+
+void CAlarmMonitor::Alarm(int id, int level)
+{
+	BEQ::IUnit* pUnit = m_pBonder->getUnit(m_nIndex);
+	ASSERT(pUnit);
+
+	if (id != 0) {
+		// 警告
+		pUnit->setAlarm(id, level, getAlarmText(id));
+		LOGI("<CAlarmMonitor-%d>设备告警(%d, %d).", m_nIndex, id, level);
+
+		CAlarm* pAlarm = new CAlarm(m_nIndex, 1, id, level, getAlarmText(id));
+		AddAlarm(pAlarm);
+		SendBroadcast(&CIntent(BC_CODE_ALARM_EVENT, "", pAlarm));
+		m_nLastId = id;
+		m_nLastLevel = level;
+	}
+	else {
+		// 解除警告
+		pUnit->setAlarm(0, 0, "");
+		LOGI("<CAlarmMonitor-%d>解除设备告警(%d, %d).", m_nIndex, m_nLastId, m_nLastLevel);
+
+		CAlarm* pAlarm = new CAlarm(m_nIndex, 2, m_nLastId, m_nLastLevel, getAlarmText(m_nLastId));
+		AddAlarm(pAlarm);
+		SendBroadcast(&CIntent(BC_CODE_ALARM_EVENT, "", pAlarm));
+		m_nLastId = 0;
+		m_nLastLevel = 0;
+	}
+}
+
+void CAlarmMonitor::Serialize(CArchive& ar)
+{
+	if (ar.IsStoring())
+	{
+		Lock();
+		int count = (int)m_alarms.size();
+		ar << count;
+		for (auto item : m_alarms) {
+			item->Serialize(ar);
+		}
+		Unlock();
+	}
+	else
+	{
+		Lock();
+		int count;
+		ar >> count;
+		for (int i = 0; i < count; i++) {
+			CAlarm* pAlarm = new CAlarm();
+			pAlarm->addRef();
+			pAlarm->Serialize(ar);
+			AddAlarm(pAlarm);
+			pAlarm->release();
+
+		}
+		Unlock();
+	}
+}
+
+void CAlarmMonitor::AddAlarm(CAlarm* pAlarm)
+{
+	Lock();
+	pAlarm->addRef();
+	m_alarms.push_back(pAlarm);
+	if (m_alarms.size() > ALARM_MAX) {
+		CAlarm* pTemp = m_alarms.front();
+		pTemp->release();
+		m_alarms.pop_front();
+	}
+	Unlock();
+}
+
+void CAlarmMonitor::getAlarmList(std::list<CAlarm*>& list)
+{
+	Lock();
+	list = m_alarms;
+	Unlock();
+}
\ No newline at end of file
diff --git a/SourceCode/Bond/BondEq/AlarmMonitor.h b/SourceCode/Bond/BondEq/AlarmMonitor.h
new file mode 100644
index 0000000..ae84f65
--- /dev/null
+++ b/SourceCode/Bond/BondEq/AlarmMonitor.h
@@ -0,0 +1,40 @@
+#pragma once
+#include "Component.h"
+#include <map>
+#include <list>
+#include "Alarm.h"
+
+class CAlarmMonitor :
+	public CComponent
+{
+public:
+	CAlarmMonitor();
+	~CAlarmMonitor();
+
+public:
+	virtual std::string& getClassName();
+	virtual void onData(int id, const void* pData, int size);
+	virtual void onRecvBroadcast(void* pSender, CIntent* pIntent);
+	virtual void init();
+	virtual void term();
+	void setBeginAddr(int nAddr);
+	int readAlarmListFromFile(const char* pszFilepath);
+	virtual void OnTimer(UINT nTimerid);
+	const char* getAlarmText(int nID);
+	void Alarm(int id, int level);
+	virtual void Serialize(CArchive& ar);
+	void getAlarmList(std::list<CAlarm*>& list);
+
+private:
+	void AddAlarm(CAlarm* pAlarm);
+
+private:
+	int m_nBeginAddr;
+
+private:
+	std::map<int, std::string> m_mapAlarmText;
+	int m_nLastId;
+	int m_nLastLevel;
+	std::list<CAlarm*> m_alarms;
+};
+
diff --git a/SourceCode/Bond/BondEq/BondEq.cpp b/SourceCode/Bond/BondEq/BondEq.cpp
index c595973..7366fa1 100644
--- a/SourceCode/Bond/BondEq/BondEq.cpp
+++ b/SourceCode/Bond/BondEq/BondEq.cpp
@@ -101,6 +101,17 @@
 	RX_Init();
 
 
+	CString strIniFile;
+	strIniFile.Format(_T("%s\\configuration.ini"), (LPTSTR)(LPCTSTR)m_strAppDir);
+	int plcTimeout = GetPrivateProfileInt("PLC", "Timeout", 700, strIniFile);
+	int plcBufSize = GetPrivateProfileInt("PLC", "BufSize", 20, strIniFile);
+	int plcPacketSize = GetPrivateProfileInt("PLC", "PacketSize", 80, strIniFile);
+	MCL_Initialize();
+	MCL_SetTimeout(plcTimeout);
+	MCL_SetMaxActionSize(plcBufSize);
+	MCL_SetPacketSize(plcPacketSize);
+
+
 	// 自定义组件
 	CAccordionWnd::RegisterWndClass();
 	CVerticalLine::RegisterWndClass();
@@ -143,6 +154,7 @@
 {
 	BEQ_Term();
 	RX_Term();
+	MCL_Term();
 
 	return CWinApp::ExitInstance();
 }
diff --git a/SourceCode/Bond/BondEq/BondEq.vcxproj b/SourceCode/Bond/BondEq/BondEq.vcxproj
index 9b0e384..b90ce2e 100644
--- a/SourceCode/Bond/BondEq/BondEq.vcxproj
+++ b/SourceCode/Bond/BondEq/BondEq.vcxproj
@@ -190,7 +190,10 @@
     <Text Include="ReadMe.txt" />
   </ItemGroup>
   <ItemGroup>
+    <ClInclude Include="CPLC.h" />
     <ClInclude Include="AccordionWnd.h" />
+    <ClInclude Include="Alarm.h" />
+    <ClInclude Include="AlarmMonitor.h" />
     <ClInclude Include="ApredTreeCtrl.h" />
     <ClInclude Include="AxisSettingsDlg.h" />
     <ClInclude Include="BaseSetPage.h" />
@@ -198,6 +201,12 @@
     <ClInclude Include="BondEq.h" />
     <ClInclude Include="BondEqDlg.h" />
     <ClInclude Include="CBaseView.h" />
+    <ClInclude Include="CBonder.h" />
+    <ClInclude Include="CDataMonitor1.h" />
+    <ClInclude Include="Component.h" />
+    <ClInclude Include="Context.h" />
+    <ClInclude Include="CPanel.h" />
+    <ClInclude Include="CParam.h" />
     <ClInclude Include="CRemoteEqUnitView.h" />
     <ClInclude Include="CRemoteEqView.h" />
     <ClInclude Include="CHomeDialog.h" />
@@ -208,15 +217,23 @@
     <ClInclude Include="Configuration.h" />
     <ClInclude Include="CPanelProject.h" />
     <ClInclude Include="DBManager\UserManager.h" />
+    <ClInclude Include="EQState.h" />
+    <ClInclude Include="EQStateMonitor.h" />
     <ClInclude Include="HmTab.h" />
     <ClInclude Include="HmVerticalTab.h" />
     <ClInclude Include="HorizontalLine.h" />
+    <ClInclude Include="Intent.h" />
+    <ClInclude Include="LoadMonitor.h" />
     <ClInclude Include="Log.h" />
     <ClInclude Include="LogEdit.h" />
+    <ClInclude Include="McBool.h" />
+    <ClInclude Include="McInt.h" />
+    <ClInclude Include="McItem.h" />
+    <ClInclude Include="McString.h" />
     <ClInclude Include="Model.h" />
     <ClInclude Include="CPageAlarm.h" />
+    <ClInclude Include="Recipe.h" />
     <ClInclude Include="Resource.h" />
-    <ClInclude Include="Bonder.h" />
     <ClInclude Include="SetPage1.h" />
     <ClInclude Include="SetPage2.h" />
     <ClInclude Include="SettingsDlg.h" />
@@ -229,7 +246,10 @@
     <ClInclude Include="View\LoginDlg.h" />
   </ItemGroup>
   <ItemGroup>
+    <ClCompile Include="CPLC.cpp" />
     <ClCompile Include="AccordionWnd.cpp" />
+    <ClCompile Include="Alarm.cpp" />
+    <ClCompile Include="AlarmMonitor.cpp" />
     <ClCompile Include="ApredTreeCtrl.cpp" />
     <ClCompile Include="AxisSettingsDlg.cpp" />
     <ClCompile Include="BaseSetPage.cpp" />
@@ -237,6 +257,12 @@
     <ClCompile Include="BondEq.cpp" />
     <ClCompile Include="BondEqDlg.cpp" />
     <ClCompile Include="CBaseView.cpp" />
+    <ClCompile Include="CBonder.cpp" />
+    <ClCompile Include="CDataMonitor1.cpp" />
+    <ClCompile Include="Component.cpp" />
+    <ClCompile Include="Context.cpp" />
+    <ClCompile Include="CPanel.cpp" />
+    <ClCompile Include="CParam.cpp" />
     <ClCompile Include="CRemoteEqUnitView.cpp" />
     <ClCompile Include="CRemoteEqView.cpp" />
     <ClCompile Include="CHomeDialog.cpp" />
@@ -246,14 +272,22 @@
     <ClCompile Include="Configuration.cpp" />
     <ClCompile Include="CPanelProject.cpp" />
     <ClCompile Include="DBManager\UserManager.cpp" />
+    <ClCompile Include="EQState.cpp" />
+    <ClCompile Include="EQStateMonitor.cpp" />
     <ClCompile Include="HmTab.cpp" />
     <ClCompile Include="HmVerticalTab.cpp" />
     <ClCompile Include="HorizontalLine.cpp" />
+    <ClCompile Include="Intent.cpp" />
+    <ClCompile Include="LoadMonitor.cpp" />
     <ClCompile Include="Log.cpp" />
     <ClCompile Include="LogEdit.cpp" />
+    <ClCompile Include="McBool.cpp" />
+    <ClCompile Include="McInt.cpp" />
+    <ClCompile Include="McItem.cpp" />
+    <ClCompile Include="McString.cpp" />
     <ClCompile Include="Model.cpp" />
     <ClCompile Include="CPageAlarm.cpp" />
-    <ClCompile Include="Bonder.cpp" />
+    <ClCompile Include="Recipe.cpp" />
     <ClCompile Include="SetPage1.cpp" />
     <ClCompile Include="SetPage2.cpp" />
     <ClCompile Include="SettingsDlg.cpp" />
diff --git a/SourceCode/Bond/BondEq/BondEqDlg.cpp b/SourceCode/Bond/BondEq/BondEqDlg.cpp
index eb1cde7..21935a5 100644
--- a/SourceCode/Bond/BondEq/BondEqDlg.cpp
+++ b/SourceCode/Bond/BondEq/BondEqDlg.cpp
@@ -7,7 +7,7 @@
 #include "BondEqDlg.h"
 #include "afxdialogex.h"
 #include "Common.h"
-#include "Bonder.h"
+#include "CBonder.h"
 #include "SettingsDlg.h"
 #include "UserManager.h"
 #include "LoginDlg.h"
@@ -198,6 +198,9 @@
 	m_pTopToolbar->Create(IDD_TOP_TOOLBAR, this);
 	m_pTopToolbar->ShowWindow(SW_SHOW);
 	m_pTopToolbar->GetBtn(IDC_BUTTON_STOP)->EnableWindow(FALSE);
+	HMENU hMenu = m_pTopToolbar->GetOperatorMenu();
+	ASSERT(hMenu);
+	::EnableMenuItem(hMenu, ID_OPEATOR_SWITCH, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
 
 
 	// 设备面板
diff --git a/SourceCode/Bond/BondEq/Bonder.cpp b/SourceCode/Bond/BondEq/Bonder.cpp
deleted file mode 100644
index 7dd03ab..0000000
--- a/SourceCode/Bond/BondEq/Bonder.cpp
+++ /dev/null
@@ -1,17 +0,0 @@
-#include "stdafx.h"
-#include "Bonder.h"
-
-
-CBonder::CBonder()
-{
-}
-
-
-CBonder::~CBonder()
-{
-}
-
-BOOL CBonder::isRunning()
-{
-	return FALSE;
-}
\ No newline at end of file
diff --git a/SourceCode/Bond/BondEq/Bonder.h b/SourceCode/Bond/BondEq/Bonder.h
deleted file mode 100644
index 5dcaf5d..0000000
--- a/SourceCode/Bond/BondEq/Bonder.h
+++ /dev/null
@@ -1,11 +0,0 @@
-#pragma once
-class CBonder
-{
-public:
-	CBonder();
-	~CBonder();
-
-public:
-	BOOL isRunning();
-};
-
diff --git a/SourceCode/Bond/BondEq/CBonder.cpp b/SourceCode/Bond/BondEq/CBonder.cpp
new file mode 100644
index 0000000..9ed5f45
--- /dev/null
+++ b/SourceCode/Bond/BondEq/CBonder.cpp
@@ -0,0 +1,1044 @@
+#include "stdafx.h"
+#include "CBonder.h"
+#include "Log.h"
+#include "EQStateMonitor.h"
+#include "CDataMonitor1.h"
+#include "AlarmMonitor.h"
+#include "LoadMonitor.h"
+
+
+CBonder* g_pBonder = NULL;
+void CALLBACK BonderTimerProc(HWND hWnd, UINT nMsg, UINT nTimerid, DWORD dwTime)
+{
+	if (g_pBonder != NULL) {
+		g_pBonder->onTimer(nTimerid);
+	}
+}
+
+UINT BoonderGetRecipeListThreadFunction(LPVOID lpParam)
+{
+	DWORD_PTR* p = (DWORD_PTR*)lpParam;
+	CBonder* pBonder = (CBonder*)p[0];
+	BEQ::IEquipment* pEquipment = (BEQ::IEquipment*)p[1];
+	BEQ::IUnit* pUnit = (BEQ::IUnit*)p[2];
+	delete[] p;
+	return pBonder->GetRecipeListThreadFunction(pEquipment, pUnit);
+}
+
+CBonder::CBonder()
+{
+	m_state = STATE_READY;
+	m_ullRunTime = 0;
+	m_ullStartTick = 0;
+	m_listener.onStateChanged = nullptr;
+	m_listener.onPlcStateChanged = nullptr;
+	m_listener.onRecvBroadcast = nullptr;
+	m_bAreYouThereRequest = TRUE;
+	m_strEquipmentModelType = "2860";
+	m_strSoftRev = "1.01";
+	m_pPlcData = nullptr;
+	InitializeCriticalSection(&m_criticalSection);
+}
+
+CBonder::~CBonder()
+{
+	for (auto item : m_components) {
+		delete item;
+	}
+	m_components.clear();
+	clearRecipes();
+
+	DeleteCriticalSection(&m_criticalSection);
+}
+
+void CBonder::setWorkDir(const char* pszWorkDir)
+{
+	m_strWorkDir = pszWorkDir;
+}
+
+void CBonder::setListener(BondListener& listener)
+{
+	m_listener.onStateChanged = listener.onStateChanged;
+	m_listener.onPlcStateChanged = listener.onPlcStateChanged;
+	m_listener.onCimStateChanged = listener.onCimStateChanged;
+	m_listener.onEfemStateChanged = listener.onEfemStateChanged;
+	m_listener.onRecvBroadcast = listener.onRecvBroadcast;
+}
+
+const std::vector<CComponent*>& CBonder::getComponents()
+{
+	return m_components;
+}
+
+int CBonder::save()
+{
+	CFile file;
+	if (!file.Open(m_strFilepath.c_str(), CFile::modeCreate | CFile::modeWrite)) {
+		return -1;
+	}
+
+	CArchive ar(&file, CArchive::store);
+	Serialize(ar);
+	ar.Close();
+	file.Close();
+
+	return 0;
+}
+
+int CBonder::read(const char* pszFilepath)
+{
+	CFile file;
+	m_strFilepath = pszFilepath;
+	if (!file.Open(pszFilepath, CFile::modeRead)) {
+		return -1;
+	}
+
+	CArchive ar(&file, CArchive::load);
+	Serialize(ar);
+	ar.Close();
+	file.Close();
+
+	return 0;
+}
+
+void CBonder::Serialize(CArchive& ar)
+{
+	if (ar.IsStoring()) {
+		Lock();
+		Unlock();
+	}
+	else {
+		Lock();
+
+		Unlock();
+	}
+
+	for (auto item : m_components) {
+		item->Serialize(ar);
+	}
+}
+
+int CBonder::init()
+{
+	// 机器状态
+	CEQStateMonitor* pEQStateMonitor1 = new CEQStateMonitor();
+	pEQStateMonitor1->setName("机器状态(A单元)");
+	pEQStateMonitor1->setDescription("A单机器状态");
+	pEQStateMonitor1->setIndex(0);
+	pEQStateMonitor1->setBeginAddr(4463 - 4400);
+	AddComponent(pEQStateMonitor1);
+	pEQStateMonitor1->init();
+
+	CEQStateMonitor* pEQStateMonitor2 = new CEQStateMonitor();
+	pEQStateMonitor2->setName("机器状态(B单元)");
+	pEQStateMonitor2->setDescription("B单机器状态");
+	pEQStateMonitor2->setIndex(1);
+	pEQStateMonitor2->setBeginAddr(4563 - 4500);
+	AddComponent(pEQStateMonitor2);
+	pEQStateMonitor2->init();
+
+
+	// 初始化各种组件
+	// 读PLC1配置
+	// 读取机器名
+	CString strIniFile;
+	strIniFile.Format(_T("%s\\configuration.ini"), m_strWorkDir.c_str());
+
+	m_pPlcData = new char[1024];
+	char szIP[256];
+	unsigned int nPort;
+	BOOL bAutoSendData = FALSE;
+	GetPrivateProfileString("PLC1", "IP", _T(""), szIP, 256, strIniFile);
+	nPort = GetPrivateProfileInt("PLC1", "PORT", 8080, strIniFile);
+	bAutoSendData = GetPrivateProfileInt("Equipment", "AutoSendData", 0, strIniFile) != 0;
+	CPLC* pPlc = new CPLC("PLC1", szIP, nPort);
+	PLCListener listener;
+	listener.onStateChanged = [&](void* pFrom, int state) -> void {
+		if (m_listener.onPlcStateChanged != nullptr) {
+			m_listener.onPlcStateChanged(pFrom, state);
+		}
+	};
+	listener.onMonitorData = [&](void* pFrom, int id) -> void {
+		if (id == 1) {
+			for (auto c : m_components) {
+				c->onData(id, m_pPlcData, 200);
+			}
+		}
+		else if (id == 2) {
+			char szBuffer[24];
+			memset(szBuffer, 0, 24);
+			memcpy(szBuffer, &m_pPlcData[200+90*2], 20);
+			m_strCurRecipeName = szBuffer;
+
+			for (auto c : m_components) {
+				c->onData(id, &m_pPlcData[200], 200);
+			}
+		}
+		else if (id == 3) {
+			for (auto c : m_components) {
+				c->onData(id, &m_pPlcData[400], 184);
+			}
+		}
+	};
+	pPlc->setListener(listener);
+	pPlc->addMonitor(1, 4400, 4499, MC::SOFT_COMPONENT::D, m_pPlcData);
+	pPlc->addMonitor(2, 4500, 4599, MC::SOFT_COMPONENT::D, &m_pPlcData[200]);
+	pPlc->addMonitor(3, 4700, 4791, MC::SOFT_COMPONENT::D, &m_pPlcData[400]);
+	pPlc->setName("PLC(1)");
+	pPlc->setDescription("PLC");
+	pPlc->setIndex(0);
+	pPlc->init();
+	AddComponent(pPlc);
+
+
+	CDataMonitor1* pDataMonitor1 = new CDataMonitor1();
+	pDataMonitor1->setName("数据监控(A单元)");
+	pDataMonitor1->setDescription("A单元真空、压力和温度数据");
+	pDataMonitor1->setIndex(0);
+	pDataMonitor1->setResponseAddr(4425);
+	pDataMonitor1->enableAutoSendData(bAutoSendData);
+	AddComponent(pDataMonitor1);
+	pDataMonitor1->init();
+	
+	CDataMonitor1* pDataMonitor2 = new CDataMonitor1();
+	pDataMonitor2->setName("数据监控(B单元)");
+	pDataMonitor2->setDescription("B单元真空、压力和温度数据");
+	pDataMonitor2->setIndex(1);
+	pDataMonitor2->setResponseAddr(4525);
+	pDataMonitor2->enableAutoSendData(bAutoSendData);
+	AddComponent(pDataMonitor2);
+	pDataMonitor2->init();
+	
+
+
+	CString strAlarmFile;
+	strAlarmFile.Format(_T("%s\\AlarmList.txt"), m_strWorkDir.c_str());
+	CAlarmMonitor* pAlarmMonitor1 = new CAlarmMonitor();
+	pAlarmMonitor1->setName("警告信息(A单元)");
+	pAlarmMonitor1->setDescription("警告信息监控(A单元)");
+	pAlarmMonitor1->setBeginAddr(4461 - 4400);
+	pAlarmMonitor1->setIndex(0);
+	pAlarmMonitor1->readAlarmListFromFile((LPTSTR)(LPCTSTR)strAlarmFile);
+	AddComponent(pAlarmMonitor1);
+	pAlarmMonitor1->init();
+
+	CAlarmMonitor* pAlarmMonitor2 = new CAlarmMonitor();
+	pAlarmMonitor2->setName("警告信息(B单元)");
+	pAlarmMonitor2->setDescription("警告信息监控(B单元)");
+	pAlarmMonitor2->setBeginAddr(4561 - 4500);
+	pAlarmMonitor2->setIndex(1);
+	pAlarmMonitor2->readAlarmListFromFile((LPTSTR)(LPCTSTR)strAlarmFile);
+	AddComponent(pAlarmMonitor2);
+	pAlarmMonitor2->init();
+
+	// LoadMonitor
+	CLoadMonitor* pLoadMonitor1 = new CLoadMonitor();
+	pLoadMonitor1->setName("上下料(A单元)");
+	pLoadMonitor1->setDescription("上下料信号监控(A单元)");
+	pLoadMonitor1->setBeginAddr(4700);
+	pLoadMonitor1->setIndex(0);
+	AddComponent(pLoadMonitor1);
+	pLoadMonitor1->init();
+
+	CLoadMonitor* pLoadMonitor2 = new CLoadMonitor();
+	pLoadMonitor2->setName("上下料(B单元)");
+	pLoadMonitor2->setDescription("上下料信号监控(B单元)");
+	pLoadMonitor2->setBeginAddr(4700);
+	pLoadMonitor2->setIndex(1);
+	AddComponent(pLoadMonitor2);
+	pLoadMonitor2->init();
+
+	CLoadMonitor* pLoadMonitor3 = new CLoadMonitor();
+	pLoadMonitor3->setName("上下料(冷却箱)");
+	pLoadMonitor3->setDescription("上下料信号监控(冷却箱)");
+	pLoadMonitor3->setBeginAddr(4700);
+	pLoadMonitor3->setIndex(2);
+	AddComponent(pLoadMonitor3);
+	pLoadMonitor3->init();
+
+
+	// BEQ与EFEM通讯
+	BEQ_CreateEquipment(m_pEquipment, m_strUnitId.c_str());
+	ASSERT(m_pEquipment != nullptr);
+	BEQ::EquipmentListener equListener;
+	equListener.onConnected = [&](void* pEquipment, const char* pszAddr, int port) -> void {
+		if (m_listener.onEfemStateChanged != nullptr) {
+			m_listener.onEfemStateChanged(this, pszAddr, port, 1);
+		}
+		LOGI("<Bonder>EFEM连接进入[%s:%d]", pszAddr, port);
+	};
+	equListener.onDisconnected = [&](void* pEquipment, const char* pszAddr, int port) -> void {
+		m_listener.onEfemStateChanged(this, pszAddr, port, 0);
+		LOGI("<Bonder>EFEM连接断开[%s:%d]", pszAddr, port);
+	};
+	equListener.onRunRecipe = [&](void* pEquipment, void* pUnit, int id) -> int {
+		return runRecipe((BEQ::IUnit*)pUnit, id);
+	};
+	equListener.onGetRecipeList = [&](void* pEquipment, void* pUnit) -> int {
+		getRecipeListInBlock((BEQ::IEquipment*)pEquipment, (BEQ::IUnit*)pUnit);
+		return 1;
+	};
+	equListener.onLoadReady = [&](void* pEquipment, void* pUnit, const char* pszMaterielId, const char* pszRecipeId) -> int {
+		return loadReady((BEQ::IUnit*)pUnit, pszMaterielId, pszRecipeId);
+	};
+	equListener.onLoadComplete = [&](void* pEquipment, void* pUnit, int layer) -> int {
+		return loadComplete((BEQ::IUnit*)pUnit, layer);
+	};
+	equListener.onUnloadComplete = [&](void* pEquipment, void* pUnit, int layer) -> int {
+		return unloadComplete((BEQ::IUnit*)pUnit, layer);
+	};
+	m_pEquipment->setEquipmentListener(equListener);
+	m_pEquipment->setVersion(m_strSoftRev.c_str());
+	m_pEquipment->addUnit(UNITA, 5);
+	m_pEquipment->addUnit(UNITB, 5);
+	BEQ::IUnit* pUnitC = m_pEquipment->addUnit(UNITC, 1);
+	pUnitC->setLayerCount(4);
+	m_pEquipment->runOnServerMode(8192);
+
+
+	g_pBonder = this;
+	SetTimer(NULL, 1, 1000, (TIMERPROC)BonderTimerProc);
+
+	return 0;
+}
+
+int CBonder::term()
+{
+	m_listener.onStateChanged = nullptr;
+	m_listener.onPlcStateChanged = nullptr;
+	m_listener.onRecvBroadcast = nullptr;
+
+	for (auto item : m_components) {
+		item->term();
+	}
+
+	if (m_pPlcData != nullptr) {
+		delete[] m_pPlcData;
+		m_pPlcData = nullptr;
+	}
+
+	return 0;
+}
+
+void CBonder::sendBroadcast(CComponent* pSender, CIntent* pIntent)
+{
+	for (auto item : m_components) {
+		if (item != pSender) {
+			item->onRecvBroadcast(pSender, pIntent);
+		}
+	}
+	this->onRecvBroadcast(pSender, pIntent);
+}
+
+void CBonder::onRecvBroadcast(CComponent* pSender, CIntent* pIntent)
+{
+	int code = pIntent->getCode();
+	if (m_listener.onRecvBroadcast != nullptr) {
+		m_listener.onRecvBroadcast(pSender, pIntent);
+	}
+
+	if (BC_CODE_RUN_RECIPE_RESULT == code) {
+		int errorCode = (int)pIntent->getContext();
+		m_pEquipment->repLoadReadyComplete(errorCode);
+	}
+}
+
+void CBonder::setUnitId(const char* pszUnitId)
+{
+	m_strUnitId = pszUnitId;
+}
+
+void CBonder::setEquipmentModelType(const char* pszModelType)
+{
+	m_strEquipmentModelType = pszModelType;
+}
+
+void CBonder::setSoftRev(const char* pszSoftRev)
+{
+	m_strSoftRev = pszSoftRev;
+}
+
+int CBonder::start()
+{
+	Lock();
+	if (m_state == STATE_RUNNING) {
+		Unlock();
+		return -1;
+	}
+
+	if (m_state == STATE_ERROR) {
+		Unlock();
+		return -2;
+	}
+
+	LOGI("<Bonder>Start...");
+	m_state = STATE_RUNNING;
+	m_ullStartTick = GetTickCount64();
+	for (auto item : m_components) {
+		item->run();
+	}
+	Unlock();
+
+	if (m_listener.onStateChanged != nullptr) {
+		m_listener.onStateChanged(this, m_state);
+	}
+
+
+	return 0;
+}
+
+int CBonder::stop()
+{
+	Lock();
+	if (m_state != STATE_RUNNING) {
+		Unlock();
+		return -1;
+	}
+
+	m_state = STATE_STOP;
+	m_ullRunTime += (GetTickCount64() - m_ullStartTick);
+	for (auto item : m_components) {
+		item->stop();
+	}
+	Unlock();
+
+	LOGI("<Bonder>Stop.");
+	if (m_listener.onStateChanged != nullptr) {
+		m_listener.onStateChanged(this, m_state);
+	}
+
+
+	return 0;
+}
+
+int CBonder::clearError()
+{
+	Lock();
+	if (m_state != STATE_ERROR) {
+		Unlock();
+		return -1;
+	}
+
+	m_state = STATE_READY;
+	Unlock();
+	if (m_listener.onStateChanged != nullptr) {
+		m_listener.onStateChanged(this, m_state);
+	}
+
+	return 0;
+}
+
+BOOL CBonder::isRunning()
+{
+	return m_state == STATE_RUNNING;
+}
+
+ULONGLONG CBonder::getRunTime()
+{
+	if (m_state != STATE_RUNNING) {
+		return m_ullRunTime;
+	}
+	else {
+		return m_ullRunTime + (GetTickCount64() - m_ullStartTick);
+	}
+}
+
+void CBonder::onTimer(UINT nTimerid)
+{
+	for (auto item : m_components) {
+		item->OnTimer(nTimerid);
+	}
+
+	static int iii = 0;
+	iii++;
+	if (iii % 5 == 0) {
+		save();
+	}
+}
+
+void CBonder::AddComponent(CComponent* pComponent)
+{
+	ASSERT(pComponent);
+	pComponent->setBonder(this);
+	m_components.push_back(pComponent);
+}
+
+CComponent* CBonder::GetComponent(const char* pszName)
+{
+	for (auto c : m_components) {
+		if (c->getName().compare(pszName) == 0) {
+			return c;
+		}
+	}
+
+	return nullptr;
+}
+
+int CBonder::writeInt(int unitId, int addr, int value)
+{
+	static CPLC* pPLC = nullptr;
+	if (pPLC == nullptr) {
+		pPLC = (CPLC*)GetComponent("PLC(1)");
+	}
+	ASSERT(pPLC);
+	pPLC->writeWord(MC::SOFT_COMPONENT::D, addr, value,
+		[&](IMcChannel* pChannel, int addr, DWORD value, int flag) -> void {
+		if (flag != 0) {
+			LOGE("<CBonder>writeInt超时<unitId=%d,addr=%d,value=%d,flag=%d>", unitId, addr, value, flag);
+		}
+	});
+
+	return 0;
+}
+
+int CBonder::writeData(MC::SOFT_COMPONENT softComponent, unsigned int addr,
+	const char* pszData, unsigned int length, ONWRITE funOnWrite)
+{
+	static CPLC* pPLC = nullptr;
+	if (pPLC == nullptr) {
+		pPLC = (CPLC*)GetComponent("PLC(1)");
+	}
+	ASSERT(pPLC);
+	return pPLC->writeData(softComponent, addr, pszData, length, funOnWrite);
+}
+
+int CBonder::readData(MC::SOFT_COMPONENT softComponent, unsigned int addr,
+	unsigned int readLen, ONREADDATA funOnRead)
+{
+	static CPLC* pPLC = nullptr;
+	if (pPLC == nullptr) {
+		pPLC = (CPLC*)GetComponent("PLC(1)");
+	}
+	ASSERT(pPLC);
+	return pPLC->readData(softComponent, addr, readLen, funOnRead);
+}
+
+BOOL CBonder::readDataBlocking(HANDLE hEvent, MC::SOFT_COMPONENT softComponent, unsigned int addr,
+	unsigned int readLen, char* pszBuffer)
+{
+	static CPLC* pPLC = nullptr;
+	if (pPLC == nullptr) {
+		pPLC = (CPLC*)GetComponent("PLC(1)");
+	}
+	ASSERT(pPLC);
+
+	BOOL bReadOk = FALSE;
+	BOOL bOutputLog = FALSE;
+	auto funOnReadData = [&](IMcChannel* pChannel, int addr, char* pData, unsigned int nDataSize, int flag) -> void {
+		if (flag == 0) {
+			if (bOutputLog) {
+				CString s;
+				s.Format(_T("CBonder::readDataBlocking::funOnReadData %d ["), nDataSize);
+				for (unsigned int i = 0; i < nDataSize; i++) {
+					s.AppendFormat(" %x", (BYTE)pData[i]);
+				}
+				s.Append("]");
+				LOGI("<CBonder>Addr:%d, Received plc data.%s\n", addr, (LPTSTR)(LPCTSTR)s);
+			}
+		}
+		else {
+			LOGE("<CBonder>Addr:%d, PLC批读取数据位超时.flag=%d\n", addr, flag);
+		}
+
+		if (nDataSize == readLen && flag == 0) {
+			bReadOk = TRUE;
+			memcpy(pszBuffer, pData, readLen);
+		}
+		SetEvent(hEvent);
+	};
+
+
+	ResetEvent(hEvent);
+	pPLC->readData(softComponent, addr, readLen, funOnReadData);
+	WaitForSingleObject(hEvent, INFINITE);
+
+	return bReadOk;
+}
+
+BEQ::IEquipment* CBonder::getEquipment()
+{
+	return m_pEquipment;
+}
+
+BEQ::IUnit* CBonder::getUnit(int index)
+{
+	if (index == 0)
+		return m_pEquipment->getUnit(UNITA);
+	if (index == 1)
+		return m_pEquipment->getUnit(UNITB);
+	if (index == 2)
+		return m_pEquipment->getUnit(UNITC);
+
+	return nullptr;
+}
+
+std::string& CBonder::getCurRecipeName()
+{
+	return m_strCurRecipeName;
+}
+
+#define RECIPE_HEADER_SIZE	20 * 2
+#define RECIPE_NAME_SIZE	10 * 2
+#define RECIPE_SIZE		1140
+int CBonder::getRecipeList()
+{
+	CPLC* pPLC = (CPLC*)GetComponent("PLC(1)");
+	ASSERT(pPLC);
+	if (!pPLC->isConnected()) return -1;
+	clearRecipes();
+
+	HANDLE hEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
+	BOOL bOutputLog = TRUE;
+	BOOL bReadOk = FALSE;
+	char szBuffer[RECIPE_HEADER_SIZE];
+	char szRecipeName[RECIPE_NAME_SIZE + 4];
+	szRecipeName[RECIPE_NAME_SIZE] = '\0';
+	auto funOnReadData = [&](IMcChannel* pChannel, int addr, char* pData, unsigned int nDataSize, int flag) -> void {
+		if (flag == 0) {
+			if (bOutputLog) {
+				CString s;
+				s.Format(_T("CPLC::monitorReadData::funOnReadData %d ["), nDataSize);
+				for (unsigned int i = 0; i < nDataSize; i++) {
+					s.AppendFormat(" %x", (BYTE)pData[i]);
+				}
+				s.Append("]");
+				TRACE("<CBonder>Addr:%d, Received plc data.%s\n", addr, (LPTSTR)(LPCTSTR)s);
+			}
+		}
+		else {
+			TRACE("<CBonder>Addr:%d, PLC批读取数据位超时.flag=%d\n", addr, flag);
+		}
+
+		if (nDataSize == RECIPE_HEADER_SIZE && flag == 0) {
+			bReadOk = TRUE;
+			memcpy(szBuffer, pData, RECIPE_HEADER_SIZE);
+		}
+		SetEvent(hEvent);
+	};
+
+
+	for (int i = 0; i < 100; i++) {
+		bReadOk = FALSE;
+		pPLC->readData(MC::SOFT_COMPONENT::ZR, 270000 + i*RECIPE_SIZE, RECIPE_HEADER_SIZE, funOnReadData);
+		WaitForSingleObject(hEvent, 3 * 1000);
+		ResetEvent(hEvent);
+		// 解释数据得到配方
+		if (bReadOk) {
+			int id = (szBuffer[0] & 0xff) | (szBuffer[1] & 0xff) << 8
+				| (szBuffer[2] & 0xff) << 16 | (szBuffer[3] & 0xff) << 24;
+			int x = (szBuffer[28] & 0xff) | (szBuffer[29] & 0xff) << 8
+				| (szBuffer[30] & 0xff) << 16 | (szBuffer[31] & 0xff) << 24;
+			int y = (szBuffer[32] & 0xff) | (szBuffer[33] & 0xff) << 8
+				| (szBuffer[34] & 0xff) << 16 | (szBuffer[35] & 0xff) << 24;
+			int z = (szBuffer[36] & 0xff) | (szBuffer[37] & 0xff) << 8
+				| (szBuffer[38] & 0xff) << 16 | (szBuffer[39] & 0xff) << 24;
+			if (x > 0 && y > 0 && z > 0 && getRecipe(id) == nullptr) {
+				memcpy(szRecipeName, &szBuffer[4], RECIPE_NAME_SIZE);
+				Lock();
+				CRecipe* pRecipe = new CRecipe(id, szRecipeName);
+				m_recipes[id] = pRecipe;
+				Unlock();
+			}
+			// MYTRACE1("<Bonder>读取 %d,%s, xyz<%d,%d,%d>, OK\n", i, szRecipeName, x, y, z);
+		}
+	}
+
+
+	CloseHandle(hEvent);
+	return 0;
+}
+
+int CBonder::getRecipeListInBlock(BEQ::IEquipment* pEquipment, BEQ::IUnit* pUnit)
+{
+	DWORD_PTR* p = new DWORD_PTR[3];
+	p[0] = (DWORD_PTR)this;
+	p[1] = (DWORD_PTR)pEquipment;
+	p[2] = (DWORD_PTR)pUnit;
+	CWinThread* pAcceptThread = AfxBeginThread(&BoonderGetRecipeListThreadFunction, (LPVOID)p,
+		THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED);
+	if (pAcceptThread) {
+		pAcceptThread->ResumeThread();
+	}
+
+	return 0;
+}
+
+UINT CBonder::GetRecipeListThreadFunction(BEQ::IEquipment* pEquipment, BEQ::IUnit* pUnit)
+{
+	char szUnitName[256];
+	pUnit->getName(szUnitName, 256);
+	LOGI("<CBonder>正在获取%s配方", szUnitName);
+	getRecipeList();
+	LOGI("<CBonder>获取%s配方完成", szUnitName);
+
+	for (auto item : m_recipes) {
+		pUnit->addRecipe(item.first, item.second->getName().c_str(), false);
+	}
+	pEquipment->repRecipeListComplete();
+
+	return 0;
+}
+
+int CBonder::runRecipe(BEQ::IUnit* pUnit, int id)
+{
+	char szUnitName[256];
+	pUnit->getName(szUnitName, 256);
+	LOGI("<CBonder>%s正在切换配方-%d", szUnitName, id);
+
+	CPLC* pPLC = (CPLC*)GetComponent("PLC(1)");
+	ASSERT(pPLC);
+	if (!pPLC->isConnected()) return -1;
+
+
+	// 先写数据到plc
+	HANDLE hEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
+	BOOL bWrite = TRUE;
+	char szBuffer[8];
+	szBuffer[0] = (2 & 0xff);
+	szBuffer[1] = (2 & 0xff00) >> 8;
+	szBuffer[2] = 0;
+	szBuffer[3] = 0;
+	szBuffer[4] = (id & 0xff);
+	szBuffer[5] = (id & 0xff00) >> 8;
+	szBuffer[6] = (id & 0xff0000) >> 16;
+	szBuffer[7] = (id & 0xff000000) >> 24;
+	pPLC->writeData(MC::SOFT_COMPONENT::D, 4615, szBuffer, 8, [&](IMcChannel* pChannel, int addr, DWORD value, int flag) -> void {
+		if (flag != 0) {
+			LOGE("<CBonder::runRecipe-%d>PLC1写数据超时.flag=%d", flag, __LINE__);
+			bWrite = FALSE;
+		}
+		SetEvent(hEvent);
+	});
+	WaitForSingleObject(hEvent, INFINITE);
+	ResetEvent(hEvent);
+	if (!bWrite) {
+		CloseHandle(hEvent);
+		return -2;
+	}
+
+
+	// 然后从PLC读结果
+	BOOL bOutputLog = FALSE;
+	BOOL bReadOk = FALSE;
+	Sleep(5000);
+	auto funOnReadData = [&](IMcChannel* pChannel, int addr, char* pData, unsigned int nDataSize, int flag) -> void {
+		if (flag == 0) {
+			if (bOutputLog) {
+				CString s;
+				s.Format(_T("CPLC::runRecipe::funOnReadData %d ["), nDataSize);
+				for (unsigned int i = 0; i < nDataSize; i++) {
+					s.AppendFormat(" %x", (BYTE)pData[i]);
+				}
+				s.Append("]");
+				LOGI("<CBonder>Addr:%d, Received plc data.%s\n", addr, (LPTSTR)(LPCTSTR)s);
+			}
+		}
+		else {
+			LOGE("<CBonder::runRecipe>Addr:%d, PLC批读取数据位超时.flag=%d\n", addr, flag);
+		}
+
+		if (nDataSize == 2 && flag == 0) {
+			int value = (pData[0] & 0xff) | (pData[1] & 0xff) << 8;
+			bReadOk = (value == 2);
+		}
+		SetEvent(hEvent);
+	};
+
+	pPLC->readData(MC::SOFT_COMPONENT::D, 4630, 2, funOnReadData);
+	WaitForSingleObject(hEvent, INFINITE);
+	ResetEvent(hEvent);
+
+
+	// 清空结果
+	memset(szBuffer, 0, 8);
+	pPLC->writeData(MC::SOFT_COMPONENT::D, 4615, szBuffer, 8, [&](IMcChannel* pChannel, int addr, DWORD value, int flag) -> void {
+		if (flag != 0) {
+			LOGE("<CBonder::runRecipe-%d>PLC1写数据超时.flag=%d", flag, __LINE__);
+			bWrite = FALSE;
+		}
+		SetEvent(hEvent);
+	});
+	CloseHandle(hEvent);
+
+
+	if (bReadOk) {
+		LOGI("<CBonder>%s切换配方-%d完成", szUnitName, id);
+		return 0;
+	}
+	else {
+		LOGE("<CBonder>%s切换配方-%d失败", szUnitName, id);
+		return -3;
+	}
+}
+
+int CBonder::loadReady(BEQ::IUnit* pUnit, const char* pszMaterielId, const char* pszRecipeId)
+{
+	char szUnitName[256];
+	pUnit->getName(szUnitName, 256);
+	LOGI("<CBonder>%s上料准备就绪,MaterielId:%s, RecipeId:%s", szUnitName, pszMaterielId, pszRecipeId);
+
+	CPLC* pPLC = (CPLC*)GetComponent("PLC(1)");
+	ASSERT(pPLC);
+	if (!pPLC->isConnected()) {
+		return -1;
+	}
+
+
+	// 单元C为水冷塔,不需要写
+	if (strcmp(szUnitName, UNITC) == 0) {
+		return 0;
+	}
+
+
+	// 如果是单元A或单元B, 写物料ID和配方ID到PLC
+	CLoadMonitor* pLoadMonitor = nullptr;
+	if (strcmp(szUnitName, UNITA) == 0) {
+
+		pLoadMonitor = (CLoadMonitor*)GetComponent("上下料(A单元)");
+		return pLoadMonitor->loadReady(pszMaterielId, pszRecipeId);
+	}
+	else if (strcmp(szUnitName, UNITB) == 0) {
+
+		pLoadMonitor = (CLoadMonitor*)GetComponent("上下料(B单元)");
+		return pLoadMonitor->loadReady(pszMaterielId, pszRecipeId);
+	}
+
+	return -2;
+}
+
+int CBonder::loadComplete(BEQ::IUnit* pUnit, int layer)
+{
+	char szUnitName[256];
+	pUnit->getName(szUnitName, 256);
+	LOGI("<CBonder>%s上料完成,layer:%d", szUnitName, layer);
+
+	CPLC* pPLC = (CPLC*)GetComponent("PLC(1)");
+	ASSERT(pPLC);
+	if (!pPLC->isConnected()) {
+		return -1;
+	}
+	if (layer <= 0 || layer > 4) {
+		return -2;
+	}
+
+	// 写BIT位到PLC,以告诉它上料完成
+	// D寄存器似乎不能按位写,先读出再写入
+	BOOL bOutputLog = FALSE;
+	BOOL bReadOk = FALSE;
+	char szBuffer[32];
+	HANDLE hEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
+	auto funOnReadData = [&](IMcChannel* pChannel, int addr, char* pData, unsigned int nDataSize, int flag) -> void {
+		if (flag == 0) {
+			if (bOutputLog) {
+				CString s;
+				s.Format(_T("CPLC::loadComplete::funOnReadData %d ["), nDataSize);
+				for (unsigned int i = 0; i < nDataSize; i++) {
+					s.AppendFormat(" %x", (BYTE)pData[i]);
+				}
+				s.Append("]");
+				TRACE("<CBonder>Addr:%d, Received plc data.%s\n", addr, (LPTSTR)(LPCTSTR)s);
+			}
+		}
+		else {
+			LOGE("<CBonder>Addr:%d, PLC批读取数据位超时.flag=%d\n", addr, flag);
+		}
+
+		if (nDataSize == 6 && flag == 0) {
+			bReadOk = TRUE;
+			memcpy(szBuffer, pData, 6);
+		}
+		SetEvent(hEvent);
+	};
+	pPLC->readData(MC::SOFT_COMPONENT::D, 4710, 6, funOnReadData);
+	WaitForSingleObject(hEvent, INFINITE);
+	ResetEvent(hEvent);
+	if (!bReadOk) {
+		CloseHandle(hEvent);
+		LOGE("<CBonder>%s上料完成,读标志位失败。layer:%d", szUnitName, layer);
+		return -3;
+	}
+
+	// 写
+	int index, nFlagAddr;
+	if (strcmp(szUnitName, UNITA) == 0) {
+		index = 0;
+		nFlagAddr = 4710;
+		szBuffer[index * 2] |= 0x02;
+	}
+	else if (strcmp(szUnitName, UNITB) == 0) {
+		index = 1;
+		nFlagAddr = 4711;
+		szBuffer[index * 2] |= 0x02;
+	}
+	else if (strcmp(szUnitName, UNITC) == 0) {
+		index = 2;
+		nFlagAddr = 4712;
+		switch (layer)
+		{
+		case 1:
+			szBuffer[index * 2] |= 0x01;
+			break;
+		case 2:
+			szBuffer[index * 2] |= 0x02;
+			break;
+		case 3:
+			szBuffer[index * 2] |= 0x04;
+			break;
+		case 4:
+			szBuffer[index * 2] |= 0x08;
+			break;
+		default:
+			break;
+		}
+	}
+
+
+	BOOL bWriteOk = TRUE;
+	pPLC->writeData(MC::SOFT_COMPONENT::D, nFlagAddr, &szBuffer[index * 2], 2, [&](IMcChannel* pChannel, int addr, DWORD value, int flag) -> void {
+		if (flag != 0) {
+			LOGE("<CBonder::loadReady-%d>PLC1写数据超时.flag=%d", __LINE__, flag);
+			bWriteOk = FALSE;
+		}
+		SetEvent(hEvent);
+	});
+	WaitForSingleObject(hEvent, INFINITE);
+	ResetEvent(hEvent);
+	CloseHandle(hEvent);
+
+	if (bWriteOk) {
+		LOGI("<CBonder>%s上料完成,已写入PLC", szUnitName);
+		return 0;
+	}
+	else {
+		LOGE("<CBonder>%s上料完成, 写PLC无响应", szUnitName);
+		return -4;
+	}
+}
+
+int CBonder::unloadComplete(BEQ::IUnit* pUnit, int layer)
+{
+	char szUnitName[256];
+	pUnit->getName(szUnitName, 256);
+	LOGI("<CBonder>%s下料完成,layer:%d", szUnitName, layer);
+
+	CPLC* pPLC = (CPLC*)GetComponent("PLC(1)");
+	ASSERT(pPLC);
+	if (!pPLC->isConnected()) {
+		return -1;
+	}
+	if (layer <= 0 || layer > 4) {
+		return -2;
+	}
+
+	// 写BIT位到PLC,以告诉它上料完成
+	// D寄存器似乎不能按位写,先读出再写入
+	BOOL bOutputLog = FALSE;
+	BOOL bReadOk = FALSE;
+	char szBuffer[32];
+	HANDLE hEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
+	auto funOnReadData = [&](IMcChannel* pChannel, int addr, char* pData, unsigned int nDataSize, int flag) -> void {
+		if (flag == 0) {
+			if (bOutputLog) {
+				CString s;
+				s.Format(_T("CPLC::unloadComplete::funOnReadData %d ["), nDataSize);
+				for (unsigned int i = 0; i < nDataSize; i++) {
+					s.AppendFormat(" %x", (BYTE)pData[i]);
+				}
+				s.Append("]");
+				LOGD("<CBonder>Addr:%d, Received plc data.%s\n", addr, (LPTSTR)(LPCTSTR)s);
+			}
+		}
+		else {
+			LOGE("<CBonder>Addr:%d, PLC批读取数据位超时.flag=%d\n", addr, flag);
+		}
+
+		if (nDataSize == 6 && flag == 0) {
+			bReadOk = TRUE;
+			memcpy(szBuffer, pData, 6);
+		}
+		SetEvent(hEvent);
+	};
+	pPLC->readData(MC::SOFT_COMPONENT::D, 4710, 6, funOnReadData);
+	WaitForSingleObject(hEvent, INFINITE);
+	ResetEvent(hEvent);
+
+	if (!bReadOk) {
+		CloseHandle(hEvent);
+		LOGE("<CBonder>%s下料完成,读标志位失败。layer:%d", szUnitName, layer);
+		return -3;
+	}
+
+	// 写
+	int index, nFlagAddr;
+	if (strcmp(szUnitName, UNITA) == 0) {
+		index = 0;
+		nFlagAddr = 4710;
+		szBuffer[index * 2 + 1] |= 0x02;
+	}
+	else if (strcmp(szUnitName, UNITB) == 0) {
+		index = 1;
+		nFlagAddr = 4711;
+		szBuffer[index * 2 + 1] |= 0x02;
+	}
+	else if (strcmp(szUnitName, UNITC) == 0) {
+		index = 2;
+		nFlagAddr = 4712;
+		switch (layer)
+		{
+		case 1:
+			szBuffer[index * 2] |= 0x20;
+			break;
+		case 2:
+			szBuffer[index * 2] |= 0x40;
+			break;
+		case 3:
+			szBuffer[index * 2] |= 0x80;
+			break;
+		case 4:
+			szBuffer[index * 2 + 1] |= 0x01;
+			break;
+		default:
+			break;
+		}
+	}
+
+
+	BOOL bWriteOk = TRUE;
+	pPLC->writeData(MC::SOFT_COMPONENT::D, nFlagAddr, &szBuffer[index * 2], 2, [&](IMcChannel* pChannel, int addr, DWORD value, int flag) -> void {
+		if (flag != 0) {
+			LOGE("<CBonder::unloadReady-%d>PLC1写数据超时.flag=%d", __LINE__, flag);
+			bWriteOk = FALSE;
+		}
+		SetEvent(hEvent);
+	});
+	WaitForSingleObject(hEvent, INFINITE);
+	ResetEvent(hEvent);
+	CloseHandle(hEvent);
+
+	if (bWriteOk) {
+		LOGI("<CBonder>%s下料完成,已写入PLC", szUnitName);
+		return 0;
+	}
+	else {
+		LOGE("<CBonder>%s下料完成, 写PLC无响应", szUnitName);
+		return -4;
+	}
+}
+
+void CBonder::clearRecipes()
+{
+	for (auto item : m_recipes) {
+		delete item.second;
+	}
+	m_recipes.clear();
+}
+
+CRecipe* CBonder::getRecipe(int id)
+{
+	auto iter = m_recipes.find(id);
+	if (iter == m_recipes.end()) return nullptr;
+
+	return iter->second;
+}
+
+
diff --git a/SourceCode/Bond/BondEq/CBonder.h b/SourceCode/Bond/BondEq/CBonder.h
new file mode 100644
index 0000000..295cac7
--- /dev/null
+++ b/SourceCode/Bond/BondEq/CBonder.h
@@ -0,0 +1,117 @@
+#pragma once
+#include "Component.h"
+#include <vector>
+#include <functional>
+#include "CPLC.h"
+#include <list>
+#include <map>
+#include "Recipe.h"
+
+
+#define ER_NOERROR			0
+#define ER_NOTSELECT		-1
+#define ER_BUSY				-2
+
+#define STATE_READY			0		/* 就绪 */
+#define STATE_RUNNING		1		/* 运行中 */
+#define STATE_STOP			2		/* 停止 */
+#define STATE_ERROR			3		/* 发生故障 */
+
+
+typedef std::function<void(void* pFrom, int)> ONBONDSTATECHANGED;
+typedef std::function<void(void* pFrom, int)> ONPLCSTATECHANGED;
+typedef std::function<void(void* pFrom, int)> ONCIMSTATECHANGED;
+typedef std::function<void(void* pFrom, const char* pszAddr, int port, int)> ONEFEMSTATECHANGED;
+typedef std::function<void(void* pFrom, void*)> ONRECVBROADCAST;
+
+typedef struct _BondListener
+{
+	ONBONDSTATECHANGED		onStateChanged;
+	ONPLCSTATECHANGED		onPlcStateChanged;
+	ONCIMSTATECHANGED		onCimStateChanged;
+	ONEFEMSTATECHANGED		onEfemStateChanged;
+	ONRECVBROADCAST			onRecvBroadcast;
+} BondListener;
+
+class CBonder
+{
+public:
+	CBonder();
+	virtual ~CBonder();
+
+
+public:
+	void setListener(BondListener& listener);
+	void setWorkDir(const char* pszWorkDir);
+	const std::vector<CComponent*>& getComponents();
+	int init();
+	int term();
+	void sendBroadcast(CComponent* pSender, CIntent* pIntent);
+	void onRecvBroadcast(CComponent* pSender, CIntent* pIntent);
+	int start();
+	int stop();
+	int clearError();
+	BOOL isRunning();
+	ULONGLONG getRunTime();
+	void onTimer(UINT nTimerid);
+	int save();
+	int read(const char* pszFilepath);
+	void setUnitId(const char* pszUnitId);
+	void setEquipmentModelType(const char* pszModelType);
+	void setSoftRev(const char* pszSoftRev);
+	CComponent* GetComponent(const char* pszName);;
+	int getRecipeList();
+	int getRecipeListInBlock(BEQ::IEquipment* pEquipment, BEQ::IUnit* pUnit);
+	int runRecipe(BEQ::IUnit* pUnit, int id);
+	UINT GetRecipeListThreadFunction(BEQ::IEquipment* pEquipment, BEQ::IUnit* pUnit);
+	int loadReady(BEQ::IUnit* pUnit, const char* pszMaterielId, const char* pszRecipeId);
+	int loadComplete(BEQ::IUnit* pUnit, int layer);
+	int unloadComplete(BEQ::IUnit* pUnit, int layer);
+
+public:
+	int writeInt(int unitId, int addr, int value);
+	int writeData(MC::SOFT_COMPONENT softComponent, unsigned int addr,
+		const char* pszData, unsigned int length, ONWRITE funOnWrite);
+	int readData(MC::SOFT_COMPONENT softComponent, unsigned int addr,
+		unsigned int length, ONREADDATA funOnRead);
+	BOOL readDataBlocking(HANDLE hEvent, MC::SOFT_COMPONENT softComponent, unsigned int addr,
+		unsigned int readLen, char* pszBuffer);
+
+private:
+	inline void Lock() { EnterCriticalSection(&m_criticalSection); }
+	inline void Unlock() { LeaveCriticalSection(&m_criticalSection); }
+	void AddComponent(CComponent* pComponent);
+	void Serialize(CArchive& ar);
+	unsigned int getSystemByte();
+	const char* getCeidDataId();
+	CRecipe* getRecipe(int id);
+	void clearRecipes();
+
+public:
+	BEQ::IEquipment* getEquipment();
+	BEQ::IUnit* getUnit(int index);
+	std::string& getCurRecipeName();
+
+private:
+	std::string m_strWorkDir;
+	std::vector<CComponent*> m_components;
+	int m_state;
+	ULONGLONG m_ullRunTime;
+	ULONGLONG m_ullStartTick;
+	CRITICAL_SECTION m_criticalSection;
+	BondListener m_listener;
+
+private:
+	std::string m_strFilepath;
+	std::string m_strUnitId;
+	std::string m_strEquipmentModelType;
+	std::string m_strSoftRev;
+	BOOL m_bAreYouThereRequest;
+
+private:
+	char* m_pPlcData;
+	BEQ::IEquipment* m_pEquipment;
+	std::map<int, CRecipe*> m_recipes;
+	std::string m_strCurRecipeName;
+};
+
diff --git a/SourceCode/Bond/BondEq/CDataMonitor1.cpp b/SourceCode/Bond/BondEq/CDataMonitor1.cpp
new file mode 100644
index 0000000..d7ff4fc
--- /dev/null
+++ b/SourceCode/Bond/BondEq/CDataMonitor1.cpp
@@ -0,0 +1,412 @@
+#include "stdafx.h"
+#include "CDataMonitor1.h"
+#include "CBonder.h"
+#include "Log.h"
+
+
+CDataMonitor1::CDataMonitor1()
+{
+	m_pActivePanel = nullptr;
+	m_nResponseAddr = 0;
+	m_bAutoSendData = TRUE;
+	m_bSampling = FALSE;
+	m_hRemoveEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
+	m_pszRemoveParamData = new char[4096];
+}
+
+CDataMonitor1::~CDataMonitor1()
+{
+	Lock();
+	if (m_pActivePanel != nullptr) {
+		m_pActivePanel->release();
+		m_pActivePanel = nullptr;
+	}
+
+	for (auto item : m_panels) {
+		item->release();
+	}
+	m_panels.clear();
+	Unlock();
+
+	if (m_hRemoveEvent != nullptr) {
+		::CloseHandle(m_hRemoveEvent);
+		m_hRemoveEvent = nullptr;
+	}
+
+	if (m_pszRemoveParamData != nullptr) {
+		delete[] m_pszRemoveParamData;
+		m_pszRemoveParamData = nullptr;
+	}
+}
+
+std::string& CDataMonitor1::getClassName()
+{
+	static std::string strClassName = "CDataMonitor1";
+	return strClassName;
+}
+
+void CDataMonitor1::OnTimer(UINT nTimerid)
+{
+	/*
+	if (m_nIndex == 0) {
+		char szData[200];
+		memset(szData, 0, 200);
+		strcpy_s(szData, 20, "ABC123");
+
+		static int step = 0;
+		static int iii = 0;
+		iii+=5;
+		if (iii == 100) {
+			step = 20;
+			szData[20 * 2] = 20;
+			szData[20 * 2 + 1] = 0x00;
+
+		}
+		if (iii > 100 + 15 * 5 && iii < 100 + 24 * 5) {
+			step = 1;
+			szData[20 * 2] = 1;
+			szData[20 * 2 + 1] = 0x00;
+		}
+		if (iii == 100 + 25 * 5) {
+			step = 2;
+			szData[20 * 2] = 2;
+			szData[20 * 2 + 1] = 0x00;
+		}
+		if (iii == 100 + 35 * 5) {
+			step = 30;
+			szData[20 * 2] = 30;
+			szData[20 * 2 + 1] = 0x00;
+		}
+
+
+		if (step == 1) {
+			onData(1, szData, 200);
+			onData(1, szData, 200);
+			onData(1, szData, 200);
+			onData(1, szData, 200);
+			onData(1, szData, 200);
+		}
+		else if (step != 0) {
+			onData(1, szData, 200);
+		}
+	}
+	else {
+
+	}
+	*/
+}
+
+void CDataMonitor1::onData(int unitId, const void* pData, int size)
+{
+	if (m_nIndex + 1 != unitId) return;
+
+	const char* pszData = (const char*)pData;
+	BEQ::IUnit* pUnit = m_pBonder->getUnit(m_nIndex);
+	ASSERT(pUnit);
+
+
+	// 先检查采样标志
+	// sapmleFlag: 1采样,2结束采样,20入站,30出站
+	int i, v;
+	i = 20 * 2;
+	int sampleFlag = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8;
+	if (sampleFlag == STEP_RECEIVED) {
+		WriteResultFlag(unitId, STEP_RECEIVED);
+
+		CString strId;
+		for (int i = 0; i < 10 * 20; i++) {
+			strId.Insert(strId.GetLength(), pszData[i]);
+		}
+
+		// 当前面板
+		Lock();
+		if (m_pActivePanel == nullptr) {
+			m_pActivePanel = new CPanel((LPTSTR)(LPCTSTR)strId, m_nIndex);
+			m_pActivePanel->setStep(STEP_RECEIVED);
+			m_pActivePanel->addRef();
+			SendBroadcast(&CIntent(BC_CODE_DATA1_MATERIAL_RECEIVED, "", nullptr));
+			LOGI("<CDataMonitor1-%d>产品准备入站,id=%s.", m_nIndex, (LPTSTR)(LPCTSTR)strId);
+			pUnit->stepMaterialReceived((LPTSTR)(LPCTSTR)strId);
+		}
+		ASSERT(m_pActivePanel);
+		LOGI("<CDataMonitor1-%d>产品已入站,id=%s.", m_nIndex, (LPTSTR)(LPCTSTR)strId);
+		Unlock();
+	}
+	else if (sampleFlag == STEP_BEGIN_SAMPLING) {
+		m_bSampling = TRUE;
+		WriteResultFlag(unitId, STEP_BEGIN_SAMPLING);
+
+		// 当前面板
+		if (m_pActivePanel != nullptr) {
+			if (m_pActivePanel->getStep() == STEP_RECEIVED) {
+				m_pActivePanel->setStep(STEP_BEGIN_SAMPLING);
+				LOGI("<CDataMonitor1-%d>采样开始.", m_nIndex);
+				pUnit->stepProcessingStarted(m_pActivePanel->getQRCode().c_str());
+				SendBroadcast(&CIntent(BC_CODE_DATA1_BEGIN_SAMPLING, "", nullptr));
+			}
+		}
+	}
+	else if (sampleFlag == STEP_READY) {
+		// 当前面板
+		if (m_bSampling && m_pActivePanel != nullptr) {
+
+			// 上腔体温度
+			UNITDATA1 ud1;
+			ud1.time = m_pActivePanel->GetCurrentSampleTime();
+
+			i = 30 * 2;
+			v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8;
+			ud1.temp[0] = v * 0.1f;
+			i += 2;
+			v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8;
+			ud1.temp[1] = v * 0.1f;
+			i += 2;
+			v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8;
+			ud1.temp[2] = v * 0.1f;
+			i += 2;
+			v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8;
+			ud1.temp[3] = v * 0.1f;
+			i += 2;
+			v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8;
+			ud1.temp[4] = v * 0.1f;
+			i += 2;
+			v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8;
+			ud1.temp[5] = v * 0.1f;
+			i += 2;
+			v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8;
+			ud1.temp[6] = v * 0.1f;
+			i += 2;
+			v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8;
+			ud1.temp[7] = v * 0.1f;
+			i += 2;
+			v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8;
+			ud1.temp[8] = v * 0.1f;
+			i += 2;
+			v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8;
+			ud1.temp[9] = v * 0.1f;
+			i += 2;
+			v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8;
+			ud1.temp[10] = v * 0.1f;
+			i += 2;
+			v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8;
+			ud1.temp[11] = v * 0.1f;
+			LOGD("<CDataMonitor1-%d>温度:%f %f %f %f %f %f %f %f %f %f %f %f", m_nIndex,
+				ud1.temp[0], ud1.temp[1], ud1.temp[2], ud1.temp[3], ud1.temp[4],
+				ud1.temp[5], ud1.temp[6], ud1.temp[7], ud1.temp[8], ud1.temp[9], ud1.temp[10], ud1.temp[11]);
+
+
+			// 真空
+			i += 18;
+			ud1.vacuum = toFloat(&pszData[i]);
+			LOGD("<CDataMonitor1-%d>vacuum: %f", m_nIndex,
+				ud1.vacuum);
+
+
+			// 压力
+			i += 10;
+			ud1.pressure[0] = short((pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8);
+			i += 2;
+			ud1.pressure[1] = short((pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8);
+			i += 2;
+			ud1.pressure[2] = short((pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8);
+			i += 2;
+			ud1.pressure[3] = short((pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8);
+			i += 2;
+			ud1.pressure[4] = short((pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8);
+			LOGD("<CDataMonitor1-%d>pressure: %.03f %.03f %.03f %.03f %.03f", m_nIndex,
+				ud1.pressure[0], ud1.pressure[1], ud1.pressure[2], ud1.pressure[3], ud1.pressure[4]);
+
+			Lock();
+			size_t size = m_pActivePanel->addData(ud1);
+			Unlock();
+			int nSvTime = 15 * 60 * 5;
+			int nTvTime = (int)size;
+			if (nTvTime % (60 * 5) == 0 && nTvTime < nSvTime) {
+				pUnit->stepProcessing(m_pActivePanel->getQRCode().c_str(), 15, nTvTime / (60 * 5));
+			}
+
+			// unit data
+			CString strTmp, strAir, strPre;
+			for (int i = 0; i < 12; i++) {
+				strTmp.AppendFormat("%.2f,", ud1.temp[i]);
+			}
+			strTmp.Delete(strTmp.GetLength() - 1);
+			strAir.Format("%.2f", ud1.vacuum);
+			for (int i = 0; i < 5; i++) {
+				strPre.AppendFormat("%.2f,", ud1.pressure[i]);
+			}
+			strPre.Delete(strPre.GetLength() - 1);
+
+			pUnit->setDataTimeAndResetData(ud1.time);
+			pUnit->addData("TMP", (LPTSTR)(LPCTSTR)strTmp, false);
+			pUnit->addData("AIR", (LPTSTR)(LPCTSTR)strAir, false);
+			pUnit->addData("PRE", (LPTSTR)(LPCTSTR)strPre, m_bAutoSendData != FALSE);
+
+			SendBroadcast(&CIntent(BC_CODE_DATA1_UPDATE, "", nullptr));
+		}
+	}
+	else if (sampleFlag == STEP_END_SAMPLING) {
+		m_bSampling = FALSE;
+		WriteResultFlag(unitId, STEP_END_SAMPLING);
+
+		// 采样结束
+		if (m_pActivePanel != nullptr) {
+			m_pActivePanel->setStep(STEP_END_SAMPLING);
+			SendBroadcast(&CIntent(BC_CODE_DATA1_END_SAMPLING, "", nullptr));
+
+			pUnit->stepProcessingCompleted(m_pActivePanel->getQRCode().c_str());
+			LOGI("<CDataMonitor1-%d>采样结束.", m_nIndex);
+		}
+	}
+	else if (sampleFlag == STEP_REMOVED) {
+		WriteResultFlag(unitId, STEP_REMOVED);
+		if (m_pActivePanel != nullptr) {
+			// 20241111,客户要求新增出站时读取一大块参数
+			BOOL bReadOk;
+			bReadOk = m_pBonder->readDataBlocking(m_hRemoveEvent, MC::SOFT_COMPONENT::D,
+				5500, 800, &m_pszRemoveParamData[0]);
+			if (bReadOk) {
+				bReadOk = m_pBonder->readDataBlocking(m_hRemoveEvent, MC::SOFT_COMPONENT::D,
+					5900, 800, &m_pszRemoveParamData[800]);
+			}
+			if (bReadOk) {
+				bReadOk = m_pBonder->readDataBlocking(m_hRemoveEvent, MC::SOFT_COMPONENT::D,
+					6300, 800, &m_pszRemoveParamData[1600]);
+			}
+			if (bReadOk) {
+				m_pActivePanel->SetParamsRawData(m_pszRemoveParamData);
+			}
+
+			// 记录当前参数和配方
+			i = 70 * 2;
+			double air = toFloat(&pszData[i]);
+			m_pActivePanel->setAir1(air);
+			i += 4;
+			air = toFloat(&pszData[i]);
+			m_pActivePanel->setAir2(air);
+			i += 4;
+			air = toFloat(&pszData[i]);
+			m_pActivePanel->setAir3(air);
+			i += 4;
+			v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8 | (pszData[i + 2] & 0xff) << 16 | (pszData[i + 3] & 0xff) << 24;
+			m_pActivePanel->setPre1(v);
+			i += 4;
+			v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8;
+			m_pActivePanel->setTmp1(v * 0.1);
+			i += 4;
+			v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8;
+			m_pActivePanel->setTmp2(v * 0.1);
+			m_pActivePanel->setRecipeName(m_pBonder->getCurRecipeName().c_str());
+
+			LOGI("<CDataMonitor1-%d>Recipe:%s, 干泵吸真空值:%f,分子泵吸真空值:%f",
+				m_nIndex,
+				m_pActivePanel->getRecipeName().c_str(),
+				m_pActivePanel->getAir1(),
+				m_pActivePanel->getAir2());
+			LOGI("<CDataMonitor1-%d>气囊压力值:%f,贴合总压力:%d",
+				m_nIndex,
+				m_pActivePanel->getAir3(),
+				m_pActivePanel->getPre1());
+			LOGI("<CDataMonitor1-%d>上腔体温度:%f,下腔体温度:%f",
+				m_nIndex,
+				m_pActivePanel->getTmp1(),
+				m_pActivePanel->getTmp2());
+
+			m_pActivePanel->setStep(STEP_REMOVED);
+			SendBroadcast(&CIntent(BC_CODE_DATA1_MATERIAL_REMOVED, "", m_pActivePanel));
+			AddPanel(m_pActivePanel);
+
+			pUnit->stepMaterialRemoved(m_pActivePanel->getQRCode().c_str());
+			Sleep(50);
+			pUnit->stepIdle();
+
+			m_pActivePanel->release();
+			m_pActivePanel = nullptr;
+			LOGI("<CDataMonitor1-%d>出站.", m_nIndex);
+		}
+	}
+}
+
+CPanel* CDataMonitor1::getActivePanel()
+{
+	return m_pActivePanel;
+}
+
+void CDataMonitor1::setResponseAddr(int addr)
+{
+	m_nResponseAddr = addr;
+}
+
+void CDataMonitor1::enableAutoSendData(BOOL bEnable)
+{
+	m_bAutoSendData = bEnable;
+}
+
+const std::list<CPanel*>& CDataMonitor1::getPanels()
+{
+	return m_panels;
+}
+
+void CDataMonitor1::init()
+{
+	CComponent::init();
+}
+
+void CDataMonitor1::term()
+{
+	CComponent::term();
+}
+
+void CDataMonitor1::onRecvBroadcast(void* pSender, CIntent* pIntent)
+{
+
+}
+
+void CDataMonitor1::Serialize(CArchive& ar)
+{
+	if (ar.IsStoring())
+	{
+		Lock();
+		int count = (int)m_panels.size() + (m_pActivePanel != nullptr ? 1 : 0);
+		ar << count;
+		for (auto item : m_panels) {
+			item->Serialize(ar);
+		}
+		if (m_pActivePanel != nullptr) {
+			m_pActivePanel->Serialize(ar);
+		}
+		Unlock();
+	}
+	else
+	{
+		Lock();
+		int count;
+		ar >> count;
+		for (int i = 0; i < count; i++) {
+			CPanel* pPanel = new CPanel();
+			pPanel->addRef();
+			pPanel->Serialize(ar);
+			AddPanel(pPanel);
+			pPanel->release();
+			
+		}
+		Unlock();
+	}
+}
+
+void CDataMonitor1::AddPanel(CPanel* pPanel)
+{
+	pPanel->addRef();
+	m_panels.push_back(pPanel);
+	if (m_panels.size() > 4 * 24) {
+		CPanel* pTemp = m_panels.front();
+		pTemp->release();
+		m_panels.pop_front();
+	}
+}
+
+void CDataMonitor1::WriteResultFlag(int unitId, int flag)
+{
+	WriteInt(unitId, m_nResponseAddr, flag);
+}
+
diff --git a/SourceCode/Bond/BondEq/CDataMonitor1.h b/SourceCode/Bond/BondEq/CDataMonitor1.h
new file mode 100644
index 0000000..b3e217e
--- /dev/null
+++ b/SourceCode/Bond/BondEq/CDataMonitor1.h
@@ -0,0 +1,44 @@
+#pragma once
+#include "Component.h"
+#include "CPanel.h"
+#include <list>
+
+class CDataMonitor1 :
+    public CComponent
+{
+public:
+    CDataMonitor1();
+    virtual ~CDataMonitor1();
+    
+
+public:
+    virtual std::string& getClassName();
+	virtual void OnTimer(UINT nTimerid);
+	virtual void onData(int id, const void* pData, int size);
+	virtual void onRecvBroadcast(void* pSender, CIntent* pIntent);
+    virtual void init();
+	virtual void term();
+    virtual void Serialize(CArchive& ar);
+    const std::list<CPanel*>& getPanels();
+    CPanel* getActivePanel();
+	void setResponseAddr(int addr);
+	void enableAutoSendData(BOOL bEnable);
+
+private:
+    void AddPanel(CPanel* pPanel);
+	inline void WriteResultFlag(int unitId, int flag);
+
+private:
+    CPanel* m_pActivePanel;
+    std::list<CPanel*> m_panels;
+	int m_nResponseAddr;
+	BOOL m_bAutoSendData;
+	BOOL m_bSampling;
+	
+private:
+	HANDLE m_hRemoveEvent;
+	char* m_pszRemoveParamData;
+};
+
+
+
diff --git a/SourceCode/Bond/BondEq/CPLC.cpp b/SourceCode/Bond/BondEq/CPLC.cpp
new file mode 100644
index 0000000..9b1584c
--- /dev/null
+++ b/SourceCode/Bond/BondEq/CPLC.cpp
@@ -0,0 +1,314 @@
+#include "stdafx.h"
+#include "CPLC.h"
+#include "Log.h"
+
+void CALLBACK TimerFileProc(UINT uID, UINT uMsg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2)
+{
+	CPLC* pPlc = (CPLC*)dwUser;
+	SetEvent(pPlc->m_hTimeEvent);
+}
+
+unsigned __stdcall McMonitorThreadFunction(LPVOID lpParam)
+{
+	CPLC* pPlc = (CPLC*)lpParam;
+	return pPlc->onMonitor();
+}
+
+CPLC::CPLC()
+{
+	m_nPort = 0;
+	m_state = PLCSTATE::READY;
+	m_listener.onStateChanged = nullptr;
+	m_listener.onMonitorData = nullptr;
+	m_nUnHeartBeat = 0;
+	m_hMcMonitorStop = NULL;
+	m_hMcMonitorThreadHandle = NULL;
+	m_mcMonitorThrdaddr = 0;
+	m_nTimerId = 0;
+	m_hTimeEvent = nullptr;
+}
+
+CPLC::CPLC(const char* pszName, const char* pszIP, unsigned int nPort)
+{
+	m_strName = pszName;
+	m_strIP = pszIP;
+	m_nPort = nPort;
+	m_state = PLCSTATE::READY;
+	m_listener.onStateChanged = nullptr;
+	m_listener.onMonitorData = nullptr;
+	m_nUnHeartBeat = 0;
+	m_hMcMonitorStop = NULL;
+	m_hMcMonitorThreadHandle = NULL;
+	m_mcMonitorThrdaddr = 0;
+	m_nTimerId = 0;
+	m_hTimeEvent = nullptr;
+}
+
+CPLC::~CPLC()
+{
+
+}
+
+std::string& CPLC::getClassName()
+{
+	static std::string strClassName = "CPLC";
+	return strClassName;
+}
+
+void CPLC::setListener(PLCListener& listener)
+{
+	m_listener.onStateChanged = listener.onStateChanged;
+	m_listener.onMonitorData = listener.onMonitorData;
+}
+
+std::string& CPLC::getIP()
+{
+	return m_strIP;
+}
+
+unsigned int CPLC::getPort()
+{
+	return m_nPort;
+}
+
+int CPLC::addMonitor(int id, int beginAddr, int endAddr, MC::SOFT_COMPONENT softComponent, char* pszRecvBuffer)
+{
+	// 检查是否有重复的
+	Lock();
+	for (auto& m : m_monitors) {
+		if (m.id == id) {
+			Unlock();
+			return -1;
+		}
+	}
+
+	MONITOR m;
+	memset(&m, 0, sizeof(MONITOR));
+	m.id = id;
+	m.beginAddr = beginAddr;
+	m.readLen = (endAddr - beginAddr + 1) * 2;
+	m.softComponent = softComponent;
+	m.szRecvBuffer = pszRecvBuffer;
+	m.hEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
+	m_monitors.push_back(m);
+
+	Unlock();
+	return 0;
+}
+
+void CPLC::init()
+{
+	// mc channel
+	McChannelListener m_mcChannellistener;
+	m_mcChannellistener.funOnConnected = [&](IMcChannel* pChannel, int nErrorCode) -> void {
+		LOGI("<PLC-%s>连接结果<code= %d>", m_strName.c_str(), nErrorCode);
+		if (nErrorCode == 0) {
+			setState(PLCSTATE::CONNECTED);
+		}
+		else {
+			setState(PLCSTATE::DISCONNECTED);
+		}
+	};
+	m_mcChannellistener.funOnClose = [&](IMcChannel* pChannel) -> void {
+		setState(PLCSTATE::DISCONNECTED);
+	};
+	m_mcChannellistener.funOnClosing = [&](IMcChannel* pChannel) -> void {
+	};
+	m_mcChannellistener.funOnRead = [&](IMcChannel* pChannel, char* pData, unsigned int nDataSize, int nDecodeRet) -> void {
+		CString strText;
+		dataToHexString(pData, nDataSize, strText);
+		if (nDecodeRet != 0) {
+			LOGE("<PLC-%s>funOnRead[%s], nDecodeRet=%d", m_strName.c_str(), (LPTSTR)(LPCTSTR)strText, nDecodeRet);
+		}
+		m_nUnHeartBeat = 0;
+	};
+	m_mcChannellistener.funOnWrite = [&](IMcChannel* pChannel) -> void {
+
+	};
+
+	if (0 == MCL_CreateChannel(m_pChannel, m_strName.c_str(), m_strIP.c_str(), m_nPort, 0)
+		&& m_pChannel != NULL) {
+		m_pChannel->setChannelListener(&m_mcChannellistener);
+		m_pChannel->setActionInterval(m_nActionInterval);
+		LOGI("<PLC-%s>正在连接PLC.", m_strName.c_str());
+		setState(PLCSTATE::CONNECTING);
+		m_pChannel->connect();
+	}
+	else if (m_pChannel != NULL) {
+		m_pChannel->setChannelListener(&m_mcChannellistener);
+		m_pChannel->setActionInterval(m_nActionInterval);
+	}
+
+	m_hTimeEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
+	timeBeginPeriod(1);
+	m_nTimerId = timeSetEvent(200, 1, TimerFileProc, (DWORD_PTR)this, TIME_PERIODIC);
+
+
+	if (m_hMcMonitorStop != NULL) return;
+	m_hMcMonitorStop = ::CreateEvent(NULL, TRUE, FALSE, NULL);
+	m_hMcMonitorThreadHandle = (HANDLE)_beginthreadex(NULL, 0, ::McMonitorThreadFunction, this,
+		0, &m_mcMonitorThrdaddr);
+
+}
+
+void CPLC::term()
+{
+	timeKillEvent(m_nTimerId);
+	timeEndPeriod(1);		// 清除前面对定时器的设置
+
+	ASSERT(m_hMcMonitorStop);
+	SetEvent(m_hMcMonitorStop);
+	if (m_hMcMonitorThreadHandle != NULL) {
+		WaitForSingleObject(m_hMcMonitorThreadHandle, INFINITE);
+		CloseHandle(m_hMcMonitorThreadHandle);
+		m_hMcMonitorThreadHandle = NULL;
+	}
+	CloseHandle(m_hMcMonitorStop);
+	m_hMcMonitorStop = NULL;
+
+	for (auto& m : m_monitors) {
+		CloseHandle(m.hEvent);
+	}
+}
+
+unsigned CPLC::onMonitor()
+{
+	HANDLE hEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
+
+	int nReadLen = 60 * 2;
+	HANDLE hEvents[2] = { m_hMcMonitorStop, m_hTimeEvent };
+
+	while (1) {
+		int nRet = WaitForMultipleObjects(2, hEvents, FALSE, INFINITE);
+		ResetEvent(m_hTimeEvent);
+		if (nRet == WAIT_OBJECT_0) {
+			break;
+		}
+
+		if (!m_bRunning || !isConnected()) {
+			continue;
+		}
+
+		for (auto& m : m_monitors) {
+			monitorReadData(m);
+		}
+	}
+
+	TRACE("CPLC::onMonitor 线程退出\n");
+	return 0;
+}
+
+void CPLC::monitorReadData(MONITOR& monitor)
+{
+	BOOL bOutputLog = FALSE;
+	BOOL bReadOk;
+
+
+	// 批量读数据再解释
+	auto funOnReadData = [&](IMcChannel* pChannel, int addr, char* pData, unsigned int nDataSize, int flag) -> void {
+		if (flag == 0) {
+			if (bOutputLog) {
+				CString s;
+				s.Format(_T("CPLC::monitorReadData::funOnReadData %d ["), nDataSize);
+				for (unsigned int i = 0; i < nDataSize; i++) {
+					s.AppendFormat(" %x", (BYTE)pData[i]);
+				}
+				s.Append("]");
+				LOGD("<CPLC-%d-%d>Received plc data.%s", m_nIndex, monitor.id, (LPTSTR)(LPCTSTR)s);
+			}
+		}
+		else {
+			LOGE("<CPLC-%d-%d>PLC批读取数据位超时.flag=%d", m_nIndex, monitor.id, flag);
+		}
+
+		if (nDataSize == monitor.readLen && flag == 0) {
+			memcpy(monitor.szRecvBuffer, pData, nDataSize);
+			monitor.readCount++;
+			bReadOk = TRUE;
+		}
+		SetEvent(monitor.hEvent);
+	};
+
+
+	bReadOk = FALSE;
+	m_pChannel->readData(monitor.softComponent, monitor.beginAddr, monitor.readLen, funOnReadData);
+	WaitForSingleObject(monitor.hEvent, INFINITE);
+	ResetEvent(monitor.hEvent);
+	if (bReadOk) {
+		ASSERT(m_listener.onMonitorData);
+		m_listener.onMonitorData(this, monitor.id);
+	}
+}
+
+bool CPLC::isConnected()
+{
+	return m_pChannel->isConnected();
+}
+
+int CPLC::readWord(MC::SOFT_COMPONENT softComponent, unsigned int addr,
+	ONREAD funOnRead)
+{
+	return m_pChannel->readWord(softComponent, addr, funOnRead);
+}
+
+int CPLC::readData(MC::SOFT_COMPONENT softComponent, unsigned int addr,
+	unsigned int nReadLen, ONREADDATA funOnReadData)
+{
+	return m_pChannel->readData(softComponent, addr, nReadLen, funOnReadData);
+}
+
+int CPLC::writeBit(MC::SOFT_COMPONENT softComponent, unsigned int addr,
+	BOOL bValue, ONWRITE funOnWrite)
+{
+	return m_pChannel->writeBit(softComponent, addr, bValue, funOnWrite);
+}
+
+int CPLC::writeWord(MC::SOFT_COMPONENT softComponent, unsigned int addr,
+	int value, ONWRITE funOnWrite)
+{
+	return m_pChannel->writeWord(softComponent, addr, value, funOnWrite);
+}
+
+int CPLC::writeData(MC::SOFT_COMPONENT softComponent, unsigned int addr,
+	const char* pszData, unsigned int length, ONWRITE funOnWrite)
+{
+	return m_pChannel->writeData(softComponent, addr, pszData, length, funOnWrite);
+}
+
+CString& CPLC::dataToHexString(const char* pData, const int size, CString& strOut)
+{
+	strOut.Empty();
+	for (int i = 0; i < size; i++) {
+		if (i < size - 1) {
+			strOut.AppendFormat(_T("%02X "), (BYTE)pData[i]);
+		}
+		else {
+			strOut.AppendFormat(_T("%02X"), (BYTE)pData[i]);
+		}
+	}
+
+	return strOut;
+}
+
+void CPLC::setActionInterval(unsigned int nInterval)
+{
+	m_nActionInterval = nInterval;
+}
+
+void CPLC::setState(PLCSTATE state)
+{
+	m_state = state;
+	if (m_listener.onStateChanged != nullptr) {
+		m_listener.onStateChanged(this, (int)m_state);
+	}
+}
+
+void CPLC::OnTimer(UINT nTimerid)
+{
+	static int iii = 0;
+	iii++;
+	if (iii % 5 == 3) {
+		if (!m_pChannel->isConnected())
+			m_pChannel->connect();
+	}
+}
\ No newline at end of file
diff --git a/SourceCode/Bond/BondEq/CPLC.h b/SourceCode/Bond/BondEq/CPLC.h
new file mode 100644
index 0000000..89fded1
--- /dev/null
+++ b/SourceCode/Bond/BondEq/CPLC.h
@@ -0,0 +1,88 @@
+#pragma once
+#include "Component.h"
+#include <string>
+#include <functional>
+#include <vector>
+#include "MMSystem.h"
+#pragma comment(lib,"winmm")
+
+
+typedef std::function<void(void* pFrom, int)> ONPLCSTATECHANGED;
+typedef std::function<void(void* pFrom, int)> ONPLCMONITORDATA;
+typedef struct _PLCListener
+{
+	ONPLCSTATECHANGED		onStateChanged;
+	ONPLCMONITORDATA		onMonitorData;
+} PLCListener;
+
+typedef struct _MONITOR
+{
+	int id;
+	int beginAddr;
+	int readLen;
+	MC::SOFT_COMPONENT softComponent;
+	char* szRecvBuffer;
+	HANDLE hEvent;
+	ULONGLONG readCount;
+} MONITOR;
+
+enum class PLCSTATE
+{
+	READY = 0,
+	CONNECTING,
+	CONNECTED,
+	DISCONNECTED
+};
+
+class CPLC :
+	public CComponent
+{
+public:
+	CPLC();
+	CPLC(const char* pszName, const char* pszIP, unsigned int nPort);
+	virtual ~CPLC();
+
+public:
+	virtual std::string& getClassName();
+	void setListener(PLCListener& listener);
+	static CString& dataToHexString(const char* pData, const int size, CString& strOut);
+	void setActionInterval(unsigned int nInterval);
+	void init();
+	void term();
+	bool isConnected();
+	unsigned onMonitor();
+	void OnTimer(UINT nTimerid);
+	std::string& getIP();
+	unsigned int getPort();
+	int addMonitor(int id, int beginAddr, int endAddr, MC::SOFT_COMPONENT softComponent, char* pszRecvBuffer);
+	int readWord(MC::SOFT_COMPONENT softComponent, unsigned int addr, ONREAD funOnRead);
+	int readData(MC::SOFT_COMPONENT softComponent, unsigned int addr, unsigned int nReadLen, ONREADDATA funOnReadData);
+	int writeWord(MC::SOFT_COMPONENT softComponent, unsigned int addr, int value, ONWRITE funOnWrite);
+	int writeBit(MC::SOFT_COMPONENT softComponent, unsigned int addr, BOOL bValue, ONWRITE funOnWrite);
+	int writeData(MC::SOFT_COMPONENT softComponent, unsigned int addr, const char* pszData, unsigned int length, ONWRITE funOnWrite);
+
+private:
+	void setState(PLCSTATE state);
+	void monitorReadData(MONITOR& monitor);
+
+private:
+	std::string m_strName;
+	std::string m_strIP;
+	unsigned int m_nPort;
+	IMcChannel* m_pChannel;
+	PLCSTATE m_state;
+	unsigned int m_nActionInterval;
+	PLCListener m_listener;
+	unsigned int m_nUnHeartBeat;
+
+private:
+	std::vector<MONITOR> m_monitors;
+	HANDLE m_hMcMonitorStop;
+	HANDLE m_hMcMonitorThreadHandle;
+	unsigned m_mcMonitorThrdaddr;
+	MMRESULT m_nTimerId;
+
+public:
+	HANDLE m_hTimeEvent;
+};
+
diff --git a/SourceCode/Bond/BondEq/CPanel.cpp b/SourceCode/Bond/BondEq/CPanel.cpp
new file mode 100644
index 0000000..188c5fa
--- /dev/null
+++ b/SourceCode/Bond/BondEq/CPanel.cpp
@@ -0,0 +1,1006 @@
+#include "stdafx.h"
+#include "CPanel.h"
+#include "Log.h"
+#include "ToolUnits.h"
+
+
+CPanel::CPanel() : CContext()
+{
+	m_datas.reserve(PANEL_DATA_SIZE);
+	memset(&m_dataMath[ITOTAL], 0, sizeof(UNITDATA1));
+	memset(&m_dataMath[IAVE], 0, sizeof(UNITDATA1));
+	for (int i = 0; i < 10; i++) {
+		m_dataMath[IMAX].temp[i] = -99999999.0f;
+		m_dataMath[IMIN].temp[i] = 99999999.0f;
+	}
+	m_dataMath[IMAX].vacuum = -99999999.0f;
+	m_dataMath[IMIN].vacuum = 99999999.0f;
+	for (int i = 0; i < 5; i++) {
+		m_dataMath[IMAX].pressure[i] = -99999999.0f;
+		m_dataMath[IMIN].pressure[i] = 99999999.0f;
+	}
+
+	m_nUnitId = 0;
+	m_nStep = 0;
+	m_fAir1 = 0.0;
+	m_fAir2 = 0.0;
+	m_fAir3 = 0.0;
+	m_nPre1 = 0;
+	m_fTmp1 = 0.0;
+	m_fTmp2 = 0.0;
+	m_pszParamsRawData = new char[PARAM_RAWDATA_SIZE];
+	memset(m_pszParamsRawData, 0, PARAM_RAWDATA_SIZE);
+}
+
+CPanel::CPanel(const char* pszQRCode, int nUnitId) : CContext()
+{
+	m_strQRCode = pszQRCode;
+	m_datas.reserve(PANEL_DATA_SIZE);
+	memset(&m_dataMath[ITOTAL], 0, sizeof(UNITDATA1));
+	memset(&m_dataMath[IAVE], 0, sizeof(UNITDATA1));
+	for (int i = 0; i < 10; i++) {
+		m_dataMath[IMAX].temp[i] = -99999999.0f;
+		m_dataMath[IMIN].temp[i] = 99999999.0f;
+	}
+	m_dataMath[IMAX].vacuum = -99999999.0f;
+	m_dataMath[IMIN].vacuum = 99999999.0f;
+	for (int i = 0; i < 5; i++) {
+		m_dataMath[IMAX].pressure[i] = -99999999.0f;
+		m_dataMath[IMIN].pressure[i] = 99999999.0f;
+	}
+
+	m_nUnitId = nUnitId;
+	m_nStep = 0;
+	m_fAir1 = 0.0;
+	m_fAir2 = 0.0;
+	m_fAir3 = 0.0;
+	m_nPre1 = 0;
+	m_fTmp1 = 0.0;
+	m_fTmp2 = 0.0;
+	m_pszParamsRawData = new char[2048];
+	memset(m_pszParamsRawData, 0, 2048);
+}
+
+CPanel::~CPanel()
+{
+	m_datas.clear();
+	for (auto item : m_params) {
+		delete item;
+	}
+	m_params.clear();
+	if (m_pszParamsRawData != nullptr) {
+		delete[] m_pszParamsRawData;
+		m_pszParamsRawData = nullptr;
+	}
+}
+
+std::string& CPanel::getClassName()
+{
+	static std::string strName = "CPanel";
+	return strName;
+}
+
+std::string CPanel::toString()
+{
+	std::string strText;
+	strText += "CPanel[";
+	strText += ("QRCode:" + m_strQRCode + ";");
+	strText += "]";
+
+	return strText;
+}
+
+std::string& CPanel::getQRCode()
+{
+	return m_strQRCode;
+}
+
+void CPanel::setQRCode(const char* pszQRCode)
+{
+	m_strQRCode = pszQRCode;
+}
+
+int CPanel::getUnitId()
+{
+	return m_nUnitId;
+}
+
+void CPanel::setUnitId(int id)
+{
+	m_nUnitId = id;
+}
+
+void CPanel::setStep(int step)
+{
+	if (step == STEP_RECEIVED) {
+		m_timeReceived = CToolUnits::getTimestamp();
+	}
+	else if (step == STEP_BEGIN_SAMPLING) {
+		m_timeBeginSampling = CToolUnits::getTimestamp();
+	}
+	else if (step == STEP_END_SAMPLING) {
+		m_timeEndSampling = CToolUnits::getTimestamp();
+	}
+	else if (step == STEP_REMOVED) {
+		m_timeRemoved = CToolUnits::getTimestamp();
+	}
+
+	m_nStep = step;
+}
+
+int CPanel::getStep()
+{
+	return m_nStep;
+}
+
+int CPanel::addData(UNITDATA1& data)
+{
+	m_datas.push_back(data);
+	int size = (int)m_datas.size();
+
+	// 最大最小平均数计算
+	for (int i = 0; i < 10; i++) {
+		m_dataMath[ITOTAL].temp[i] += data.temp[i];
+		m_dataMath[IAVE].temp[i] = m_dataMath[ITOTAL].temp[i] / (float)size;
+		m_dataMath[IMAX].temp[i] = max(m_dataMath[IMAX].temp[i], data.temp[i]);
+		m_dataMath[IMIN].temp[i] = min(m_dataMath[IMIN].temp[i], data.temp[i]);
+	}
+	m_dataMath[ITOTAL].vacuum += data.vacuum;
+	m_dataMath[IAVE].vacuum = m_dataMath[ITOTAL].vacuum / (float)size;
+	m_dataMath[IMAX].vacuum = max(m_dataMath[IMAX].vacuum, data.vacuum);
+	m_dataMath[IMIN].vacuum = min(m_dataMath[IMIN].vacuum, data.vacuum);
+	for (int i = 0; i < 5; i++) {
+		m_dataMath[ITOTAL].pressure[i] += data.pressure[i];
+		m_dataMath[IAVE].pressure[i] = m_dataMath[ITOTAL].pressure[i] / (float)size;
+		m_dataMath[IMAX].pressure[i] = max(m_dataMath[IMAX].pressure[i], data.pressure[i]);
+		m_dataMath[IMIN].pressure[i] = min(m_dataMath[IMIN].pressure[i], data.pressure[i]);
+	}
+
+
+	return size;
+}
+
+const std::vector<UNITDATA1>& CPanel::getDatas()
+{
+	return m_datas;
+}
+
+void CPanel::getDatas(std::vector<UNITDATA1>& out)
+{
+	Lock();
+	out = m_datas;
+	Unlock();
+}
+
+BOOL CPanel::getNewestData(UNITDATA1& data)
+{
+	if (m_datas.empty()) return FALSE;
+	data = m_datas[m_datas.size() - 1];
+	return TRUE;
+}
+
+UNITDATA1& CPanel::getMathData(int index)
+{
+	ASSERT(0 <= index && index < 4);
+	return m_dataMath[index];
+}
+
+void CPanel::setMathData(int index, UNITDATA1& data)
+{
+	ASSERT(0 <= index && index < 4);
+	memcpy(&m_dataMath[index], &data, sizeof(UNITDATA1));
+}
+
+int CPanel::getBlodLen()
+{
+	return sizeof(UNITDATA1) * (4 + m_datas.size()) + PARAM_RAWDATA_SIZE;
+}
+
+int CPanel::getBlod(char* pszBuffer, int nBufferSize)
+{
+	int size = sizeof(UNITDATA1) * (4 + m_datas.size()) + PARAM_RAWDATA_SIZE;
+	if (nBufferSize < size)
+		return -1;
+	memcpy(pszBuffer, m_pszParamsRawData, PARAM_RAWDATA_SIZE);
+	pszBuffer += PARAM_RAWDATA_SIZE;
+
+	memcpy(pszBuffer, &m_dataMath[0], sizeof(UNITDATA1) * 4);
+	pszBuffer += sizeof(UNITDATA1) * 4;
+
+	for (auto& item : m_datas) {
+		memcpy(pszBuffer, &item, sizeof(UNITDATA1));
+		pszBuffer += sizeof(UNITDATA1);
+	}	
+
+	return size;
+}
+
+int CPanel::setBlod(char* pszBlod, int len)
+{
+	if (len < PARAM_RAWDATA_SIZE) return -1;
+
+	int count = (len - PARAM_RAWDATA_SIZE) / sizeof(UNITDATA1);
+	if (count < 4) return -2;
+
+	SetParamsRawData(m_pszParamsRawData);
+	pszBlod += PARAM_RAWDATA_SIZE;
+
+	memcpy(&m_dataMath[0], pszBlod, sizeof(UNITDATA1) * 4);
+	pszBlod += sizeof(UNITDATA1) * 4;
+
+	m_datas.clear();
+	for (int i = 4; i < count; i++) {
+		UNITDATA1 data;
+		memcpy(&data, pszBlod, sizeof(UNITDATA1));
+		m_datas.push_back(data);
+		pszBlod += sizeof(UNITDATA1);
+	}
+
+	return 0;
+}
+
+void CPanel::Serialize(CArchive& ar)
+{
+	if (ar.IsStoring())
+	{
+		Lock();
+		ar << m_timeReceived;
+		ar << m_timeBeginSampling;
+		ar << m_timeEndSampling;
+		ar << m_timeRemoved;
+		WriteString(ar, m_strQRCode);
+		ar << m_fAir1;
+		ar << m_fAir2;
+		ar << m_fAir3;
+		ar << m_nPre1;
+		ar << m_fTmp1;
+		ar << m_fTmp2;
+		WriteString(ar, m_strRecipeName);
+		int nCount = (int)m_datas.size();
+		ar << nCount;
+		for (auto& item : m_datas) {
+			ar.Write(&item, sizeof(UNITDATA1));
+		}
+		nCount = (int)m_params.size();
+		ar << nCount;
+		for (auto& item : m_params) {
+			item->Serialize(ar);
+		}
+		Unlock();
+	}
+	else
+	{
+		Lock();
+		ar >> m_timeReceived;
+		ar >> m_timeBeginSampling;
+		ar >> m_timeEndSampling;
+		ar >> m_timeRemoved;
+		ReadString(ar, m_strQRCode);
+		ar >> m_fAir1;
+		ar >> m_fAir2;
+		ar >> m_fAir3;
+		ar >> m_nPre1;
+		ar >> m_fTmp1;
+		ar >> m_fTmp2;
+		ReadString(ar, m_strRecipeName);
+		int nCount = 0;
+		ar >> nCount;
+		for (int i = 0; i < nCount; i++) {
+			UNITDATA1 ud1;
+			ar.Read(&ud1, sizeof(UNITDATA1));
+			m_datas.push_back(ud1);
+		}
+		ar >> nCount;
+		for (int i = 0; i < nCount; i++) {
+			CParam* pParam = new CParam();
+			pParam->Serialize(ar);
+			m_params.push_back(pParam);
+		}
+		Unlock();
+	}
+}
+
+bool CPanel::getReceivedTime(int& year, int& month, int& day)
+{
+	ULONGLONG time1;
+	time1 = m_timeReceived / 1000;
+
+	struct tm timeinfo;
+	time_t t = time_t(time1);
+	localtime_s(&timeinfo, &t);
+	year = timeinfo.tm_year + 1900;
+	month = timeinfo.tm_mon + 1;
+	day = timeinfo.tm_mday;
+
+	return true;
+}
+
+ULONG64 CPanel::GetCurrentSampleTime()
+{
+	return m_timeBeginSampling + m_datas.size() * 200;
+}
+
+ULONGLONG CPanel::getReceivedTime()
+{
+	return m_timeReceived;
+}
+
+void CPanel::setReceivedTime(ULONGLONG time)
+{
+	m_timeReceived = time;
+}
+
+ULONGLONG CPanel::getBeginSamplingTime()
+{
+	return m_timeBeginSampling;
+}
+
+void CPanel::setBeginSamplingTime(ULONGLONG time)
+{
+	m_timeBeginSampling = time;
+}
+
+ULONGLONG CPanel::getEndSamplingTime()
+{
+	return m_timeEndSampling;
+}
+
+void CPanel::setEndSamplingTime(ULONGLONG time)
+{
+	m_timeEndSampling = time;
+}
+
+ULONGLONG CPanel::getRemovedTime()
+{
+	return m_timeRemoved;
+}
+
+void CPanel::setRemovedTime(ULONGLONG time)
+{
+	m_timeRemoved = time;
+}
+
+void CPanel::setRecipeName(const char* pszName)
+{
+	m_strRecipeName = pszName;
+}
+
+std::string& CPanel::getRecipeName()
+{
+	return m_strRecipeName;
+}
+
+void CPanel::setAir1(double air)
+{
+	m_fAir1 = air;
+}
+
+double CPanel::getAir1()
+{
+	return m_fAir1;
+}
+
+void CPanel::setAir2(double air)
+{
+	m_fAir2 = air;
+}
+
+double CPanel::getAir2()
+{
+	return m_fAir2;
+}
+
+void CPanel::setAir3(double air)
+{
+	m_fAir3 = air;
+}
+
+double CPanel::getAir3()
+{
+	return m_fAir3;
+}
+
+void CPanel::setPre1(int pre)
+{
+	m_nPre1 = pre;
+}
+
+int CPanel::getPre1()
+{
+	return m_nPre1;
+}
+
+void CPanel::setTmp1(double tmp)
+{
+	m_fTmp1 = tmp;
+}
+
+double CPanel::getTmp1()
+{
+	return m_fTmp1;
+}
+
+void CPanel::setTmp2(double tmp)
+{
+	m_fTmp2 = tmp;
+}
+
+double CPanel::getTmp2()
+{
+	return m_fTmp2;
+}
+
+void CPanel::addIntParam(const char* pszName, const char* pszUnit, int value)
+{
+	CParam* pParam = new CParam(pszName, pszUnit, value);
+	m_params.push_back(pParam);
+}
+
+void CPanel::addDoubleParam(const char* pszName, const char* pszUnit, double value)
+{
+	CParam* pParam = new CParam(pszName, pszUnit, value);
+	m_params.push_back(pParam);
+}
+
+std::vector<CParam*>& CPanel::getParams()
+{
+	return m_params;
+}
+
+void CPanel::SetParamsRawData(const char* pszData)
+{
+	memcpy(m_pszParamsRawData, pszData, PARAM_RAWDATA_SIZE);
+
+	// 解释数据到m_params中
+	BOOL bUnitA = TRUE, bUnitB = TRUE;
+	int i, v, startAddr = 5500;
+
+	if (bUnitA) {
+		i = (5520 - startAddr) * 2;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8;
+		addIntParam("A单元_下腔体吸真空延时", "", v);
+
+		i += 2;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8;
+		addIntParam("A单元_干泵吸真空延时", "", v);
+
+		i += 2;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8;
+		addIntParam("B单元_分子泵吸真空延时", "", v);
+	}
+
+	if (bUnitB) {
+		i = (5540 - startAddr) * 2;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8;
+		addIntParam("B单元_下腔体吸真空延时", "", v);
+
+		i += 2;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8;
+		addIntParam("B单元_干泵吸真空延时", "", v);
+
+		i += 2;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8;
+		addIntParam("B单元_分子泵吸真空延时", "", v);
+	}
+
+	if (bUnitA) {
+		i = (5600 - startAddr) * 2;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8 | (pszData[i + 2] & 0xff) << 16 | (pszData[i + 3] & 0xff) << 24;
+		addIntParam("A单元_上腔体至待预热位速度", "", v);
+
+		i += 4;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8 | (pszData[i + 2] & 0xff) << 16 | (pszData[i + 3] & 0xff) << 24;
+		addIntParam("A单元_上腔体至预热位速度", "", v);
+
+		i += 4;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8 | (pszData[i + 2] & 0xff) << 16 | (pszData[i + 3] & 0xff) << 24;
+		addIntParam("A单元_上腔体预压速度", "", v);
+
+		i += 4;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8 | (pszData[i + 2] & 0xff) << 16 | (pszData[i + 3] & 0xff) << 24;
+		addIntParam("A单元_上腔体压合速度", "", v);
+
+		i += 4;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8;
+		addDoubleParam("A单元_上腔体保压时间", "秒", (double)v * 0.1);
+
+		i += 4;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8;
+		addDoubleParam("A单元_上腔体水冷时间", "秒", (double)v * 0.1);
+
+		i += 2;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8;
+		addDoubleParam("A单元_预热延时", "秒", (double)v * 0.1);
+
+		i += 2;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8;
+		addIntParam("A单元_分离膜使用次数", "", v);
+
+		i += 4;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8;
+		addIntParam("A单元分离膜次数设定", "", v);
+
+		i += 4;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8 | (pszData[i + 2] & 0xff) << 16 | (pszData[i + 3] & 0xff) << 24;
+		addIntParam("A单元_分离速度", "", v);
+
+		i += 4;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8;
+		addDoubleParam("A单元_上腔体初始力矩值", "%", (double)v * 0.1);
+
+		i += 2;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8;
+		addDoubleParam("A单元_上腔体M1轴力矩值", "%", (double)v * 0.1);
+
+		i += 2;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8;
+		addDoubleParam("A单元_上腔体M2轴力矩值", "%", (double)v * 0.1);
+
+		i += 2;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8;
+		addDoubleParam("A单元_上腔体M3轴力矩值", "%", (double)v * 0.1);
+
+		i += 2;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8;
+		addDoubleParam("A单元_上腔体M4轴力矩值", "%", (double)v * 0.1);
+
+		i += 2;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8;
+		addDoubleParam("A单元_上腔体M5轴力矩值", "%", (double)v * 0.1);
+
+		i += 2;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8 | (pszData[i + 2] & 0xff) << 16 | (pszData[i + 3] & 0xff) << 24;
+		addIntParam("A单元_上腔体5轴力矩压合速度", "", v);
+
+		i += 4;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8;
+		addIntParam("A单元_上腔体M1轴压合压力", "kg", v);
+
+		i += 2;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8;
+		addIntParam("A单元_上腔体M2轴压合压力", "kg", v);
+
+		i += 2;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8;
+		addIntParam("A单元_上腔体M3轴压合压力", "kg", v);
+
+		i += 2;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8;
+		addIntParam("A单元_上腔体M4轴压合压力", "kg", v);
+
+		i += 2;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8;
+		addIntParam("A单元_上腔体M5轴压合压力", "kg", v);
+
+		i += 4;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8;
+		addIntParam("A单元_上腔体Z轴压合总压力", "kg", v);
+
+		i += 4;
+		addDoubleParam("A单元_气囊当前压力", "", (double)toFloat(&pszData[i]));
+
+		i += 4;
+		addDoubleParam("A单元_贴合气囊压力设定值", "", (double)toFloat(&pszData[i]));
+
+		i += 4;
+		addDoubleParam("A单元_气囊压缩率", "", (double)toFloat(&pszData[i]));
+
+		i += 4;
+		addDoubleParam("A单元_上腔体初始温度", "", (double)toFloat(&pszData[i]));
+
+		i += 4;
+		addDoubleParam("A单元_下腔体初始温度", "", (double)toFloat(&pszData[i]));
+
+		i += 4;
+		addDoubleParam("A单元_干泵抽真空设定值", "", (double)toFloat(&pszData[i]));
+
+		i += 4;
+		addDoubleParam("A单元_分子泵抽真空设定值", "", (double)toFloat(&pszData[i]));
+
+		i += 4;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8 | (pszData[i + 2] & 0xff) << 16 | (pszData[i + 3] & 0xff) << 24;
+		addIntParam("A单元_顶PIN下降速度", "", v);
+
+		i += 4;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8;
+		addDoubleParam("A单元_干泵气阀关闭延时", "", (double)v * 0.1);
+
+		i += 4;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8 | (pszData[i + 2] & 0xff) << 16 | (pszData[i + 3] & 0xff) << 24;
+		addIntParam("A单元_上腔Z轴压入量补偿值", "", v);
+
+		i += 4;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8;
+		addDoubleParam("A单元_收膜力矩值", "%", (double)v * 0.1);
+
+		i += 4;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8;
+		addDoubleParam("A单元_放膜力矩值", "%", (double)v * 0.1);
+
+		i += 4;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8 | (pszData[i + 2] & 0xff) << 16 | (pszData[i + 3] & 0xff) << 24;
+		addIntParam("A单元_力矩电机转速", "", v);
+
+		i += 4;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8 | (pszData[i + 2] & 0xff) << 16 | (pszData[i + 3] & 0xff) << 24;
+		addIntParam("A单元_分离距离补偿值", "", v);
+
+		i += 4;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8;
+		addIntParam("A单元_上腔体冷却温度", "", v);
+
+		i += 2;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8;
+		addIntParam("A单元_下腔体冷却温度", "", v);
+
+		i += 2;
+		addIntParam("A单元_压感压纸气囊压力设定值", "", (double)toFloat(&pszData[i]));
+
+		i += 4;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8;
+		addDoubleParam("A单元_主轴力矩增速率", "%", (double)v * 0.1);
+
+		i += 4;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8;
+		addDoubleParam("A单元_主轴力矩上限", "%", (double)v * 0.1);
+
+		i += 4;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8;
+		addDoubleParam("A单元_主轴力矩减速率", "%", (double)v * 0.1);
+
+		i += 12;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8 | (pszData[i + 2] & 0xff) << 16 | (pszData[i + 3] & 0xff) << 24;
+		addIntParam("A单元_上腔体分离膜高度补偿", "", v);
+
+		i += 4;
+		addDoubleParam("A单元_上腔体压合温度", "", (double)toFloat(&pszData[i]));
+
+		i += 4;
+		addDoubleParam("A单元_下腔体压合温度", "", (double)toFloat(&pszData[i]));
+
+		i += 4;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8;
+		addIntParam("A单元_上腔体Z轴初始压合压力", "kg", v);
+
+		i += 4;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8;
+		addIntParam("A单元_Step1超时设定", "", v);
+
+		i += 2;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8;
+		addIntParam("A单元_Step2超时设定", "", v);
+
+		i += 2;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8;
+		addIntParam("A单元_Step3超时设定", "", v);
+
+		i += 2;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8;
+		addIntParam("A单元_Step4超时设定", "", v);
+
+		i += 2;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8;
+		addIntParam("A单元_Step5超时设定", "", v);
+
+		i += 2;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8;
+		addIntParam("A单元_Step6超时设定", "", v);
+
+		i += 2;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8;
+		addDoubleParam("A单元_上腔体M1轴力矩值%-临时", "%", (double)v * 0.1);
+
+		i += 2;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8;
+		addDoubleParam("A单元_上腔体M2轴力矩值%-临时", "%", (double)v * 0.1);
+
+		i += 2;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8;
+		addDoubleParam("A单元_上腔体M3轴力矩值%-临时", "%", (double)v * 0.1);
+
+		i += 2;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8;
+		addDoubleParam("A单元_上腔体M4轴力矩值%-临时", "%", (double)v * 0.1);
+
+		i += 2;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8;
+		addDoubleParam("A单元_上腔体M5轴力矩值%-临时", "%", (double)v * 0.1);
+	}
+
+	if (bUnitB) {
+		i = (5700 - startAddr) * 2;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8 | (pszData[i + 2] & 0xff) << 16 | (pszData[i + 3] & 0xff) << 24;
+		addIntParam("B单元_上腔体至待预热位速度", "", v);
+
+		i += 4;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8 | (pszData[i + 2] & 0xff) << 16 | (pszData[i + 3] & 0xff) << 24;
+		addIntParam("B单元_上腔体至预热位速度", "", v);
+
+		i += 4;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8 | (pszData[i + 2] & 0xff) << 16 | (pszData[i + 3] & 0xff) << 24;
+		addIntParam("B单元_上腔体预压速度", "", v);
+
+		i += 4;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8 | (pszData[i + 2] & 0xff) << 16 | (pszData[i + 3] & 0xff) << 24;
+		addIntParam("B单元_上腔体压合速度", "", v);
+
+		i += 4;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8;
+		addDoubleParam("B单元_上腔体保压时间", "秒", (double)v * 0.1);
+
+		i += 4;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8;
+		addDoubleParam("B单元_上腔体水冷时间", "秒", (double)v * 0.1);
+
+		i += 2;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8;
+		addDoubleParam("B单元_预热延时", "秒", (double)v * 0.1);
+
+		i += 2;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8;
+		addIntParam("B单元_分离膜使用次数", "", v);
+
+		i += 4;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8;
+		addIntParam("B单元分离膜次数设定", "", v);
+
+		i += 4;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8 | (pszData[i + 2] & 0xff) << 16 | (pszData[i + 3] & 0xff) << 24;
+		addIntParam("B单元_分离速度", "", v);
+
+		i += 4;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8;
+		addDoubleParam("B单元_上腔体初始力矩值", "%", (double)v * 0.1);
+
+		i += 2;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8;
+		addDoubleParam("B单元_上腔体M1轴力矩值", "%", (double)v * 0.1);
+
+		i += 2;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8;
+		addDoubleParam("B单元_上腔体M2轴力矩值", "%", (double)v * 0.1);
+
+		i += 2;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8;
+		addDoubleParam("B单元_上腔体M3轴力矩值", "%", (double)v * 0.1);
+
+		i += 2;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8;
+		addDoubleParam("B单元_上腔体M4轴力矩值", "%", (double)v * 0.1);
+
+		i += 2;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8;
+		addDoubleParam("B单元_上腔体M5轴力矩值", "%", (double)v * 0.1);
+
+		i += 2;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8 | (pszData[i + 2] & 0xff) << 16 | (pszData[i + 3] & 0xff) << 24;
+		addIntParam("B单元_上腔体5轴力矩压合速度", "", v);
+
+		i += 4;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8;
+		addIntParam("B单元_上腔体M1轴压合压力", "kg", v);
+
+		i += 2;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8;
+		addIntParam("B单元_上腔体M2轴压合压力", "kg", v);
+
+		i += 2;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8;
+		addIntParam("B单元_上腔体M3轴压合压力", "kg", v);
+
+		i += 2;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8;
+		addIntParam("B单元_上腔体M4轴压合压力", "kg", v);
+
+		i += 2;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8;
+		addIntParam("B单元_上腔体M5轴压合压力", "kg", v);
+
+		i += 4;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8;
+		addIntParam("B单元_上腔体Z轴压合总压力", "kg", v);
+
+		i += 4;
+		addDoubleParam("B单元_气囊当前压力", "", (double)toFloat(&pszData[i]));
+
+		i += 4;
+		addDoubleParam("B单元_贴合气囊压力设定值", "", (double)toFloat(&pszData[i]));
+
+		i += 4;
+		addDoubleParam("B单元_气囊压缩率", "", (double)toFloat(&pszData[i]));
+
+		i += 4;
+		addDoubleParam("B单元_上腔体初始温度", "", (double)toFloat(&pszData[i]));
+
+		i += 4;
+		addDoubleParam("B单元_下腔体初始温度", "", (double)toFloat(&pszData[i]));
+
+		i += 4;
+		addDoubleParam("B单元_干泵抽真空设定值", "", (double)toFloat(&pszData[i]));
+
+		i += 4;
+		addDoubleParam("B单元_分子泵抽真空设定值", "", (double)toFloat(&pszData[i]));
+
+		i += 4;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8 | (pszData[i + 2] & 0xff) << 16 | (pszData[i + 3] & 0xff) << 24;
+		addIntParam("B单元_顶PIN下降速度", "", v);
+
+		i += 4;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8;
+		addDoubleParam("B单元_干泵气阀关闭延时", "", (double)v * 0.1);
+
+		i += 4;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8 | (pszData[i + 2] & 0xff) << 16 | (pszData[i + 3] & 0xff) << 24;
+		addIntParam("B单元_上腔Z轴压入量补偿值", "", v);
+
+		i += 4;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8;
+		addDoubleParam("B单元_收膜力矩值", "%", (double)v * 0.1);
+
+		i += 4;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8;
+		addDoubleParam("B单元_放膜力矩值", "%", (double)v * 0.1);
+
+		i += 4;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8 | (pszData[i + 2] & 0xff) << 16 | (pszData[i + 3] & 0xff) << 24;
+		addIntParam("B单元_力矩电机转速", "", v);
+
+		i += 4;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8 | (pszData[i + 2] & 0xff) << 16 | (pszData[i + 3] & 0xff) << 24;
+		addIntParam("B单元_分离距离补偿值", "", v);
+
+		i += 4;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8;
+		addIntParam("B单元_上腔体冷却温度", "", v);
+
+		i += 2;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8;
+		addIntParam("B单元_下腔体冷却温度", "", v);
+
+		i += 2;
+		addIntParam("B单元_压感压纸气囊压力设定值", "", (double)toFloat(&pszData[i]));
+
+		i += 4;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8;
+		addDoubleParam("B单元_主轴力矩增速率", "%", (double)v * 0.1);
+
+		i += 4;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8;
+		addDoubleParam("B单元_主轴力矩上限", "%", (double)v * 0.1);
+
+		i += 4;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8;
+		addDoubleParam("B单元_主轴力矩减速率", "%", (double)v * 0.1);
+
+		i += 12;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8 | (pszData[i + 2] & 0xff) << 16 | (pszData[i + 3] & 0xff) << 24;
+		addIntParam("B单元_上腔体分离膜高度补偿", "", v);
+
+		i += 4;
+		addDoubleParam("B单元_上腔体压合温度", "", (double)toFloat(&pszData[i]));
+
+		i += 4;
+		addDoubleParam("B单元_下腔体压合温度", "", (double)toFloat(&pszData[i]));
+
+		i += 4;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8;
+		addIntParam("B单元_上腔体Z轴初始压合压力", "kg", v);
+
+		i += 4;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8;
+		addIntParam("B单元_Step1超时设定", "", v);
+
+		i += 2;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8;
+		addIntParam("B单元_Step2超时设定", "", v);
+
+		i += 2;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8;
+		addIntParam("B单元_Step3超时设定", "", v);
+
+		i += 2;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8;
+		addIntParam("B单元_Step4超时设定", "", v);
+
+		i += 2;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8;
+		addIntParam("B单元_Step5超时设定", "", v);
+
+		i += 2;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8;
+		addIntParam("B单元_Step6超时设定", "", v);
+
+		i += 2;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8;
+		addDoubleParam("B单元_上腔体M1轴力矩值%-临时", "%", (double)v * 0.1);
+
+		i += 2;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8;
+		addDoubleParam("B单元_上腔体M2轴力矩值%-临时", "%", (double)v * 0.1);
+
+		i += 2;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8;
+		addDoubleParam("B单元_上腔体M3轴力矩值%-临时", "%", (double)v * 0.1);
+
+		i += 2;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8;
+		addDoubleParam("B单元_上腔体M4轴力矩值%-临时", "%", (double)v * 0.1);
+
+		i += 2;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8;
+		addDoubleParam("B单元_上腔体M5轴力矩值%-临时", "%", (double)v * 0.1);
+	}
+
+	i = (5800 - startAddr) * 2;
+	v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8;
+	addDoubleParam("冷却柜冷却时间", "", (double)v * 0.1);
+
+	if (bUnitA) {
+		i = (5840 - startAddr) * 2;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8;
+		addDoubleParam("A单元_温度上公差", "度", (double)v * 0.1);
+
+		i += 4;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8;
+		addDoubleParam("A单元_温度下公差", "度", (double)v * 0.1);
+
+		i += 4;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8 | (pszData[i + 2] & 0xff) << 16 | (pszData[i + 3] & 0xff) << 24;
+		addIntParam("A单元_压力上公差", "", v);
+
+		i += 4;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8 | (pszData[i + 2] & 0xff) << 16 | (pszData[i + 3] & 0xff) << 24;
+		addIntParam("A单元_压力下公差", "", v);
+
+		i += 4;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8 | (pszData[i + 2] & 0xff) << 16 | (pszData[i + 3] & 0xff) << 24;
+		addIntParam("A单元_顶Pin慢速上升速度", "", v);
+
+		i += 4;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8 | (pszData[i + 2] & 0xff) << 16 | (pszData[i + 3] & 0xff) << 24;
+		addIntParam("A单元_上腔体升到零点位速度", "", v);
+
+		i += 4;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8 | (pszData[i + 2] & 0xff) << 16 | (pszData[i + 3] & 0xff) << 24;
+		addIntParam("A单元_慢速上升距离", "", v);
+
+		i += 4;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8;
+		addIntParam("A单元_顶Pin破真空延时", "", v);
+	}
+
+	if (bUnitB) {
+		i = (5870 - startAddr) * 2;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8;
+		addDoubleParam("B单元_温度上公差", "度", (double)v * 0.1);
+
+		i += 4;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8;
+		addDoubleParam("B单元_温度下公差", "度", (double)v * 0.1);
+
+		i += 4;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8 | (pszData[i + 2] & 0xff) << 16 | (pszData[i + 3] & 0xff) << 24;
+		addIntParam("B单元_压力上公差", "", v);
+
+		i += 4;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8 | (pszData[i + 2] & 0xff) << 16 | (pszData[i + 3] & 0xff) << 24;
+		addIntParam("B单元_压力下公差", "", v);
+
+		i += 4;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8 | (pszData[i + 2] & 0xff) << 16 | (pszData[i + 3] & 0xff) << 24;
+		addIntParam("B单元_顶Pin慢速上升速度", "", v);
+
+		i += 4;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8 | (pszData[i + 2] & 0xff) << 16 | (pszData[i + 3] & 0xff) << 24;
+		addIntParam("B单元_上腔体升到零点位速度", "", v);
+
+		i += 4;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8 | (pszData[i + 2] & 0xff) << 16 | (pszData[i + 3] & 0xff) << 24;
+		addIntParam("B单元_慢速上升距离", "", v);
+
+		i += 4;
+		v = (m_pszParamsRawData[i] & 0xff) | (m_pszParamsRawData[i + 1] & 0xff) << 8;
+		addIntParam("B单元_顶Pin破真空延时", "", v);
+	}
+}
+
diff --git a/SourceCode/Bond/BondEq/CPanel.h b/SourceCode/Bond/BondEq/CPanel.h
new file mode 100644
index 0000000..fa2020a
--- /dev/null
+++ b/SourceCode/Bond/BondEq/CPanel.h
@@ -0,0 +1,101 @@
+#pragma once
+#include "Context.h"
+#include "Common.h"
+#include <vector>
+#include "CParam.h"
+
+#define ITOTAL		0
+#define IMAX		1
+#define IMIN		2
+#define IAVE		3
+
+#define PANEL_DATA_SIZE		5 * 60 * 15
+#define PARAM_RAWDATA_SIZE	4096
+
+#define STEP_READY				0
+#define STEP_RECEIVED			20
+#define STEP_BEGIN_SAMPLING		1
+#define STEP_END_SAMPLING		2
+#define STEP_REMOVED			30
+
+class CPanel :
+	public CContext
+{
+public:
+	CPanel();
+	CPanel(const char* pszQRCode, int nUnitId);
+	virtual ~CPanel();
+
+public:
+	virtual std::string& getClassName();
+	virtual std::string toString();
+	std::string& getQRCode();
+	void setQRCode(const char* pszQRCode);
+	int getUnitId();
+	void setUnitId(int id);
+	void setStep(int step);
+	int getStep();
+	int addData(UNITDATA1& data);
+	const std::vector<UNITDATA1>& getDatas();
+	void Serialize(CArchive& ar);
+	bool getReceivedTime(int& year, int& month, int& day);
+	ULONG64 GetCurrentSampleTime();
+	ULONGLONG getReceivedTime();
+	void setReceivedTime(ULONGLONG time);
+	ULONGLONG getBeginSamplingTime();
+	void setBeginSamplingTime(ULONGLONG time);
+	ULONGLONG getEndSamplingTime();
+	void setEndSamplingTime(ULONGLONG time);
+	ULONGLONG getRemovedTime();
+	void setRemovedTime(ULONGLONG time);
+	void getDatas(std::vector<UNITDATA1>& out);
+	BOOL getNewestData(UNITDATA1& data);
+	UNITDATA1& getMathData(int index);
+	void setMathData(int index, UNITDATA1& data);
+	int getBlodLen();
+	int getBlod(char* pszBuffer, int nBufferSize);
+	int setBlod(char* pszBlod, int len);
+
+public:
+	void setRecipeName(const char* pszName);
+	std::string& getRecipeName();
+	void setAir1(double air);
+	double getAir1();
+	void setAir2(double air);
+	double getAir2();
+	void setAir3(double air);
+	double getAir3();
+	void setPre1(int pre);
+	int getPre1();
+	void setTmp1(double tmp);
+	double getTmp1();
+	void setTmp2(double tmp);
+	double getTmp2();
+	void addIntParam(const char* pszName, const char* pszUnit, int value);
+	void addDoubleParam(const char* pszName, const char* pszUnit, double value);
+	std::vector<CParam*>& getParams();
+	void SetParamsRawData(const char* pszData);
+
+private:
+	std::string m_strQRCode;
+	int m_nUnitId;
+	std::vector<UNITDATA1> m_datas;
+	UNITDATA1 m_dataMath[4];			// 0:汇总;1:最大;2:最小;3:平均
+	ULONG64 m_timeBeginSampling;
+	ULONG64 m_timeEndSampling;
+	ULONG64 m_timeReceived;
+	ULONG64 m_timeRemoved;
+
+private:
+	int m_nStep;			// 当前步骤;
+	std::string m_strRecipeName;
+	double m_fAir1;			// 干泵吸真空值
+	double m_fAir2;			// 分子泵吸真空值
+	double m_fAir3;			// 气囊压力值
+	int m_nPre1;			// 贴合总压力
+	double m_fTmp1;			// 上腔体温度
+	double m_fTmp2;			// 下腔体温度
+	char* m_pszParamsRawData;
+	std::vector<CParam*> m_params;			// 出站时记录参数
+};
+
diff --git a/SourceCode/Bond/BondEq/CParam.cpp b/SourceCode/Bond/BondEq/CParam.cpp
new file mode 100644
index 0000000..3cfe6f9
--- /dev/null
+++ b/SourceCode/Bond/BondEq/CParam.cpp
@@ -0,0 +1,90 @@
+#include "stdafx.h"
+#include "CParam.h"
+
+
+CParam::CParam()
+{
+	m_nValueType = PVT_INT;
+	m_nValue = 0;
+	m_fValue = 0.0;
+}
+
+CParam::CParam(const char* pszName, const char* pszUnit, int value)
+{
+	m_nValueType = PVT_INT;
+	m_nValue = value;
+	m_fValue = 0.0;
+	m_strName = pszName;
+	m_strUnit = pszUnit;
+}
+
+CParam::CParam(const char* pszName, const char* pszUnit, double value)
+{
+	m_nValueType = PVT_DOUBLE;
+	m_nValue = 0;
+	m_fValue = value;
+	m_strName = pszName;
+	m_strUnit = pszUnit;
+}
+
+CParam::~CParam()
+{
+}
+
+std::string& CParam::getName()
+{
+	return m_strName;
+}
+
+std::string& CParam::getUnit()
+{
+	return m_strUnit;
+}
+
+int CParam::getValueType()
+{
+	return m_nValueType;
+}
+
+int CParam::getIntValue()
+{
+	return m_nValue;
+}
+
+double CParam::getDoubleValue()
+{
+	return m_fValue;
+}
+
+void CParam::Serialize(CArchive& ar)
+{
+	if (ar.IsStoring())
+	{
+		WriteString(ar, m_strName);
+		WriteString(ar, m_strUnit);
+		ar << m_nValueType;
+		ar << m_nValue;
+		ar << m_fValue;
+	}
+	else
+	{
+		ReadString(ar, m_strName);
+		ReadString(ar, m_strUnit);
+		ar >> m_nValueType;
+		ar >> m_nValue;
+		ar >> m_fValue;
+	}
+}
+
+void CParam::ReadString(CArchive& ar, std::string& string)
+{
+	CString strTemp;
+	ar >> strTemp;
+	string = (LPTSTR)(LPCTSTR)strTemp;
+}
+
+void CParam::WriteString(CArchive& ar, std::string& string)
+{
+	CString strTemp = string.c_str();
+	ar << strTemp;
+}
diff --git a/SourceCode/Bond/BondEq/CParam.h b/SourceCode/Bond/BondEq/CParam.h
new file mode 100644
index 0000000..ebe127e
--- /dev/null
+++ b/SourceCode/Bond/BondEq/CParam.h
@@ -0,0 +1,34 @@
+#pragma once
+#include <string>
+
+#define PVT_INT		0
+#define PVT_DOUBLE	1
+
+class CParam
+{
+public:
+	CParam();
+	CParam(const char* pszName, const char* pszUnit, int value);
+	CParam(const char* pszName, const char* pszUnit, double value);
+	~CParam();
+
+public:
+	std::string& getName();
+	std::string& getUnit();
+	int getValueType();
+	int getIntValue();
+	double getDoubleValue();
+	void Serialize(CArchive& ar);
+
+private:
+	void ReadString(CArchive& ar, std::string& string);
+	void WriteString(CArchive& ar, std::string& string);
+
+private:
+	int m_nValueType;
+	std::string m_strName;
+	std::string m_strUnit;
+	int m_nValue;
+	double m_fValue;
+};
+
diff --git a/SourceCode/Bond/BondEq/Common.h b/SourceCode/Bond/BondEq/Common.h
index 0dadb20..d37499f 100644
--- a/SourceCode/Bond/BondEq/Common.h
+++ b/SourceCode/Bond/BondEq/Common.h
@@ -4,6 +4,11 @@
 #define MC_TIME_SEPAR				1000
 
 
+#define UNITA			_T("UNITA")
+#define UNITB			_T("UNITB")
+#define UNITC			_T("C")
+
+
 /* Context Ret code */
 #define CRC_ACK_REJECT							-3
 #define CRC_TIMEOUT								-2
@@ -87,3 +92,21 @@
 /* 按钮id */
 #define VIEW_TOOL_BTN_CLOSE				0x1016
 
+
+/* 单元数据 */
+typedef struct _UNITDATA1
+{
+	ULONG64 time;
+
+	/* 0:上腔体温度 */
+	/* 1:下腔体温度 */
+	/* 2~9:8个腔体监测温度 */
+	float temp[12];
+
+	/* 腔体真空 pa */
+	float vacuum;
+
+	/* 5个压力值 kg */
+	float pressure[5];
+} UNITDATA1;
+
diff --git a/SourceCode/Bond/BondEq/Component.cpp b/SourceCode/Bond/BondEq/Component.cpp
new file mode 100644
index 0000000..7456b65
--- /dev/null
+++ b/SourceCode/Bond/BondEq/Component.cpp
@@ -0,0 +1,126 @@
+#include "stdafx.h"
+#include "Common.h"
+#include "Component.h"
+#include "Log.h"
+#include "CBonder.h"
+
+CComponent::CComponent()
+{
+	m_pBonder = NULL;
+	m_pChannel1 = NULL;
+	m_nIndex = 0;
+	m_bRunning = FALSE;
+	InitializeCriticalSection(&m_criticalSection);
+}
+
+CComponent::~CComponent()
+{
+	DeleteCriticalSection(&m_criticalSection);
+}
+
+void CComponent::setBonder(CBonder* pBonder)
+{
+	m_pBonder = pBonder;
+}
+
+void CComponent::init()
+{
+	MCL_GetChannel(m_pChannel1, MC_CHANNEL1_NAME);
+}
+
+void CComponent::term()
+{
+
+}
+
+int CComponent::run()
+{
+	m_bRunning = TRUE;
+	return 0;
+}
+
+int CComponent::stop()
+{
+	m_bRunning = FALSE;
+	return 0;
+}
+
+void CComponent::setName(const char* pszName)
+{
+	m_strName = pszName;
+}
+
+std::string& CComponent::getName()
+{
+	return m_strName;
+}
+
+void CComponent::setDescription(const char* pszDescription)
+{
+	m_strDescription = pszDescription;
+}
+
+std::string& CComponent::getDescription()
+{
+	return m_strDescription;
+}
+
+void CComponent::setIndex(int index)
+{
+	m_nIndex = index;
+}
+
+int CComponent::getIndex()
+{
+	return m_nIndex;
+}
+
+void CComponent::onRecvBroadcast(void* pSender, CIntent* pIntent)
+{
+
+}
+
+void CComponent::onData(int id, const void* pData, int size)
+{
+
+}
+
+void CComponent::SendBroadcast(CIntent* pIntent)
+{
+	m_pBonder->sendBroadcast(this, pIntent);
+}
+
+int CComponent::WriteInt(int unitId, int addr, int value)
+{
+	return m_pBonder->writeInt(unitId, addr, value);
+}
+
+int CComponent::WriteData(MC::SOFT_COMPONENT softComponent, unsigned int addr,
+	const char* pszData, unsigned int length, ONWRITE funOnWrite)
+{
+	return m_pBonder->writeData(softComponent, addr, pszData, length, funOnWrite);
+}
+
+void CComponent::OnTimer(UINT nTimerid)
+{
+
+}
+
+void CComponent::Serialize(CArchive& ar)
+{
+
+}
+
+float CComponent::toFloat(const char* pszAddr)
+{
+	BYTE szBuffer[4];
+	szBuffer[0] = pszAddr[0];
+	szBuffer[1] = pszAddr[1];
+	szBuffer[2] = pszAddr[2];
+	szBuffer[3] = pszAddr[3];
+	float f = 0.0;
+	memcpy(&f, szBuffer, 4);
+
+	return f;
+}
+
diff --git a/SourceCode/Bond/BondEq/Component.h b/SourceCode/Bond/BondEq/Component.h
new file mode 100644
index 0000000..46e43c3
--- /dev/null
+++ b/SourceCode/Bond/BondEq/Component.h
@@ -0,0 +1,57 @@
+#pragma once
+#include <functional>
+#include <string>
+#include "Context.h"
+#include "Intent.h"
+#include "McBool.h"
+#include "McString.h"
+#include "McInt.h"
+
+
+class CBonder;
+class CComponent
+{
+public:
+	CComponent();
+	virtual ~CComponent();
+
+
+public:
+	virtual std::string& getClassName() = 0;
+	void setBonder(CBonder* pBonder);
+	void setName(const char* pszName);
+	std::string& getName();
+	void setDescription(const char* pszDescription);
+	std::string& getDescription();
+	void setIndex(int index);
+	int getIndex();
+	virtual void onRecvBroadcast(void* pSender, CIntent* pIntent);
+	virtual void onData(int id, const void* pData, int size);
+	virtual void init();
+	virtual void term();
+	virtual int run();
+	virtual int stop();
+	virtual void OnTimer(UINT nTimerid);
+	virtual void Serialize(CArchive& ar);
+	static float toFloat(const char* pszAddr);
+	int WriteInt(int unitId, int addr, int value);
+	int WriteData(MC::SOFT_COMPONENT softComponent, unsigned int addr,
+		const char* pszData, unsigned int length, ONWRITE funOnWrite);
+
+protected:
+	inline void Lock() { EnterCriticalSection(&m_criticalSection); }
+	inline void Unlock() { LeaveCriticalSection(&m_criticalSection); }
+	void SendBroadcast(CIntent* pIntent);
+
+protected:
+	CBonder* m_pBonder;
+	IMcChannel* m_pChannel1;
+	int m_nIndex;
+	std::string m_strName;
+	std::string m_strDescription;
+	CRITICAL_SECTION m_criticalSection;
+
+protected:
+	BOOL m_bRunning;
+};
+
diff --git a/SourceCode/Bond/BondEq/Context.cpp b/SourceCode/Bond/BondEq/Context.cpp
new file mode 100644
index 0000000..693da12
--- /dev/null
+++ b/SourceCode/Bond/BondEq/Context.cpp
@@ -0,0 +1,157 @@
+#include "stdafx.h"
+#include "Context.h"
+
+
+CContext::CContext()
+{
+	m_nRef = 0;
+	m_nRetCode = 0;
+	m_hEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
+	InitializeCriticalSection(&m_criticalSection);
+}
+
+
+CContext::~CContext()
+{
+	if (m_hEvent != NULL) {
+		CloseHandle(m_hEvent);
+		m_hEvent = NULL;
+	}
+	DeleteCriticalSection(&m_criticalSection);
+}
+
+int CContext::addRef()
+{
+	Lock();
+	m_nRef++;
+	Unlock();
+
+	return m_nRef;
+}
+
+int CContext::release()
+{
+	Lock();
+	m_nRef--;
+	BOOL bDelete = m_nRef == 0;
+	Unlock();
+
+	int nRef = m_nRef;;
+	if (bDelete) delete this;
+	return nRef;
+}
+
+void CContext::setRetCode(int code)
+{
+	m_nRetCode = code;
+}
+
+int CContext::getRetCode()
+{
+	return m_nRetCode;
+}
+
+void CContext::setRetMsg(const char* pszMsg)
+{
+	m_strRetMsg = pszMsg;
+}
+
+std::string& CContext::getRetMsg()
+{
+	return m_strRetMsg;
+}
+
+HANDLE CContext::getEventHandle()
+{
+	return m_hEvent;
+}
+
+void CContext::setEvent()
+{
+	if (m_hEvent != NULL) {
+		SetEvent(m_hEvent);
+	}
+}
+
+void CContext::resetEvent()
+{
+	if (m_hEvent != NULL) {
+		ResetEvent(m_hEvent);
+	}
+}
+
+void CContext::ReadString(CArchive& ar, std::string& string)
+{
+	CString strTemp;
+	ar >> strTemp;
+	string = (LPTSTR)(LPCTSTR)strTemp;
+}
+
+void CContext::WriteString(CArchive& ar, std::string& string)
+{
+	CString strTemp = string.c_str();
+	ar << strTemp;
+}
+
+void CContext::createDir(CString strDir)
+{
+	int lastIndex = 0;
+	int index = strDir.Find(_T("\\"), lastIndex);
+	while (index > 0) {
+		CString strTempDir = strDir.Left(index);
+		CreateDirectory(strTempDir, NULL);
+
+		lastIndex = index + 1;
+		index = strDir.Find(_T("\\"), lastIndex);
+	}
+	CreateDirectory(strDir, NULL);
+}
+
+BOOL CContext::IsBoxId(CString& strId)
+{
+	//'W20'开头,倒数第五位为'Z'的字符串
+	if (strId.GetLength() < 8) {
+		return FALSE;
+	}
+
+	if (strId.Left(3).Compare(_T("W20")) != 0) {
+		return FALSE;
+	}
+
+	if (strId.Right(5).GetAt(0) != (char)'Z') {
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+BOOL CContext::IsLotId(CString& strId)
+{
+	//'N20'开头,倒数第五位为'Z'的字符串
+	if (strId.GetLength() < 8) {
+		return FALSE;
+	}
+
+	if (strId.Left(3).Compare(_T("N20")) != 0) {
+		return FALSE;
+	}
+
+	if (strId.Right(5).GetAt(0) != (char)'Z') {
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+float CContext::toFloat(const char* pszAddr)
+{
+	BYTE szBuffer[4];
+	szBuffer[0] = pszAddr[0];
+	szBuffer[1] = pszAddr[1];
+	szBuffer[2] = pszAddr[2];
+	szBuffer[3] = pszAddr[3];
+	float f = 0.0;
+	memcpy(&f, szBuffer, 4);
+
+	return f;
+}
\ No newline at end of file
diff --git a/SourceCode/Bond/BondEq/Context.h b/SourceCode/Bond/BondEq/Context.h
new file mode 100644
index 0000000..cfad188
--- /dev/null
+++ b/SourceCode/Bond/BondEq/Context.h
@@ -0,0 +1,44 @@
+#pragma once
+#include "Common.h"
+
+class CContext : public IRxObject
+{
+public:
+	CContext();
+	virtual ~CContext();
+
+public:
+	int addRef();
+	int release();
+
+public:
+	virtual std::string& getClassName() = 0;
+	virtual std::string toString() = 0;
+	void setRetCode(int code);
+	int getRetCode();
+	void setRetMsg(const char* pszMsg);
+	std::string& getRetMsg();
+	HANDLE getEventHandle();
+	void setEvent();
+	void resetEvent();
+	static void createDir(CString strDir);
+	float toFloat(const char* pszAddr);
+
+protected:
+	inline void Lock() { EnterCriticalSection(&m_criticalSection); }
+	inline void Unlock() { LeaveCriticalSection(&m_criticalSection); }
+	void ReadString(CArchive& ar, std::string& string);
+	void WriteString(CArchive& ar, std::string& string);
+	static BOOL IsBoxId(CString& strId);
+	static BOOL IsLotId(CString& strId);
+
+private:
+	int m_nRef;
+	CRITICAL_SECTION m_criticalSection;
+
+protected:
+	int m_nRetCode;
+	std::string m_strRetMsg;
+	HANDLE m_hEvent;
+};
+
diff --git a/SourceCode/Bond/BondEq/EQState.cpp b/SourceCode/Bond/BondEq/EQState.cpp
new file mode 100644
index 0000000..eb12dcf
--- /dev/null
+++ b/SourceCode/Bond/BondEq/EQState.cpp
@@ -0,0 +1,109 @@
+#include "stdafx.h"
+#include "EQState.h"
+#include "ToolUnits.h"
+
+
+CEQState::CEQState()
+{
+	m_nUnitId = 0;
+	m_state = EQSTATE::Idle;
+	m_nDoorState = -1;
+	m_time = CToolUnits::getTimestamp();
+}
+
+CEQState::CEQState(int unitId, EQSTATE state)
+{
+	m_nUnitId = unitId;
+	m_state = state;
+	m_nDoorState = -1;
+	m_time = CToolUnits::getTimestamp();
+}
+
+CEQState::~CEQState()
+{
+}
+
+std::string& CEQState::getClassName()
+{
+	static std::string strName = "CAlarm";
+	return strName;
+}
+
+std::string CEQState::toString()
+{
+	CString strTemp;
+	std::string strText;
+	strText += "CAlarm[";
+	strText += ("time:" + CToolUnits::timeToString2(m_time) + ";");
+	strText += ("State:" + std::string((LPTSTR)(LPCTSTR)getText(strTemp)) + ";");
+	strText += "]";
+
+	return strText;
+}
+
+void CEQState::setDoorState(int doorst)
+{
+	m_nDoorState = doorst;
+}
+
+int CEQState::getUnitId()
+{
+	return m_nUnitId;
+}
+
+ULONGLONG CEQState::getTime()
+{
+	return m_time;
+}
+
+EQSTATE CEQState::getState()
+{
+	return m_state;
+}
+
+CString& CEQState::getText(CString& strOut)
+{
+	static char* pszState[] = {"Idle", "Run", "Down", "Maintenance", "MCHG", "E_TIME"};
+	if (m_nDoorState != -1) {
+		strOut.Empty();
+		if (m_nDoorState & 0x01) strOut.Append("Door State<Open,");
+		else strOut.Append("Door State<Close,");
+		if (m_nDoorState & 0x02) strOut.Append("Open,");
+		else strOut.Append("Close,");
+		if (m_nDoorState & 0x04) strOut.Append("Open,");
+		else strOut.Append("Close,");
+		if (m_nDoorState & 0x08) strOut.Append("Open,");
+		else strOut.Append("Close,");
+		if (m_nDoorState & 0x10) strOut.Append("Open>");
+		else strOut.Append("Close>");
+	}
+	else {
+		strOut = CString(pszState[(int)m_state - 1]);
+	}
+
+	return strOut;
+}
+
+void CEQState::Serialize(CArchive& ar)
+{
+	if (ar.IsStoring())
+	{
+		Lock();
+		ar << m_nUnitId;
+		ar << m_time;
+		ar << (int)m_state;
+		ar << m_nDoorState;
+		Unlock();
+	}
+	else
+	{
+		int temp;
+		Lock();
+		ar >> m_nUnitId;
+		ar >> m_time;
+		ar >> temp;
+		m_state = (EQSTATE)temp;
+		ar >> m_nDoorState;
+		Unlock();
+	}
+}
diff --git a/SourceCode/Bond/BondEq/EQState.h b/SourceCode/Bond/BondEq/EQState.h
new file mode 100644
index 0000000..a1d46c5
--- /dev/null
+++ b/SourceCode/Bond/BondEq/EQState.h
@@ -0,0 +1,39 @@
+#pragma once
+#include "Context.h"
+
+
+enum class EQSTATE
+{
+	Idle = 1,
+	Run,
+	Down,
+	Maintenance,
+	MCHG,
+	E_TIME
+};
+
+class CEQState :
+	public CContext
+{
+public:
+	CEQState();
+	CEQState(int unitId, EQSTATE state);
+	~CEQState();
+
+public:
+	virtual std::string& getClassName();
+	virtual std::string toString();
+	void setDoorState(int doorst);
+	int getUnitId();
+	ULONGLONG getTime();
+	EQSTATE getState();
+	CString& getText(CString& strOut);
+	void Serialize(CArchive& ar);
+
+private:
+	int m_nUnitId;
+	ULONG64 m_time;
+	EQSTATE m_state;
+	int m_nDoorState;
+};
+
diff --git a/SourceCode/Bond/BondEq/EQStateMonitor.cpp b/SourceCode/Bond/BondEq/EQStateMonitor.cpp
new file mode 100644
index 0000000..80ce467
--- /dev/null
+++ b/SourceCode/Bond/BondEq/EQStateMonitor.cpp
@@ -0,0 +1,155 @@
+#include "stdafx.h"
+#include "EQStateMonitor.h"
+#include "Common.h"
+#include "CBonder.h"
+#include "Log.h"
+
+#define EQSTATE_MAX		200
+
+CEQStateMonitor::CEQStateMonitor()
+{
+	m_nBeginAddr = 0;
+	m_bStatusReport = FALSE;
+	m_lastState = EQSTATE::Idle;
+	m_nLastDoorState = 0;
+}
+
+
+CEQStateMonitor::~CEQStateMonitor()
+{
+
+}
+
+std::string& CEQStateMonitor::getClassName()
+{
+	static std::string strClassName = "CEQStateMonitor";
+	return strClassName;
+}
+
+void CEQStateMonitor::onRecvBroadcast(void* pSender, CIntent* pIntent)
+{
+
+}
+
+void CEQStateMonitor::onData(int id, const void* pData, int size)
+{
+	const char* pszData = (const char*)pData;
+	if (m_nIndex + 1 == id) {
+		int addr = m_nBeginAddr * 2;
+		int state = (pszData[addr] & 0xff) | (pszData[addr + 1] & 0xff) << 8;
+		if ((int)m_lastState != state && (state >= 1 && state <= 6)) {
+			LOGI("<CEQStateMonitor-%d>state:%d", m_nIndex, state);
+			ReportStatus(state);
+		}
+
+		int doorState = (pszData[addr + 2] & 0xff) | (pszData[addr + 3] & 0xff) << 8;
+		if (m_nLastDoorState != doorState) {
+			LOGI("<CEQStateMonitor-%d>door state:%d", m_nIndex, doorState);
+			ReportDoorState((int)m_lastState, doorState);
+		}
+		
+	}
+}
+
+void CEQStateMonitor::enableStatusReport(BOOL bEnable)
+{
+	m_bStatusReport = bEnable;
+}
+
+void CEQStateMonitor::init()
+{
+	CComponent::init();
+}
+
+void CEQStateMonitor::term()
+{
+	for (auto item : m_eqStates) {
+		item->release();
+	}
+}
+
+void CEQStateMonitor::setBeginAddr(int nAddr)
+{
+	m_nBeginAddr = nAddr;
+}
+
+void CEQStateMonitor::OnTimer(UINT nTimerid)
+{
+
+}
+
+void CEQStateMonitor::ReportStatus(int eqst)
+{
+	BEQ::IUnit* pUnit = m_pBonder->getUnit(m_nIndex);
+	ASSERT(pUnit);
+	pUnit->setState((BEQ::EQ_STATE)(eqst-1));
+	LOGI("<CEQStateMonitor-%d> 更新设备状态(%d).", m_nIndex, eqst);
+
+	CEQState* pState = new CEQState(m_nIndex, (EQSTATE)eqst);
+	AddEQState(pState);
+	SendBroadcast(&CIntent(BC_CODE_EQSTATE_EVENT, "", pState));
+	m_lastState = (EQSTATE)eqst;
+}
+
+void CEQStateMonitor::ReportDoorState(int eqst, int doorst)
+{
+	BEQ::IUnit* pUnit = m_pBonder->getUnit(m_nIndex);
+	ASSERT(pUnit);
+	pUnit->setDoorState(doorst);
+	LOGI("<CEQStateMonitor-%d>更新安全门状态(%d).", m_nIndex, doorst);
+
+	CEQState* pState = new CEQState(m_nIndex, (EQSTATE)eqst);
+	pState->setDoorState(doorst);
+	AddEQState(pState);
+	SendBroadcast(&CIntent(BC_CODE_EQSTATE_EVENT, "", pState));
+	m_nLastDoorState = doorst;
+}
+
+void CEQStateMonitor::Serialize(CArchive& ar)
+{
+	if (ar.IsStoring())
+	{
+		Lock();
+		int count = (int)m_eqStates.size();
+		ar << count;
+		for (auto item : m_eqStates) {
+			item->Serialize(ar);
+		}
+		Unlock();
+	}
+	else
+	{
+		Lock();
+		int count;
+		ar >> count;
+		for (int i = 0; i < count; i++) {
+			CEQState* pState = new CEQState();
+			pState->addRef();
+			pState->Serialize(ar);
+			AddEQState(pState);
+			pState->release();
+
+		}
+		Unlock();
+	}
+}
+
+void CEQStateMonitor::AddEQState(CEQState* pEQState)
+{
+	Lock();
+	pEQState->addRef();
+	m_eqStates.push_back(pEQState);
+	if (m_eqStates.size() > EQSTATE_MAX) {
+		CEQState* pTemp = m_eqStates.front();
+		pTemp->release();
+		m_eqStates.pop_front();
+	}
+	Unlock();
+}
+
+void CEQStateMonitor::getEQStateList(std::list<CEQState*>& list)
+{
+	Lock();
+	list = m_eqStates;
+	Unlock();
+}
\ No newline at end of file
diff --git a/SourceCode/Bond/BondEq/EQStateMonitor.h b/SourceCode/Bond/BondEq/EQStateMonitor.h
new file mode 100644
index 0000000..b5cf8ef
--- /dev/null
+++ b/SourceCode/Bond/BondEq/EQStateMonitor.h
@@ -0,0 +1,40 @@
+#pragma once
+#include "Component.h"
+#include <map>
+#include <list>
+#include "EQState.h"
+
+class CEQStateMonitor :
+	public CComponent
+{
+public:
+	CEQStateMonitor();
+	~CEQStateMonitor();
+
+public:
+	virtual std::string& getClassName();
+	virtual void onData(int id, const void* pData, int size);
+	virtual void onRecvBroadcast(void* pSender, CIntent* pIntent);
+	virtual void init();
+	virtual void term();
+	void setBeginAddr(int nAddr);
+	void enableStatusReport(BOOL bEnable);
+	virtual void OnTimer(UINT nTimerid);
+	void ReportStatus(int eqst);
+	void ReportDoorState(int eqst, int doorst);
+	virtual void Serialize(CArchive& ar);
+	void getEQStateList(std::list<CEQState*>& list);
+
+private:
+	void AddEQState(CEQState* eqState);
+
+private:
+	int m_nBeginAddr;
+
+private:
+	BOOL m_bStatusReport;
+	EQSTATE m_lastState;
+	int m_nLastDoorState;
+	std::list<CEQState*> m_eqStates;
+};
+
diff --git a/SourceCode/Bond/BondEq/Intent.cpp b/SourceCode/Bond/BondEq/Intent.cpp
new file mode 100644
index 0000000..66603b6
--- /dev/null
+++ b/SourceCode/Bond/BondEq/Intent.cpp
@@ -0,0 +1,51 @@
+#include "stdafx.h"
+#include "Intent.h"
+
+
+CIntent::CIntent()
+{
+	m_nCode = 0;
+	m_pContext = nullptr;
+}
+
+CIntent::CIntent(int nCode, const char* pszMsg, CContext* pContext)
+{
+	m_nCode = nCode;
+	m_strMsg = pszMsg;
+	m_pContext = pContext;
+}
+
+CIntent::~CIntent()
+{
+}
+
+void CIntent::setCode(int nCode)
+{
+	m_nCode = nCode;
+}
+
+int CIntent::getCode()
+{
+	return m_nCode;
+}
+
+void CIntent::setMsg(const char* pszMsg)
+{
+	m_strMsg = pszMsg;
+}
+
+const char* CIntent::getMsg()
+{
+	return m_strMsg.c_str();
+}
+
+void CIntent::setContext(CContext* pContext)
+{
+	pContext->addRef();
+	m_pContext = pContext;
+}
+
+CContext* CIntent::getContext()
+{
+	return m_pContext;
+}
diff --git a/SourceCode/Bond/BondEq/Intent.h b/SourceCode/Bond/BondEq/Intent.h
new file mode 100644
index 0000000..081466f
--- /dev/null
+++ b/SourceCode/Bond/BondEq/Intent.h
@@ -0,0 +1,25 @@
+#pragma once
+#include <string>
+#include "Context.h"
+
+class CIntent
+{
+public:
+	CIntent();
+	CIntent(int nCode, const char* pszMsg, CContext* pContext);
+	~CIntent();
+
+public:
+	void setCode(int nCode);
+	int getCode();
+	void setMsg(const char* pszMsg);
+	const char* getMsg();
+	void setContext(CContext* pContext);
+	CContext* getContext();
+
+private:
+	int m_nCode;
+	std::string m_strMsg;
+	CContext* m_pContext;
+};
+
diff --git a/SourceCode/Bond/BondEq/LoadMonitor.cpp b/SourceCode/Bond/BondEq/LoadMonitor.cpp
new file mode 100644
index 0000000..5799d7b
--- /dev/null
+++ b/SourceCode/Bond/BondEq/LoadMonitor.cpp
@@ -0,0 +1,419 @@
+#include "stdafx.h"
+#include "LoadMonitor.h"
+#include "Common.h"
+#include "CBonder.h"
+#include "Log.h"
+
+#define ALARM_MAX		200
+
+unsigned __stdcall LoadMonitorRunRecipeThreadFunction(LPVOID lpParam)
+{
+	CLoadMonitor* p = (CLoadMonitor*)lpParam;
+	return p->RunRecipeThreadFunction();
+}
+
+CLoadMonitor::CLoadMonitor()
+{
+	m_nBeginAddr = 0;
+	m_nLastId = 0;
+	m_nLastLevel = 0;
+	m_hEventRunRecipeResult = ::CreateEvent(NULL, TRUE, FALSE, NULL);
+	m_nRunRecipeResult = 0;
+	m_hRunRecipeWorkThreadHandle = NULL;
+	m_nRunRecipeWorkThrdaddr = 0;
+	m_bRunRecipeWorking = FALSE;
+	m_hRunRecipeWorkEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
+	m_bWaitingRecipeResult = FALSE;
+}
+
+
+CLoadMonitor::~CLoadMonitor()
+{
+	if (m_hEventRunRecipeResult != nullptr) {
+		CloseHandle(m_hEventRunRecipeResult);
+		m_hEventRunRecipeResult = nullptr;
+	}
+}
+
+std::string& CLoadMonitor::getClassName()
+{
+	static std::string strClassName = "CLoadMonitor";
+	return strClassName;
+}
+
+void CLoadMonitor::onRecvBroadcast(void* pSender, CIntent* pIntent)
+{
+
+}
+
+void CLoadMonitor::onData(int id, const void* pData, int size)
+{
+	const char* pszData = (const char*)pData;
+	if (3 != id) return;
+
+
+	BOOL bPause, bReqLoad, bReqUnload;
+	if (m_nIndex == 0 || m_nIndex == 1) {
+		// 入料请求
+		bPause = pszData[m_nIndex * 2] & 0x04;
+		if (bPause) {
+			ReqNotReady(1);
+		}
+		else {
+			bReqLoad = pszData[m_nIndex * 2] & 0x01;
+			if (bReqLoad) {
+				ReqLoad(1);
+			}
+			else {
+				// 出料请求
+				bReqUnload = pszData[m_nIndex * 2 + 1] & 0x01;
+				if (bReqUnload) {
+					ReqUnload(1);
+				}
+			}
+		}
+	}
+	else if (m_nIndex == 2) {
+		// Layer1 入料请求
+		bReqLoad = pszData[m_nIndex * 2] & 0x01;
+		if (bReqLoad) {
+			ReqLoad(1);
+		}
+		else {
+			// 出料请求
+			bReqUnload = pszData[m_nIndex * 2] & 0x20;
+			if (bReqUnload) {
+				ReqUnload(1);
+			}
+		}
+
+		// Layer2
+		bReqLoad = pszData[m_nIndex * 2] & 0x02;
+		if (bReqLoad) {
+			ReqLoad(2);
+		}
+		else {
+			bReqUnload = pszData[m_nIndex * 2] & 0x40;
+			if (bReqUnload) {
+				ReqUnload(2);
+			}
+		}
+
+		// Layer3
+		bReqLoad = pszData[m_nIndex * 2] & 0x04;
+		if (bReqLoad) {
+			ReqLoad(3);
+		}
+		else {
+			bReqUnload = pszData[m_nIndex * 2] & 0x80;
+			if (bReqUnload) {
+				ReqUnload(3);
+			}
+		}
+
+		// Layer4
+		bReqLoad = pszData[m_nIndex * 2] & 0x08;
+		if (bReqLoad) {
+			ReqLoad(4);
+		}
+		else {
+			bReqUnload = pszData[m_nIndex * 2 + 1] & 0x01;
+			if (bReqUnload) {
+				ReqUnload(4);
+			}
+		}
+	}
+
+
+	// 切换配方结果
+	if (m_nIndex == 0 || m_nIndex == 1) {
+		int nAddr = (90 + m_nIndex) * 2;
+		m_nRunRecipeResult = (pszData[nAddr] & 0xff) | (pszData[nAddr + 1]) << 8;
+		if (m_bWaitingRecipeResult) {
+			LOGI("<CLoadMonitor>正在读取PLC切换配方的结果(RunRecipeResult:%d).", m_nRunRecipeResult);
+		}
+		if (m_nRunRecipeResult != 0) {
+			SetEvent(m_hEventRunRecipeResult);
+		}
+	}
+}
+
+void CLoadMonitor::init()
+{
+	m_bRunRecipeWorking = TRUE;
+	m_hRunRecipeWorkThreadHandle = (HANDLE)_beginthreadex(NULL, 0, ::LoadMonitorRunRecipeThreadFunction, this,
+		0, &m_nRunRecipeWorkThrdaddr);
+
+	CComponent::init();
+}
+
+void CLoadMonitor::term()
+{
+	// 结束线程
+	m_bRunRecipeWorking = FALSE;
+	SetEvent(m_hRunRecipeWorkEvent);
+	if (m_hRunRecipeWorkThreadHandle != NULL) {
+		WaitForSingleObject(m_hRunRecipeWorkThreadHandle, INFINITE);
+		CloseHandle(m_hRunRecipeWorkThreadHandle);
+		m_hRunRecipeWorkThreadHandle = NULL;
+	}
+
+	for (auto item : m_alarms) {
+		item->release();
+	}
+}
+
+void CLoadMonitor::setBeginAddr(int nAddr)
+{
+	m_nBeginAddr = nAddr;
+}
+
+void CLoadMonitor::OnTimer(UINT nTimerid)
+{
+	/*
+	char szBuffer[184];
+	memset(szBuffer, 0, 184);
+
+	if (m_nIndex == 0) {
+		static int iii = 0;
+		iii++;
+		if (iii > 30 && iii < 35) {
+			szBuffer[0] = 0x01;
+			onData(3, &szBuffer[0], 184);
+		}
+		else if (iii > 35 && iii < 52) {
+			szBuffer[90 * 2] = 0x08;
+			onData(3, &szBuffer[0], 184);
+		}
+		else if (iii > 60 && iii < 90) {
+			szBuffer[1] = 0x01;
+			onData(3, &szBuffer[0], 184);
+		}
+	}
+	if (m_nIndex == 1) {
+		static int iii = 0;
+		iii++;
+		if (iii > 130 && iii < 160) {
+			szBuffer[2] = 0x01;
+			onData(3, &szBuffer[0], 184);
+		}
+		else if (iii > 160 && iii < 190) {
+			szBuffer[3] = 0x01;
+			onData(3, &szBuffer[0], 184);
+		}
+	}
+	if (m_nIndex == 2) {
+		static int iii = 0;
+		iii++;
+		if (iii > 30 && iii < 60) {
+			szBuffer[4] = 0x20;
+			onData(3, &szBuffer[0], 184);
+		}
+		else if (iii > 60 && iii < 90) {
+			szBuffer[4] = 0x40;
+			onData(3, &szBuffer[0], 184);
+		}
+		else if (iii > 90 && iii < 120) {
+			szBuffer[4] = 0x80;
+			szBuffer[5] = 0x1;
+			onData(3, &szBuffer[0], 184);
+		}
+	}
+	*/
+}
+
+void CLoadMonitor::ReqNotReady(int layer)
+{
+	BEQ::IUnit* pUnit = m_pBonder->getUnit(m_nIndex);
+	ASSERT(pUnit);
+
+	// 请求上料
+	if (0 == pUnit->reqNotReady(layer))
+		LOGI("<CLoadMonitor-%d>Layer%d暂停上下料.", m_nIndex, layer);
+}
+
+void CLoadMonitor::ReqLoad(int layer)
+{
+	BEQ::IUnit* pUnit = m_pBonder->getUnit(m_nIndex);
+	ASSERT(pUnit);
+
+	// 请求上料
+	if(0 == pUnit->reqLoad(layer))
+		LOGI("<CLoadMonitor-%d>Layer%d请求上料.", m_nIndex, layer);
+}
+
+void CLoadMonitor::ReqUnload(int layer)
+{
+	BEQ::IUnit* pUnit = m_pBonder->getUnit(m_nIndex);
+	ASSERT(pUnit);
+
+	// 请求上料
+	if(0 == pUnit->reqUnload(layer))
+		LOGI("<CLoadMonitor-%d>Layer%d请求下料.", m_nIndex, layer);
+}
+
+int CLoadMonitor::loadReady(const char* pszMaterielId, const char* pszRecipeId)
+{
+	// 根据单元号取得PLC地址
+	int nMaterielIdAddr, nRecipeIdAddr;
+	if (m_nIndex == 0) {
+		nMaterielIdAddr = 4720;
+		nRecipeIdAddr = 4780;
+	}
+	else if (m_nIndex == 1) {
+		nMaterielIdAddr = 4750;
+		nRecipeIdAddr = 4781;
+	}
+	else {
+		return 0;
+	}
+
+
+	// 写入物料ID
+	HANDLE hEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
+	BOOL bWriteOk = TRUE;
+	char szBuffer[40];
+	memset(szBuffer, 0, 40);
+	memcpy(szBuffer, pszMaterielId, min(40, strlen(pszMaterielId)));
+	WriteData(MC::SOFT_COMPONENT::D, nMaterielIdAddr, szBuffer, 40, [&](IMcChannel* pChannel, int addr, DWORD value, int flag) -> void {
+		if (flag != 0) {
+			LOGE("<CBonder::loadReady-%d>PLC1写数据超时.flag=%d", __LINE__, flag);
+			bWriteOk = FALSE;
+		}
+		SetEvent(hEvent);
+	});
+	WaitForSingleObject(hEvent, INFINITE);
+	ResetEvent(hEvent);
+	if (!bWriteOk) {
+		LOGE("<CBonder>%s上料准备就绪, PLC已写入物料id失败", m_strName.c_str());
+		CloseHandle(hEvent);
+		return -3;
+	}
+	LOGI("<CBonder>%s上料准备就绪,PLC已写入物料id", m_strName.c_str());
+
+	
+	// 写入配方ID
+	bWriteOk = TRUE;
+	int nRecipeId = atoi(pszRecipeId);
+	szBuffer[0] = (nRecipeId & 0xff);
+	szBuffer[1] = (nRecipeId & 0xff00) >> 8;
+	WriteData(MC::SOFT_COMPONENT::D, nRecipeIdAddr, szBuffer, 2, [&](IMcChannel* pChannel, int addr, DWORD value, int flag) -> void {
+		if (flag != 0) {
+			LOGE("<CBonder::loadReady-%d>PLC1写数据超时.flag=%d", __LINE__, flag);
+			bWriteOk = FALSE;
+		}
+		SetEvent(hEvent);
+	});
+	WaitForSingleObject(hEvent, INFINITE);
+	ResetEvent(hEvent);
+	CloseHandle(hEvent);
+	if (!bWriteOk) {
+		LOGE("<CBonder>%s上料准备就绪, PLC写配方ID无响应", m_strName.c_str());
+		return -4;
+	}
+	LOGI("<CBonder>%s上料准备就绪,PLC已写入配方id", m_strName.c_str());
+
+
+	// 等待PLC响应,PLC D4790(D4791)切换配方结果:1成功,2稍候重试,3报警.txt
+	// 这里要放到线程去执行了
+	SetEvent(m_hRunRecipeWorkEvent);
+	return 1;
+}
+
+void CLoadMonitor::Serialize(CArchive& ar)
+{
+	if (ar.IsStoring())
+	{
+		Lock();
+		int count = (int)m_alarms.size();
+		ar << count;
+		for (auto item : m_alarms) {
+			item->Serialize(ar);
+		}
+		Unlock();
+	}
+	else
+	{
+		Lock();
+		int count;
+		ar >> count;
+		for (int i = 0; i < count; i++) {
+			CAlarm* pAlarm = new CAlarm();
+			pAlarm->addRef();
+			pAlarm->Serialize(ar);
+			AddAlarm(pAlarm);
+			pAlarm->release();
+
+		}
+		Unlock();
+	}
+}
+
+void CLoadMonitor::AddAlarm(CAlarm* pAlarm)
+{
+	Lock();
+	pAlarm->addRef();
+	m_alarms.push_back(pAlarm);
+	if (m_alarms.size() > ALARM_MAX) {
+		CAlarm* pTemp = m_alarms.front();
+		pTemp->release();
+		m_alarms.pop_front();
+	}
+	Unlock();
+}
+
+DWORD CLoadMonitor::WaitForGetRunRecipeResult(int timeout, int& result)
+{
+	m_bWaitingRecipeResult = TRUE;
+	ResetEvent(m_hEventRunRecipeResult);
+	m_nRunRecipeResult = 0;
+	DWORD nRet = WaitForSingleObject(m_hEventRunRecipeResult, timeout);
+	result = m_nRunRecipeResult;
+	m_bWaitingRecipeResult = FALSE;
+
+	return nRet;
+}
+
+unsigned CLoadMonitor::RunRecipeThreadFunction()
+{
+	while (m_bRunRecipeWorking) {
+
+		// 待退出信号或时间到
+		int nRet = WaitForSingleObject(m_hRunRecipeWorkEvent, INFINITE);
+		ResetEvent(m_hRunRecipeWorkEvent);
+		if (!m_bRunRecipeWorking) break;
+
+
+		// 等待PLC切换配方结果
+		int nError = 0;
+		int nRunRecipeResult = 0;
+		nRet = WaitForGetRunRecipeResult(3000, nRunRecipeResult);
+		if (nRet != WAIT_OBJECT_0) {
+			LOGE("<CBonder>%s, 读取PLC切换配方结果超时", m_strName.c_str());
+			nError = -5;
+		}
+		else {
+			if (nRunRecipeResult == 1) {
+				LOGI("<CBonder>%s, PLC切换配方成功", m_strName.c_str());
+				nError = 0;
+			}
+			else if (nRunRecipeResult == 2) {
+				LOGE("<CBonder>%s, PLC忙碌,请稍候重试。", m_strName.c_str());
+				nError = -6;
+			}
+			else {
+				LOGE("<CBonder>%s, PLC切换配方失败", m_strName.c_str());
+				nError = -7;
+			}
+		}
+		SendBroadcast(&CIntent(BC_CODE_RUN_RECIPE_RESULT, "", (CContext*)(__int64)nError));
+
+		
+
+		TRACE("RunRecipeThreadFunction...... \n");
+	}
+
+	// _endthreadex(0);
+	TRACE("RunRecipeThreadFunction exit\n");
+	return 0;
+}
\ No newline at end of file
diff --git a/SourceCode/Bond/BondEq/LoadMonitor.h b/SourceCode/Bond/BondEq/LoadMonitor.h
new file mode 100644
index 0000000..55b1a68
--- /dev/null
+++ b/SourceCode/Bond/BondEq/LoadMonitor.h
@@ -0,0 +1,49 @@
+#pragma once
+#include "Component.h"
+#include <map>
+#include <list>
+#include "Alarm.h"
+
+class CLoadMonitor :
+	public CComponent
+{
+public:
+	CLoadMonitor();
+	~CLoadMonitor();
+
+public:
+	virtual std::string& getClassName();
+	virtual void onData(int id, const void* pData, int size);
+	virtual void onRecvBroadcast(void* pSender, CIntent* pIntent);
+	virtual void init();
+	virtual void term();
+	void setBeginAddr(int nAddr);
+	virtual void OnTimer(UINT nTimerid);
+	void ReqNotReady(int layer);
+	void ReqLoad(int layer);
+	void ReqUnload(int layer);
+	int loadReady(const char* pszMaterielId, const char* pszRecipeId);
+	DWORD WaitForGetRunRecipeResult(int timeout, int& result);
+	unsigned RunRecipeThreadFunction();
+	virtual void Serialize(CArchive& ar);
+
+private:
+	void AddAlarm(CAlarm* pAlarm);
+
+private:
+	int m_nBeginAddr;
+
+private:
+	std::map<int, std::string> m_mapAlarmText;
+	int m_nLastId;
+	int m_nLastLevel;
+	std::list<CAlarm*> m_alarms;
+	HANDLE m_hEventRunRecipeResult;
+	BOOL m_bWaitingRecipeResult;
+	int m_nRunRecipeResult;
+	BOOL m_bRunRecipeWorking;
+	HANDLE m_hRunRecipeWorkEvent;
+	HANDLE m_hRunRecipeWorkThreadHandle;
+	unsigned m_nRunRecipeWorkThrdaddr;
+};
+
diff --git a/SourceCode/Bond/BondEq/McBool.cpp b/SourceCode/Bond/BondEq/McBool.cpp
new file mode 100644
index 0000000..fc4daca
--- /dev/null
+++ b/SourceCode/Bond/BondEq/McBool.cpp
@@ -0,0 +1,14 @@
+#include "stdafx.h"
+#include "McBool.h"
+
+
+CMcBool::CMcBool()
+{
+	m_nAddr = 0;
+	m_bValue = false;
+}
+
+
+CMcBool::~CMcBool()
+{
+}
diff --git a/SourceCode/Bond/BondEq/McBool.h b/SourceCode/Bond/BondEq/McBool.h
new file mode 100644
index 0000000..d5db692
--- /dev/null
+++ b/SourceCode/Bond/BondEq/McBool.h
@@ -0,0 +1,12 @@
+#pragma once
+class CMcBool
+{
+public:
+	CMcBool();
+	~CMcBool();
+
+public:
+	int m_nAddr;
+	bool m_bValue;
+};
+
diff --git a/SourceCode/Bond/BondEq/McInt.cpp b/SourceCode/Bond/BondEq/McInt.cpp
new file mode 100644
index 0000000..81cbbc4
--- /dev/null
+++ b/SourceCode/Bond/BondEq/McInt.cpp
@@ -0,0 +1,14 @@
+#include "stdafx.h"
+#include "McInt.h"
+
+
+CMcInt::CMcInt()
+{
+	m_nAddr = 0;
+	m_nValue = 0;
+}
+
+
+CMcInt::~CMcInt()
+{
+}
diff --git a/SourceCode/Bond/BondEq/McInt.h b/SourceCode/Bond/BondEq/McInt.h
new file mode 100644
index 0000000..f3ec9e4
--- /dev/null
+++ b/SourceCode/Bond/BondEq/McInt.h
@@ -0,0 +1,12 @@
+#pragma once
+class CMcInt
+{
+public:
+	CMcInt();
+	~CMcInt();
+
+public:
+	int m_nAddr;
+	int m_nValue;
+};
+
diff --git a/SourceCode/Bond/BondEq/McItem.cpp b/SourceCode/Bond/BondEq/McItem.cpp
new file mode 100644
index 0000000..3841a87
--- /dev/null
+++ b/SourceCode/Bond/BondEq/McItem.cpp
@@ -0,0 +1,12 @@
+#include "stdafx.h"
+#include "McItem.h"
+
+
+CMcItem::CMcItem()
+{
+}
+
+
+CMcItem::~CMcItem()
+{
+}
diff --git a/SourceCode/Bond/BondEq/McItem.h b/SourceCode/Bond/BondEq/McItem.h
new file mode 100644
index 0000000..290d1d3
--- /dev/null
+++ b/SourceCode/Bond/BondEq/McItem.h
@@ -0,0 +1,8 @@
+#pragma once
+class CMcItem
+{
+public:
+	CMcItem();
+	~CMcItem();
+};
+
diff --git a/SourceCode/Bond/BondEq/McString.cpp b/SourceCode/Bond/BondEq/McString.cpp
new file mode 100644
index 0000000..9108ba9
--- /dev/null
+++ b/SourceCode/Bond/BondEq/McString.cpp
@@ -0,0 +1,14 @@
+#include "stdafx.h"
+#include "McString.h"
+
+
+CMcString::CMcString()
+{
+	m_nAddrStart = 0;
+	m_nAddrEnd = 0;
+}
+
+
+CMcString::~CMcString()
+{
+}
diff --git a/SourceCode/Bond/BondEq/McString.h b/SourceCode/Bond/BondEq/McString.h
new file mode 100644
index 0000000..bb44e80
--- /dev/null
+++ b/SourceCode/Bond/BondEq/McString.h
@@ -0,0 +1,15 @@
+#pragma once
+#include <string>
+
+class CMcString
+{
+public:
+	CMcString();
+	~CMcString();
+
+public:
+	int m_nAddrStart;
+	int m_nAddrEnd;
+	std::string m_strValue;
+};
+
diff --git a/SourceCode/Bond/BondEq/Model.h b/SourceCode/Bond/BondEq/Model.h
index f9136b8..0feb0c9 100644
--- a/SourceCode/Bond/BondEq/Model.h
+++ b/SourceCode/Bond/BondEq/Model.h
@@ -1,5 +1,5 @@
 #pragma once
-#include "Bonder.h"
+#include "CBonder.h"
 #include "Configuration.h"
 
 
diff --git a/SourceCode/Bond/BondEq/Recipe.cpp b/SourceCode/Bond/BondEq/Recipe.cpp
new file mode 100644
index 0000000..fdc3e85
--- /dev/null
+++ b/SourceCode/Bond/BondEq/Recipe.cpp
@@ -0,0 +1,28 @@
+#include "stdafx.h"
+#include "Recipe.h"
+
+
+CRecipe::CRecipe()
+{
+}
+
+CRecipe::CRecipe(int id, const char* pszName)
+{
+	m_nId = id;
+	m_strName = pszName;
+}
+
+CRecipe::~CRecipe()
+{
+}
+
+int CRecipe::getId()
+{
+	return m_nId;
+}
+
+std::string& CRecipe::getName()
+{
+	return m_strName;
+}
+
diff --git a/SourceCode/Bond/BondEq/Recipe.h b/SourceCode/Bond/BondEq/Recipe.h
new file mode 100644
index 0000000..8ed7c36
--- /dev/null
+++ b/SourceCode/Bond/BondEq/Recipe.h
@@ -0,0 +1,17 @@
+#pragma once
+class CRecipe
+{
+public:
+	CRecipe();
+	CRecipe(int id, const char* pszName);
+	~CRecipe();
+
+public:
+	int getId();
+	std::string& getName();
+
+private:
+	int m_nId;
+	std::string m_strName;
+};
+
diff --git a/SourceCode/Bond/BondEq/TopToolbar.cpp b/SourceCode/Bond/BondEq/TopToolbar.cpp
index bda0e52..f0cdca2 100644
--- a/SourceCode/Bond/BondEq/TopToolbar.cpp
+++ b/SourceCode/Bond/BondEq/TopToolbar.cpp
@@ -187,3 +187,8 @@
 	*pResult = 0;
 }
 
+HMENU CTopToolbar::GetOperatorMenu()
+{
+	return m_btnOperator.GetMenu();
+}
+
diff --git a/SourceCode/Bond/BondEq/TopToolbar.h b/SourceCode/Bond/BondEq/TopToolbar.h
index 8b33d3e..1261d35 100644
--- a/SourceCode/Bond/BondEq/TopToolbar.h
+++ b/SourceCode/Bond/BondEq/TopToolbar.h
@@ -18,6 +18,7 @@
 public:
 	CWnd* GetBtn(UINT nId);
 	void SetOperatorBtnText(const char* pszText);
+	HMENU GetOperatorMenu();
 
 private:
 	void Resize();
diff --git a/SourceCode/Bond/BondEq/stdafx.h b/SourceCode/Bond/BondEq/stdafx.h
index 9226195..741d4c7 100644
--- a/SourceCode/Bond/BondEq/stdafx.h
+++ b/SourceCode/Bond/BondEq/stdafx.h
@@ -40,6 +40,7 @@
 
 #include "..\RxWindows1.0\include\RxWindowsLib.h"
 #include "..\BEQLibrarySDK\include\BEQLib.h"
+#include "..\McLibrarySDK\include\McLib.h"
 
 // 数据库模块
 #include "..\DatabaseSDK\include\Database.h"
diff --git a/SourceCode/Bond/McLibrarySDK/McDemo/McDemo.h b/SourceCode/Bond/McLibrarySDK/McDemo/McDemo.h
new file mode 100644
index 0000000..4581ca2
--- /dev/null
+++ b/SourceCode/Bond/McLibrarySDK/McDemo/McDemo.h
@@ -0,0 +1,34 @@
+
+// McDemo.h : PROJECT_NAME 应用程序的主头文件
+//
+
+#pragma once
+
+#ifndef __AFXWIN_H__
+	#error "在包含此文件之前包含“stdafx.h”以生成 PCH 文件"
+#endif
+
+#include "resource.h"		// 主符号
+#include "..\McLibrarySDK\include\McLib.h"
+
+
+// CMcDemoApp: 
+// 有关此类的实现,请参阅 McDemo.cpp
+//
+
+class CMcDemoApp : public CWinApp
+{
+public:
+	CMcDemoApp();
+
+// 重写
+public:
+	virtual BOOL InitInstance();
+
+// 实现
+
+	DECLARE_MESSAGE_MAP()
+	virtual int ExitInstance();
+};
+
+extern CMcDemoApp theApp;
\ No newline at end of file
diff --git a/SourceCode/Bond/McLibrarySDK/McDemo/McDemo.rc b/SourceCode/Bond/McLibrarySDK/McDemo/McDemo.rc
new file mode 100644
index 0000000..9547e4e
--- /dev/null
+++ b/SourceCode/Bond/McLibrarySDK/McDemo/McDemo.rc
Binary files differ
diff --git a/SourceCode/Bond/McLibrarySDK/McDemo/McDemo.vcxproj.filters b/SourceCode/Bond/McLibrarySDK/McDemo/McDemo.vcxproj.filters
new file mode 100644
index 0000000..94bb1ca
--- /dev/null
+++ b/SourceCode/Bond/McLibrarySDK/McDemo/McDemo.vcxproj.filters
@@ -0,0 +1,75 @@
+锘�<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <Filter Include="婧愭枃浠�">
+      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+    </Filter>
+    <Filter Include="澶存枃浠�">
+      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+      <Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
+    </Filter>
+    <Filter Include="璧勬簮鏂囦欢">
+      <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+      <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+    </Filter>
+    <Filter Include="McLIbrarySDK">
+      <UniqueIdentifier>{63fc133b-6db0-45cc-8346-1fd184790be0}</UniqueIdentifier>
+    </Filter>
+  </ItemGroup>
+  <ItemGroup>
+    <Text Include="ReadMe.txt" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="McDemo.h">
+      <Filter>澶存枃浠�</Filter>
+    </ClInclude>
+    <ClInclude Include="McDemoDlg.h">
+      <Filter>澶存枃浠�</Filter>
+    </ClInclude>
+    <ClInclude Include="stdafx.h">
+      <Filter>澶存枃浠�</Filter>
+    </ClInclude>
+    <ClInclude Include="targetver.h">
+      <Filter>澶存枃浠�</Filter>
+    </ClInclude>
+    <ClInclude Include="Resource.h">
+      <Filter>澶存枃浠�</Filter>
+    </ClInclude>
+    <ClInclude Include="..\McLibrarySDK\include\IMcChannel.h">
+      <Filter>McLIbrarySDK</Filter>
+    </ClInclude>
+    <ClInclude Include="..\McLibrarySDK\include\McLib.h">
+      <Filter>McLIbrarySDK</Filter>
+    </ClInclude>
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="McDemo.cpp">
+      <Filter>婧愭枃浠�</Filter>
+    </ClCompile>
+    <ClCompile Include="McDemoDlg.cpp">
+      <Filter>婧愭枃浠�</Filter>
+    </ClCompile>
+    <ClCompile Include="stdafx.cpp">
+      <Filter>婧愭枃浠�</Filter>
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ResourceCompile Include="McDemo.rc">
+      <Filter>璧勬簮鏂囦欢</Filter>
+    </ResourceCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="res\McDemo.rc2">
+      <Filter>璧勬簮鏂囦欢</Filter>
+    </None>
+  </ItemGroup>
+  <ItemGroup>
+    <Image Include="res\McDemo.ico">
+      <Filter>璧勬簮鏂囦欢</Filter>
+    </Image>
+  </ItemGroup>
+  <ItemGroup>
+    <Manifest Include="res\application.exe.manifest" />
+  </ItemGroup>
+</Project>
\ No newline at end of file
diff --git a/SourceCode/Bond/McLibrarySDK/McDemo/McDemo/McDemo.sln b/SourceCode/Bond/McLibrarySDK/McDemo/McDemo/McDemo.sln
new file mode 100644
index 0000000..eaf41cc
--- /dev/null
+++ b/SourceCode/Bond/McLibrarySDK/McDemo/McDemo/McDemo.sln
@@ -0,0 +1,31 @@
+锘�
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 14
+VisualStudioVersion = 14.0.23107.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "McDemo", "McDemo\McDemo.vcxproj", "{09A3010B-32B2-45EF-AAE1-4311997C99CD}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|x64 = Debug|x64
+		Debug|x86 = Debug|x86
+		Release|x64 = Release|x64
+		Release|x86 = Release|x86
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{09A3010B-32B2-45EF-AAE1-4311997C99CD}.Debug|x64.ActiveCfg = Debug|x64
+		{09A3010B-32B2-45EF-AAE1-4311997C99CD}.Debug|x64.Build.0 = Debug|x64
+		{09A3010B-32B2-45EF-AAE1-4311997C99CD}.Debug|x86.ActiveCfg = Debug|Win32
+		{09A3010B-32B2-45EF-AAE1-4311997C99CD}.Debug|x86.Build.0 = Debug|Win32
+		{09A3010B-32B2-45EF-AAE1-4311997C99CD}.Release|x64.ActiveCfg = Release|x64
+		{09A3010B-32B2-45EF-AAE1-4311997C99CD}.Release|x64.Build.0 = Release|x64
+		{09A3010B-32B2-45EF-AAE1-4311997C99CD}.Release|x86.ActiveCfg = Release|Win32
+		{09A3010B-32B2-45EF-AAE1-4311997C99CD}.Release|x86.Build.0 = Release|Win32
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+	GlobalSection(ExtensibilityGlobals) = postSolution
+		SolutionGuid = {7D650640-3FDB-411F-A158-FA36512DEC3B}
+	EndGlobalSection
+EndGlobal
diff --git a/SourceCode/Bond/McLibrarySDK/McDemo/McDemo/McDemo/McDemo.h b/SourceCode/Bond/McLibrarySDK/McDemo/McDemo/McDemo/McDemo.h
new file mode 100644
index 0000000..4581ca2
--- /dev/null
+++ b/SourceCode/Bond/McLibrarySDK/McDemo/McDemo/McDemo/McDemo.h
@@ -0,0 +1,34 @@
+
+// McDemo.h : PROJECT_NAME 应用程序的主头文件
+//
+
+#pragma once
+
+#ifndef __AFXWIN_H__
+	#error "在包含此文件之前包含“stdafx.h”以生成 PCH 文件"
+#endif
+
+#include "resource.h"		// 主符号
+#include "..\McLibrarySDK\include\McLib.h"
+
+
+// CMcDemoApp: 
+// 有关此类的实现,请参阅 McDemo.cpp
+//
+
+class CMcDemoApp : public CWinApp
+{
+public:
+	CMcDemoApp();
+
+// 重写
+public:
+	virtual BOOL InitInstance();
+
+// 实现
+
+	DECLARE_MESSAGE_MAP()
+	virtual int ExitInstance();
+};
+
+extern CMcDemoApp theApp;
\ No newline at end of file
diff --git a/SourceCode/Bond/McLibrarySDK/McDemo/McDemo/McDemo/McDemo.rc b/SourceCode/Bond/McLibrarySDK/McDemo/McDemo/McDemo/McDemo.rc
new file mode 100644
index 0000000..9547e4e
--- /dev/null
+++ b/SourceCode/Bond/McLibrarySDK/McDemo/McDemo/McDemo/McDemo.rc
Binary files differ
diff --git a/SourceCode/Bond/McLibrarySDK/McDemo/McDemo/McDemo/McDemo.vcxproj.filters b/SourceCode/Bond/McLibrarySDK/McDemo/McDemo/McDemo/McDemo.vcxproj.filters
new file mode 100644
index 0000000..94bb1ca
--- /dev/null
+++ b/SourceCode/Bond/McLibrarySDK/McDemo/McDemo/McDemo/McDemo.vcxproj.filters
@@ -0,0 +1,75 @@
+锘�<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <Filter Include="婧愭枃浠�">
+      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+    </Filter>
+    <Filter Include="澶存枃浠�">
+      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+      <Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
+    </Filter>
+    <Filter Include="璧勬簮鏂囦欢">
+      <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+      <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+    </Filter>
+    <Filter Include="McLIbrarySDK">
+      <UniqueIdentifier>{63fc133b-6db0-45cc-8346-1fd184790be0}</UniqueIdentifier>
+    </Filter>
+  </ItemGroup>
+  <ItemGroup>
+    <Text Include="ReadMe.txt" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="McDemo.h">
+      <Filter>澶存枃浠�</Filter>
+    </ClInclude>
+    <ClInclude Include="McDemoDlg.h">
+      <Filter>澶存枃浠�</Filter>
+    </ClInclude>
+    <ClInclude Include="stdafx.h">
+      <Filter>澶存枃浠�</Filter>
+    </ClInclude>
+    <ClInclude Include="targetver.h">
+      <Filter>澶存枃浠�</Filter>
+    </ClInclude>
+    <ClInclude Include="Resource.h">
+      <Filter>澶存枃浠�</Filter>
+    </ClInclude>
+    <ClInclude Include="..\McLibrarySDK\include\IMcChannel.h">
+      <Filter>McLIbrarySDK</Filter>
+    </ClInclude>
+    <ClInclude Include="..\McLibrarySDK\include\McLib.h">
+      <Filter>McLIbrarySDK</Filter>
+    </ClInclude>
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="McDemo.cpp">
+      <Filter>婧愭枃浠�</Filter>
+    </ClCompile>
+    <ClCompile Include="McDemoDlg.cpp">
+      <Filter>婧愭枃浠�</Filter>
+    </ClCompile>
+    <ClCompile Include="stdafx.cpp">
+      <Filter>婧愭枃浠�</Filter>
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ResourceCompile Include="McDemo.rc">
+      <Filter>璧勬簮鏂囦欢</Filter>
+    </ResourceCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="res\McDemo.rc2">
+      <Filter>璧勬簮鏂囦欢</Filter>
+    </None>
+  </ItemGroup>
+  <ItemGroup>
+    <Image Include="res\McDemo.ico">
+      <Filter>璧勬簮鏂囦欢</Filter>
+    </Image>
+  </ItemGroup>
+  <ItemGroup>
+    <Manifest Include="res\application.exe.manifest" />
+  </ItemGroup>
+</Project>
\ No newline at end of file
diff --git a/SourceCode/Bond/McLibrarySDK/McDemo/McDemo/McDemo/mcdemo.cpp b/SourceCode/Bond/McLibrarySDK/McDemo/McDemo/McDemo/mcdemo.cpp
new file mode 100644
index 0000000..6812cce
--- /dev/null
+++ b/SourceCode/Bond/McLibrarySDK/McDemo/McDemo/McDemo/mcdemo.cpp
@@ -0,0 +1,121 @@
+
+// McDemo.cpp : 定义应用程序的类行为。
+//
+
+#include "stdafx.h"
+#include "McDemo.h"
+#include "McDemoDlg.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#endif
+
+
+// CMcDemoApp
+
+BEGIN_MESSAGE_MAP(CMcDemoApp, CWinApp)
+	ON_COMMAND(ID_HELP, &CWinApp::OnHelp)
+END_MESSAGE_MAP()
+
+
+// CMcDemoApp 构造
+
+CMcDemoApp::CMcDemoApp()
+{
+	// 支持重新启动管理器
+	m_dwRestartManagerSupportFlags = AFX_RESTART_MANAGER_SUPPORT_RESTART;
+
+	// TODO: 在此处添加构造代码,
+	// 将所有重要的初始化放置在 InitInstance 中
+}
+
+
+// 唯一的一个 CMcDemoApp 对象
+
+CMcDemoApp theApp;
+
+
+// CMcDemoApp 初始化
+
+BOOL CMcDemoApp::InitInstance()
+{
+	// 如果一个运行在 Windows XP 上的应用程序清单指定要
+	// 使用 ComCtl32.dll 版本 6 或更高版本来启用可视化方式,
+	//则需要 InitCommonControlsEx()。  否则,将无法创建窗口。
+	INITCOMMONCONTROLSEX InitCtrls;
+	InitCtrls.dwSize = sizeof(InitCtrls);
+	// 将它设置为包括所有要在应用程序中使用的
+	// 公共控件类。
+	InitCtrls.dwICC = ICC_WIN95_CLASSES;
+	InitCommonControlsEx(&InitCtrls);
+
+	CWinApp::InitInstance();
+
+
+	AfxEnableControlContainer();
+
+	// 创建 shell 管理器,以防对话框包含
+	// 任何 shell 树视图控件或 shell 列表视图控件。
+	CShellManager *pShellManager = new CShellManager;
+
+	// 激活“Windows Native”视觉管理器,以便在 MFC 控件中启用主题
+	CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerWindows));
+
+	// 标准初始化
+	// 如果未使用这些功能并希望减小
+	// 最终可执行文件的大小,则应移除下列
+	// 不需要的特定初始化例程
+	// 更改用于存储设置的注册表项
+	// TODO: 应适当修改该字符串,
+	// 例如修改为公司或组织名
+	SetRegistryKey(_T("应用程序向导生成的本地应用程序"));
+
+
+	// 初始化
+	MCL_Initialize();
+
+
+	CMcDemoDlg dlg;
+	m_pMainWnd = &dlg;
+	INT_PTR nResponse = dlg.DoModal();
+	if (nResponse == IDOK)
+	{
+		// TODO: 在此放置处理何时用
+		//  “确定”来关闭对话框的代码
+	}
+	else if (nResponse == IDCANCEL)
+	{
+		// TODO: 在此放置处理何时用
+		//  “取消”来关闭对话框的代码
+	}
+	else if (nResponse == -1)
+	{
+		TRACE(traceAppMsg, 0, "警告: 对话框创建失败,应用程序将意外终止。\n");
+		TRACE(traceAppMsg, 0, "警告: 如果您在对话框上使用 MFC 控件,则无法 #define _AFX_NO_MFC_CONTROLS_IN_DIALOGS。\n");
+	}
+
+	// 删除上面创建的 shell 管理器。
+	if (pShellManager != NULL)
+	{
+		delete pShellManager;
+	}
+
+#ifndef _AFXDLL
+	ControlBarCleanUp();
+#endif
+
+	// 由于对话框已关闭,所以将返回 FALSE 以便退出应用程序,
+	//  而不是启动应用程序的消息泵。
+	return FALSE;
+}
+
+
+
+int CMcDemoApp::ExitInstance()
+{
+	// TODO: 在此添加专用代码和/或调用基类
+	MCL_Term();
+
+
+	return CWinApp::ExitInstance();
+}
diff --git a/SourceCode/Bond/McLibrarySDK/McDemo/McDemo/McDemo/mcdemo.vcxproj b/SourceCode/Bond/McLibrarySDK/McDemo/McDemo/McDemo/mcdemo.vcxproj
new file mode 100644
index 0000000..e7a2a7b
--- /dev/null
+++ b/SourceCode/Bond/McLibrarySDK/McDemo/McDemo/McDemo/mcdemo.vcxproj
@@ -0,0 +1,226 @@
+锘�<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{09A3010B-32B2-45EF-AAE1-4311997C99CD}</ProjectGuid>
+    <RootNamespace>McDemo</RootNamespace>
+    <WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
+    <Keyword>MFCProj</Keyword>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>v140</PlatformToolset>
+    <CharacterSet>Unicode</CharacterSet>
+    <UseOfMfc>Dynamic</UseOfMfc>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>v140</PlatformToolset>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+    <UseOfMfc>Dynamic</UseOfMfc>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>v140</PlatformToolset>
+    <CharacterSet>MultiByte</CharacterSet>
+    <UseOfMfc>Dynamic</UseOfMfc>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>v140</PlatformToolset>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>MultiByte</CharacterSet>
+    <UseOfMfc>Dynamic</UseOfMfc>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="Shared">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <LinkIncremental>true</LinkIncremental>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <LinkIncremental>true</LinkIncremental>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <LinkIncremental>false</LinkIncremental>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <LinkIncremental>false</LinkIncremental>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>Use</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_WINDOWS;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+    </Link>
+    <Midl>
+      <MkTypLibCompatible>false</MkTypLibCompatible>
+      <ValidateAllParameters>true</ValidateAllParameters>
+      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+    </Midl>
+    <ResourceCompile>
+      <Culture>0x0804</Culture>
+      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+    </ResourceCompile>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <ClCompile>
+      <PrecompiledHeader>Use</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>_WINDOWS;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+    </Link>
+    <Midl>
+      <MkTypLibCompatible>false</MkTypLibCompatible>
+      <ValidateAllParameters>true</ValidateAllParameters>
+      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+    </Midl>
+    <ResourceCompile>
+      <Culture>0x0804</Culture>
+      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+    </ResourceCompile>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <PrecompiledHeader>Use</PrecompiledHeader>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <PreprocessorDefinitions>WIN32;_WINDOWS;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+    <Midl>
+      <MkTypLibCompatible>false</MkTypLibCompatible>
+      <ValidateAllParameters>true</ValidateAllParameters>
+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+    </Midl>
+    <ResourceCompile>
+      <Culture>0x0804</Culture>
+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+    </ResourceCompile>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <PrecompiledHeader>Use</PrecompiledHeader>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <PreprocessorDefinitions>_WINDOWS;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+    <Midl>
+      <MkTypLibCompatible>false</MkTypLibCompatible>
+      <ValidateAllParameters>true</ValidateAllParameters>
+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+    </Midl>
+    <ResourceCompile>
+      <Culture>0x0804</Culture>
+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+    </ResourceCompile>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <Text Include="ReadMe.txt" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="..\McLibrarySDK\include\IMcChannel.h" />
+    <ClInclude Include="..\McLibrarySDK\include\McLib.h" />
+    <ClInclude Include="McDemo.h" />
+    <ClInclude Include="McDemoDlg.h" />
+    <ClInclude Include="Resource.h" />
+    <ClInclude Include="stdafx.h" />
+    <ClInclude Include="targetver.h" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="McDemo.cpp" />
+    <ClCompile Include="McDemoDlg.cpp" />
+    <ClCompile Include="stdafx.cpp">
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ResourceCompile Include="McDemo.rc" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="res\McDemo.rc2" />
+  </ItemGroup>
+  <ItemGroup>
+    <Image Include="res\McDemo.ico" />
+  </ItemGroup>
+  <ItemGroup>
+    <Manifest Include="res\application.exe.manifest" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+  <ProjectExtensions>
+    <VisualStudio>
+      <UserProperties RESOURCE_FILE="McDemo.rc" />
+    </VisualStudio>
+  </ProjectExtensions>
+</Project>
\ No newline at end of file
diff --git a/SourceCode/Bond/McLibrarySDK/McDemo/McDemo/McDemo/mcdemodlg.cpp b/SourceCode/Bond/McLibrarySDK/McDemo/McDemo/McDemo/mcdemodlg.cpp
new file mode 100644
index 0000000..abe306e
--- /dev/null
+++ b/SourceCode/Bond/McLibrarySDK/McDemo/McDemo/McDemo/mcdemodlg.cpp
@@ -0,0 +1,769 @@
+
+// McDemoDlg.cpp : 实现文件
+//
+
+#include "stdafx.h"
+#include "McDemo.h"
+#include "McDemoDlg.h"
+#include "afxdialogex.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#endif
+
+
+#define MAX_MESSAGE_LENGTH		1024
+#define CHANNEL_NAME			_T("Test1")
+
+// 用于应用程序“关于”菜单项的 CAboutDlg 对话框
+
+class CAboutDlg : public CDialogEx
+{
+public:
+	CAboutDlg();
+
+// 对话框数据
+#ifdef AFX_DESIGN_TIME
+	enum { IDD = IDD_ABOUTBOX };
+#endif
+
+	protected:
+	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持
+
+// 实现
+protected:
+	DECLARE_MESSAGE_MAP()
+};
+
+CAboutDlg::CAboutDlg() : CDialogEx(IDD_ABOUTBOX)
+{
+}
+
+void CAboutDlg::DoDataExchange(CDataExchange* pDX)
+{
+	CDialogEx::DoDataExchange(pDX);
+}
+
+BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
+END_MESSAGE_MAP()
+
+
+// CMcDemoDlg 对话框
+
+
+
+CMcDemoDlg::CMcDemoDlg(CWnd* pParent /*=NULL*/)
+	: CDialogEx(IDD_MCDEMO_DIALOG, pParent)
+{
+	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
+	m_pChannel = NULL;
+}
+
+void CMcDemoDlg::DoDataExchange(CDataExchange* pDX)
+{
+	CDialogEx::DoDataExchange(pDX);
+}
+
+BEGIN_MESSAGE_MAP(CMcDemoDlg, CDialogEx)
+	ON_WM_SYSCOMMAND()
+	ON_WM_PAINT()
+	ON_WM_QUERYDRAGICON()
+	ON_BN_CLICKED(IDC_BUTTON_CREATE, &CMcDemoDlg::OnBnClickedButtonCreate)
+	ON_BN_CLICKED(IDC_BUTTON_SEND, &CMcDemoDlg::OnBnClickedButtonSend)
+	ON_BN_CLICKED(IDC_BUTTON_CLOSE, &CMcDemoDlg::OnBnClickedButtonClose)
+	ON_BN_CLICKED(IDC_BUTTON_DESTROY, &CMcDemoDlg::OnBnClickedButtonDestroy)
+	ON_BN_CLICKED(IDC_BUTTON_READ, &CMcDemoDlg::OnBnClickedButtonRead)
+	ON_BN_CLICKED(IDC_BUTTON_RAWDATA, &CMcDemoDlg::OnBnClickedButtonRawdata)
+	ON_BN_CLICKED(IDC_BUTTON_WRITE, &CMcDemoDlg::OnBnClickedButtonWrite)
+	ON_BN_CLICKED(IDC_BUTTON_READ_BIT, &CMcDemoDlg::OnBnClickedButtonReadBit)
+	ON_BN_CLICKED(IDC_CHECK_WRITE_BIT_VALUE, &CMcDemoDlg::OnBnClickedCheckWriteBitValue)
+	ON_BN_CLICKED(IDC_BUTTON_WRITE_BIT, &CMcDemoDlg::OnBnClickedButtonWriteBit)
+	ON_BN_CLICKED(IDC_BUTTON_READ_DWORD, &CMcDemoDlg::OnBnClickedButtonReadDword)
+	ON_BN_CLICKED(IDC_BUTTON_WRITE_DWORD, &CMcDemoDlg::OnBnClickedButtonWriteDword)
+END_MESSAGE_MAP()
+
+
+// CMcDemoDlg 消息处理程序
+
+BOOL CMcDemoDlg::OnInitDialog()
+{
+	CDialogEx::OnInitDialog();
+
+	// 将“关于...”菜单项添加到系统菜单中。
+
+	// IDM_ABOUTBOX 必须在系统命令范围内。
+	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
+	ASSERT(IDM_ABOUTBOX < 0xF000);
+
+	CMenu* pSysMenu = GetSystemMenu(FALSE);
+	if (pSysMenu != NULL)
+	{
+		BOOL bNameValid;
+		CString strAboutMenu;
+		bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
+		ASSERT(bNameValid);
+		if (!strAboutMenu.IsEmpty())
+		{
+			pSysMenu->AppendMenu(MF_SEPARATOR);
+			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
+		}
+	}
+
+	// 设置此对话框的图标。  当应用程序主窗口不是对话框时,框架将自动
+	//  执行此操作
+	SetIcon(m_hIcon, TRUE);			// 设置大图标
+	SetIcon(m_hIcon, FALSE);		// 设置小图标
+
+	// TODO: 在此添加额外的初始化代码
+
+
+	CIPAddressCtrl* pIpAddressCtrl = (CIPAddressCtrl*)GetDlgItem(IDC_IPADDRESS_SERVER);
+	pIpAddressCtrl->SetAddress(192, 168, 3, 39);
+	// pIpAddressCtrl->SetAddress(127, 0, 0, 1);
+	SetDlgItemInt(IDC_EDIT_SERVER_PORT, 9300);
+
+	((CButton*)GetDlgItem(IDC_RADIO2))->SetCheck(1);
+	//CString strText = _T("50 00 00 FF FF 03 00 0C 00 10 00 01 04 00 00 64 00 00 A8 01 00");
+	//SetDlgItemText(IDC_EDIT_RAW, strText);
+
+
+	// 软元件
+	std::vector<std::string> softComponents;
+	int softComponentsSize = MCL_GetSoftComponents(softComponents);
+	CComboBox* pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_SOFTITEM);
+	CComboBox* pComboBox2 = (CComboBox*)GetDlgItem(IDC_COMBO_SOFTITEM2);
+	for (auto item : softComponents) {
+		pComboBox->InsertString(pComboBox->GetCount(), item.c_str());
+		pComboBox2->InsertString(pComboBox2->GetCount(), item.c_str());
+	}
+	if (softComponentsSize > 0) {
+		pComboBox->SetCurSel(0);
+		pComboBox2->SetCurSel(0);
+	}
+
+
+	// 命令
+	std::vector<std::string> cmds;
+	int cmdsSize = MCL_GetCmds(cmds);
+	pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_CMD);
+	for (auto item : cmds) {
+		pComboBox->InsertString(pComboBox->GetCount(), item.c_str());
+	}
+	if (cmdsSize > 0) {
+		pComboBox->SetCurSel(0);
+	}
+
+
+
+	// 子命令
+	std::vector<std::string> subCmds;
+	int subCmdsSize = MCL_GetSubCmds(subCmds);
+	pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_SUBCMD);
+	for (auto item : subCmds) {
+		pComboBox->InsertString(pComboBox->GetCount(), item.c_str());
+	}
+	if (cmdsSize > 0) {
+		pComboBox->SetCurSel(0);
+	}
+
+
+	SetDlgItemInt(IDC_EDIT_HEAD_ADDR, 100);
+	SetDlgItemInt(IDC_EDIT_READ_COUNT, 1);
+	UpdateUISecsion1();
+	UpdateUISecsion2();
+	UpdateUISecsion3();
+
+	return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
+}
+
+void CMcDemoDlg::OnSysCommand(UINT nID, LPARAM lParam)
+{
+	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
+	{
+		CAboutDlg dlgAbout;
+		dlgAbout.DoModal();
+	}
+	else
+	{
+		CDialogEx::OnSysCommand(nID, lParam);
+	}
+}
+
+// 如果向对话框添加最小化按钮,则需要下面的代码
+//  来绘制该图标。  对于使用文档/视图模型的 MFC 应用程序,
+//  这将由框架自动完成。
+
+void CMcDemoDlg::OnPaint()
+{
+	if (IsIconic())
+	{
+		CPaintDC dc(this); // 用于绘制的设备上下文
+
+		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
+
+		// 使图标在工作区矩形中居中
+		int cxIcon = GetSystemMetrics(SM_CXICON);
+		int cyIcon = GetSystemMetrics(SM_CYICON);
+		CRect rect;
+		GetClientRect(&rect);
+		int x = (rect.Width() - cxIcon + 1) / 2;
+		int y = (rect.Height() - cyIcon + 1) / 2;
+
+		// 绘制图标
+		dc.DrawIcon(x, y, m_hIcon);
+	}
+	else
+	{
+		CDialogEx::OnPaint();
+	}
+}
+
+//当用户拖动最小化窗口时系统调用此函数取得光标
+//显示。
+HCURSOR CMcDemoDlg::OnQueryDragIcon()
+{
+	return static_cast<HCURSOR>(m_hIcon);
+}
+
+
+
+void CMcDemoDlg::OnBnClickedButtonCreate()
+{
+	m_mcChannellistener.funOnConnected = [&](IMcChannel* pChannel, int nErrorCode) -> void {
+		CString strText;
+		strText.Format(_T(">> funOnConnected, %s连接结果<code =  %d>\r\n"), pChannel->getName().c_str(), nErrorCode);
+		AppendLog(strText);
+
+		UpdateUISecsion1();
+		UpdateUISecsion2();
+		UpdateUISecsion3();
+	};
+	m_mcChannellistener.funOnClose = [&](IMcChannel* pChannel) -> void {
+		AppendLog(">> funOnClose, %s已关闭\r\n", pChannel->getName().c_str());
+		UpdateUISecsion1();
+		UpdateUISecsion2();
+		UpdateUISecsion3();
+	};
+	m_mcChannellistener.funOnClosing = [&](IMcChannel* pChannel) -> void {
+		AppendLog(">> funOnClosing, 正在关闭 %s\r\n", pChannel->getName().c_str());
+		UpdateUISecsion1();
+		UpdateUISecsion2();
+		UpdateUISecsion3();
+	};
+	m_mcChannellistener.funOnRead = [&](IMcChannel* pChannel, char* pData, unsigned int nDataSize) -> void {
+		CString strText;
+		DataToHexString(pData, nDataSize, strText);
+		AppendLog(">> funOnRead:[%s]\r\n", strText);
+	};
+	m_mcChannellistener.funOnWrite = [&](IMcChannel* pChannel) -> void {
+		AppendLog(">> funOnWrite\r\n");
+	};
+
+
+	CIPAddressCtrl* pIpAddressCtrl = (CIPAddressCtrl*)GetDlgItem(IDC_IPADDRESS_SERVER);
+	BYTE b1, b2, b3, b4;
+	pIpAddressCtrl->GetAddress(b1, b2, b3, b4);
+	CString strIP;
+	strIP.Format("%d.%d.%d.%d", b1, b2, b3, b4);
+	UINT port = GetDlgItemInt(IDC_EDIT_SERVER_PORT);
+
+
+	m_pChannel = NULL;
+	if (0 == MCL_CreateChannel(m_pChannel, CHANNEL_NAME, (LPTSTR)(LPCTSTR)strIP, port, 0) && m_pChannel != NULL) {
+		m_pChannel->setChannelListener(&m_mcChannellistener);
+		CString strText;
+		strText.Format(_T(">> 创建通道(%s)成功\r\n"), m_pChannel->getName().c_str()),
+		AppendLog(strText);
+		//m_pChannel->connect();
+	}
+	else if(m_pChannel != NULL){
+		m_pChannel->setChannelListener(&m_mcChannellistener);
+		AppendLog(">> 找到现有通道(%s).\r\n", m_pChannel->getName().c_str());
+	}
+
+	UpdateUISecsion1();
+	UpdateUISecsion2();
+	UpdateUISecsion3();
+}
+
+void CMcDemoDlg::OnBnClickedButtonSend()
+{
+	
+	if (m_pChannel != NULL && m_pChannel->isConnected()) {
+		CString strText;
+		GetDlgItemText(IDC_EDIT_RAW, strText);
+		CButton* pButton = (CButton*)GetDlgItem(IDC_RADIO2);
+		if (pButton->GetCheck() == 1) {
+			char szBuffer[1024];
+			int nLen = HexStringToData(strText, szBuffer, 1024);
+			if (nLen > 0) {
+				m_pChannel->sendRawData(szBuffer, nLen);
+			}
+		}
+		else {
+			m_pChannel->sendRawData((LPTSTR)(LPCTSTR)strText, strText.GetLength());
+		}
+	}
+}
+
+void CMcDemoDlg::OnBnClickedButtonClose()
+{
+	if (m_pChannel != NULL) {
+		if (m_pChannel->isConnected()) {
+			m_pChannel->close();
+		}
+		else {
+			AppendLog(_T(">> 正在连接 %s, %s:%d\r\n"), m_pChannel->getName().c_str(), m_pChannel->getIp().c_str(), m_pChannel->getServerPort());
+			m_pChannel->connect();
+		}
+
+		UpdateUISecsion1();
+		UpdateUISecsion2();
+		UpdateUISecsion3();
+	}
+
+	/*
+	IMcChannel* pChannel = NULL;
+	if (0 == MCL_GetChannel(pChannel, CHANNEL_NAME) && pChannel != NULL) {
+		pChannel->close();
+	}*/
+}
+
+
+void CMcDemoDlg::OnBnClickedButtonDestroy()
+{
+	if (m_pChannel != NULL) {
+		MCL_DestroyChannel(m_pChannel->getName().c_str());
+		m_pChannel = NULL;
+		UpdateUISecsion1();
+		UpdateUISecsion2();
+		UpdateUISecsion3();
+	}
+}
+
+void CMcDemoDlg::AppendLog(CString strText)
+{
+	CEdit *pEdit = (CEdit *)GetDlgItem(IDC_EDIT_LOG);
+	if (pEdit == NULL) {
+		return;
+	}
+
+
+	// 超过指定行则删除最前面一行
+	int nLine = pEdit->GetLineCount();
+	if (nLine > 100) {
+		CString strOldText;
+		pEdit->GetWindowText(strOldText);
+
+		int nIndex = strOldText.Find(_T("\r\n"), 0);
+		for (int i = 0; i < 1111; i++) {
+			nIndex = strOldText.Find(_T("\r\n"), nIndex + 2);
+		}
+		pEdit->SetSel(0, nIndex);
+		pEdit->ReplaceSel(_T(""));
+	}
+
+
+	// 追加到最后
+	int length = pEdit->GetWindowTextLength();
+	pEdit->SetSel(length, length);
+	pEdit->ReplaceSel(strText);
+	pEdit->PostMessage(WM_VSCROLL, SB_BOTTOM, 0);
+}
+
+void CMcDemoDlg::AppendLog(char* szMessage, ...)
+{
+	if (!::IsWindow(GetSafeHwnd())) {
+		return;
+	}
+
+	CEdit *pEdit = (CEdit *)GetDlgItem(IDC_EDIT_LOG);
+	if (pEdit == NULL) {
+		return;
+	}
+
+	char szFormatMessage[MAX_MESSAGE_LENGTH];
+	va_list ap;
+	va_start(ap, szMessage);
+	_vsnprintf_s(szFormatMessage, MAX_MESSAGE_LENGTH, szMessage, ap);
+	va_end(ap);
+
+	// 超过指定行则删除最前面一行
+	int nLine = pEdit->GetLineCount();
+	if (nLine > 100) {
+		CString strOldText;
+		pEdit->GetWindowText(strOldText);
+
+		int nIndex = strOldText.Find(_T("\r\n"), 0);
+		for (int i = 0; i < 1111; i++) {
+			nIndex = strOldText.Find(_T("\r\n"), nIndex + 2);
+		}
+		pEdit->SetSel(0, nIndex);
+		pEdit->ReplaceSel(_T(""));
+	}
+
+
+	// 追加到最后
+	int length = pEdit->GetWindowTextLength();
+	pEdit->SetSel(length, length);
+	pEdit->ReplaceSel(szFormatMessage);
+	pEdit->PostMessage(WM_VSCROLL, SB_BOTTOM, 0);
+}
+
+void CMcDemoDlg::DataToHexString(const char* pData, const int size, CString& strOut)
+{
+	strOut.Empty();
+	for (int i = 0; i < size; i++) {
+		if (i < size - 1) {
+			strOut.AppendFormat(_T("%02X "), (BYTE)pData[i]);
+		}
+		else {
+			strOut.AppendFormat(_T("%02X"), (BYTE)pData[i]);
+		}
+	}
+}
+
+int CMcDemoDlg::HexStringToData(CString& strHex, char* pszBuffer, const int nBufferSize)
+{
+	int index = 0;
+	int nLength = strHex.GetLength();
+	CString strItem;
+	for (int i = 0; i < nLength; i++) {
+		if (strHex.GetAt(i) == ' ') {
+			if (!strItem.IsEmpty()) {
+				BYTE b = (BYTE)strtol(strItem, NULL, 16);
+				pszBuffer[index] = b;
+				index++;
+				if (index >= nBufferSize) {
+					break;
+				}
+				strItem.Empty();
+			}
+			continue;
+		}
+
+		strItem.AppendChar(strHex.GetAt(i));
+		if (strItem.GetLength() == 2) {
+			BYTE b = (BYTE)strtol(strItem, NULL, 16);
+			pszBuffer[index] = b;
+			index++;
+			if (index >= nBufferSize) {
+				break;
+			}
+			strItem.Empty();
+		}
+	}
+
+	return index;
+}
+
+void CMcDemoDlg::UpdateUISecsion1()
+{
+	if (!::IsWindow(GetSafeHwnd())) {
+		return;
+	}
+
+	GetDlgItem(IDC_BUTTON_CREATE)->EnableWindow(m_pChannel == NULL);
+	GetDlgItem(IDC_BUTTON_CLOSE)->EnableWindow(m_pChannel != NULL);
+	SetDlgItemText(IDC_BUTTON_CLOSE, (m_pChannel != NULL && m_pChannel->isConnected()) ? _T("Close") : _T("Open"));
+	GetDlgItem(IDC_BUTTON_DESTROY)->EnableWindow(m_pChannel != NULL);
+}
+
+void CMcDemoDlg::UpdateUISecsion2()
+{
+	if (!::IsWindow(GetSafeHwnd())) {
+		return;
+	}
+
+	BOOL bEnable = (m_pChannel != NULL && m_pChannel->isConnected());
+	GetDlgItem(IDC_RADIO1)->EnableWindow(bEnable);
+	GetDlgItem(IDC_RADIO2)->EnableWindow(bEnable);
+	GetDlgItem(IDC_EDIT_RAW)->EnableWindow(bEnable);
+	GetDlgItem(IDC_BUTTON_SEND)->EnableWindow(bEnable);
+	GetDlgItem(IDC_COMBO_CMD)->EnableWindow(bEnable);
+	GetDlgItem(IDC_COMBO_SUBCMD)->EnableWindow(bEnable);
+	GetDlgItem(IDC_COMBO_SOFTITEM)->EnableWindow(bEnable);
+	GetDlgItem(IDC_EDIT_HEAD_ADDR)->EnableWindow(bEnable);
+	GetDlgItem(IDC_EDIT_READ_COUNT)->EnableWindow(bEnable);
+	GetDlgItem(IDC_BUTTON_RAWDATA)->EnableWindow(bEnable);
+}
+
+void CMcDemoDlg::UpdateUISecsion3()
+{
+	if (!::IsWindow(GetSafeHwnd())) {
+		return;
+	}
+
+	GetDlgItem(IDC_COMBO_SOFTITEM2)->EnableWindow((m_pChannel != NULL && m_pChannel->isConnected()));
+	GetDlgItem(IDC_EDIT_HEAD_ADDR2)->EnableWindow((m_pChannel != NULL && m_pChannel->isConnected()));
+	GetDlgItem(IDC_BUTTON_READ_DWORD)->EnableWindow((m_pChannel != NULL && m_pChannel->isConnected()));
+	GetDlgItem(IDC_BUTTON_READ)->EnableWindow((m_pChannel != NULL && m_pChannel->isConnected()));
+	GetDlgItem(IDC_BUTTON_READ_BIT)->EnableWindow((m_pChannel != NULL && m_pChannel->isConnected()));
+	GetDlgItem(IDC_EDIT_WRITE_VALUE)->EnableWindow((m_pChannel != NULL && m_pChannel->isConnected()));
+	GetDlgItem(IDC_CHECK_WRITE_BIT_VALUE)->EnableWindow((m_pChannel != NULL && m_pChannel->isConnected()));
+	GetDlgItem(IDC_BUTTON_WRITE_DWORD)->EnableWindow((m_pChannel != NULL && m_pChannel->isConnected()));
+	GetDlgItem(IDC_BUTTON_WRITE)->EnableWindow((m_pChannel != NULL && m_pChannel->isConnected()));
+	GetDlgItem(IDC_BUTTON_WRITE_BIT)->EnableWindow((m_pChannel != NULL && m_pChannel->isConnected()));
+}
+
+void CMcDemoDlg::OnBnClickedButtonRawdata()
+{
+	/*
+	char szBuffer[] = {0x50, 0x00, 0x00, 0xff, 0xff, 0x03, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x01,
+	0x04, 0x00, 0x00, 0x64, 0x00, 0x00, 0xa8, 0x01, 0x00};
+
+
+	// 软元类型
+	static char szSoftItem[] = {0x90, 0xa8, 0x9c, 0x9d, 0xb0};
+	CComboBox* pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_SOFTITEM);
+	szBuffer[18] = szSoftItem[pComboBox->GetCurSel()];
+
+
+	// 首地址
+	int nHeadAddr = GetDlgItemInt(IDC_EDIT_HEAD_ADDR);
+	szBuffer[15] = nHeadAddr & 0xff;
+	szBuffer[16] = (nHeadAddr & 0xff00) >> 8;
+	szBuffer[17] = (nHeadAddr & 0xff0000) >> 16;
+
+
+	// 数量
+	int nReadCount = GetDlgItemInt(IDC_EDIT_READ_COUNT);
+	szBuffer[19] = nReadCount & 0xff;
+	szBuffer[20] = (nReadCount & 0xff00) >> 8;
+
+
+	// 命令
+	int nCmd = ((CComboBox*)GetDlgItem(IDC_COMBO_CMD))->GetCurSel();
+	if (nCmd == 0) {
+	// 成批读
+	szBuffer[11] = 0x01;
+	szBuffer[12] = 0x04;
+	}
+	else if (nCmd == 1) {
+	// 成批写
+	szBuffer[11] = 0x01;
+	szBuffer[12] = 0x14;
+	}
+	else if (nCmd == 2) {
+	// 随机读
+	szBuffer[11] = 0x03;
+	szBuffer[12] = 0x04;
+	}
+	else if (nCmd == 3) {
+	// 测试(随机写)
+	szBuffer[11] = 0x02;
+	szBuffer[12] = 0x14;
+	}
+	else if (nCmd == 4) {
+	// 监视登录数据
+	szBuffer[11] = 0x01;
+	szBuffer[12] = 0x08;
+	}
+	else if (nCmd == 5) {
+	// 监视
+	szBuffer[11] = 0x02;
+	szBuffer[12] = 0x08;
+	}
+
+
+	// 子命令
+	int nSubCmd = ((CComboBox*)GetDlgItem(IDC_COMBO_SUBCMD))->GetCurSel();
+	if (nSubCmd == 0) {
+	// 按字
+	szBuffer[13] = 0x00;
+	szBuffer[14] = 0x00;
+	}
+	else if (nSubCmd == 1) {
+	// 按位
+	szBuffer[13] = 0x00;
+	szBuffer[14] = 0x01;
+	}
+
+
+
+
+	CString strRawData;
+	DataToHexString(szBuffer, sizeof(szBuffer), strRawData);
+	SetDlgItemText(IDC_EDIT_RAW, strRawData);
+	*/
+
+
+	// 新方法
+	CComboBox* pComboBox = NULL;
+	CString strLbText;
+	pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_CMD);
+	pComboBox->GetLBText(pComboBox->GetCurSel(), strLbText);
+	std::string strCmd = (LPTSTR)(LPCTSTR)strLbText;
+	MC::CMD cmd;
+	MCL_GetCmd(strCmd, cmd);
+
+	pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_SUBCMD);
+	pComboBox->GetLBText(pComboBox->GetCurSel(), strLbText);
+	std::string strSubCmd = (LPTSTR)(LPCTSTR)strLbText;
+	MC::SUBCMD subCmd;
+	MCL_GetSubCmd(strSubCmd, subCmd);
+
+	pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_SOFTITEM);
+	pComboBox->GetLBText(pComboBox->GetCurSel(), strLbText);
+	std::string strSoftComponent = (LPTSTR)(LPCTSTR)strLbText;
+	MC::SOFT_COMPONENT softComponent;
+	MCL_GetSoftComponent(strSoftComponent, softComponent);
+
+	int nFirstAddr = GetDlgItemInt(IDC_EDIT_HEAD_ADDR);
+	int nOperateCount = GetDlgItemInt(IDC_EDIT_READ_COUNT);
+	char szRawData[1024];
+	char szAttach[4] = { 0x10, 0x11, 0x12, 0x13 };
+	int nDataSize = MCL_GetRawData(cmd, subCmd, softComponent, nFirstAddr, nOperateCount, NULL, 0, szRawData, sizeof(szRawData));
+
+	CString strRawData2;
+	DataToHexString(szRawData, nDataSize, strRawData2);
+	SetDlgItemText(IDC_EDIT_RAW, strRawData2);
+	// AfxMessageBox(strRawData2);
+}
+
+void CMcDemoDlg::OnBnClickedButtonRead()
+{
+	CComboBox* pComboBox;
+	CString strLbText;
+
+	pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_SOFTITEM2);
+	pComboBox->GetLBText(pComboBox->GetCurSel(), strLbText);
+	std::string strSoftComponent = (LPTSTR)(LPCTSTR)strLbText;
+	MC::SOFT_COMPONENT softComponent;
+	MCL_GetSoftComponent(strSoftComponent, softComponent);
+
+	int nAddr = GetDlgItemInt(IDC_EDIT_HEAD_ADDR2);
+
+	if (m_pChannel != NULL && m_pChannel->isConnected()) {
+		auto funOnRead = [&](IMcChannel* pChannel, int addr, DWORD value, int flag) -> void {
+			AppendLog(">> funOnRead:[%d]\r\n", value);
+			CString strText;
+			strText.Format(_T("Read Word(%d)"), value);
+			SetDlgItemText(IDC_BUTTON_READ, strText);
+		};
+		m_pChannel->readWord(softComponent, nAddr, funOnRead);
+	}
+}
+
+
+void CMcDemoDlg::OnBnClickedButtonReadBit()
+{
+	CComboBox* pComboBox;
+	CString strLbText;
+
+	pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_SOFTITEM2);
+	pComboBox->GetLBText(pComboBox->GetCurSel(), strLbText);
+	std::string strSoftComponent = (LPTSTR)(LPCTSTR)strLbText;
+	MC::SOFT_COMPONENT softComponent;
+	MCL_GetSoftComponent(strSoftComponent, softComponent);
+
+	int nAddr = GetDlgItemInt(IDC_EDIT_HEAD_ADDR2);
+
+	if (m_pChannel != NULL && m_pChannel->isConnected()) {
+		auto funOnRead = [&](IMcChannel* pChannel, int addr, DWORD value, int flag) -> void {
+			AppendLog(">> funOnRead:[%s]\r\n", value != 0 ? "ON" : "OFF");
+			CString strText;
+			strText.Format(_T("Read Bit(%s)"), value != 0 ? "ON" : "OFF");
+			SetDlgItemText(IDC_BUTTON_READ_BIT, strText);
+		};
+		m_pChannel->readBit(softComponent, nAddr, funOnRead);
+	}
+}
+
+void CMcDemoDlg::OnBnClickedButtonWrite()
+{
+	CComboBox* pComboBox;
+	CString strLbText;
+
+	pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_SOFTITEM2);
+	pComboBox->GetLBText(pComboBox->GetCurSel(), strLbText);
+	std::string strSoftComponent = (LPTSTR)(LPCTSTR)strLbText;
+	MC::SOFT_COMPONENT softComponent;
+	MCL_GetSoftComponent(strSoftComponent, softComponent);
+
+	int nAddr = GetDlgItemInt(IDC_EDIT_HEAD_ADDR2);
+	int nValue = GetDlgItemInt(IDC_EDIT_WRITE_VALUE);
+
+	if (m_pChannel != NULL && m_pChannel->isConnected()) {
+		auto funOnWrite = [&](IMcChannel* pChannel, int addr, DWORD value) -> void {
+			AppendLog(">> funOnWrite:[%d]\r\n", value);
+		};
+		m_pChannel->writeWord(softComponent, nAddr, nValue, funOnWrite);
+	}
+}
+
+void CMcDemoDlg::OnBnClickedButtonReadDword()
+{
+	CComboBox* pComboBox;
+	CString strLbText;
+
+	pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_SOFTITEM2);
+	pComboBox->GetLBText(pComboBox->GetCurSel(), strLbText);
+	std::string strSoftComponent = (LPTSTR)(LPCTSTR)strLbText;
+	MC::SOFT_COMPONENT softComponent;
+	MCL_GetSoftComponent(strSoftComponent, softComponent);
+
+	int nAddr = GetDlgItemInt(IDC_EDIT_HEAD_ADDR2);
+
+	if (m_pChannel != NULL && m_pChannel->isConnected()) {
+		auto funOnRead = [&](IMcChannel* pChannel, int addr, DWORD value, int flag) -> void {
+			AppendLog(">> funOnRead:[%d]\r\n", value);
+			CString strText;
+			strText.Format(_T("Read DWORD(%d)"), value);
+			SetDlgItemText(IDC_BUTTON_READ_DWORD, strText);
+		};
+		m_pChannel->readDWord(softComponent, nAddr, funOnRead);
+	}
+}
+
+void CMcDemoDlg::OnBnClickedButtonWriteDword()
+{
+	CComboBox* pComboBox;
+	CString strLbText;
+
+	pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_SOFTITEM2);
+	pComboBox->GetLBText(pComboBox->GetCurSel(), strLbText);
+	std::string strSoftComponent = (LPTSTR)(LPCTSTR)strLbText;
+	MC::SOFT_COMPONENT softComponent;
+	MCL_GetSoftComponent(strSoftComponent, softComponent);
+
+	int nAddr = GetDlgItemInt(IDC_EDIT_HEAD_ADDR2);
+	int nValue = GetDlgItemInt(IDC_EDIT_WRITE_VALUE);
+
+	if (m_pChannel != NULL && m_pChannel->isConnected()) {
+		auto funOnWrite = [&](IMcChannel* pChannel, int addr, DWORD value) -> void {
+			AppendLog(">> funOnWrite:[%d]\r\n", value);
+		};
+		m_pChannel->writeDWord(softComponent, nAddr, nValue, funOnWrite);
+	}
+}
+
+void CMcDemoDlg::OnBnClickedButtonWriteBit()
+{
+	CComboBox* pComboBox;
+	CString strLbText;
+
+	pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_SOFTITEM2);
+	pComboBox->GetLBText(pComboBox->GetCurSel(), strLbText);
+	std::string strSoftComponent = (LPTSTR)(LPCTSTR)strLbText;
+	MC::SOFT_COMPONENT softComponent;
+	MCL_GetSoftComponent(strSoftComponent, softComponent);
+
+	int nAddr = GetDlgItemInt(IDC_EDIT_HEAD_ADDR2);
+	CButton* pButton = (CButton*)GetDlgItem(IDC_CHECK_WRITE_BIT_VALUE);
+	BOOL bValue = pButton->GetCheck();;
+
+	if (m_pChannel != NULL && m_pChannel->isConnected()) {
+		auto funOnWrite = [&](IMcChannel* pChannel, int addr, DWORD value) -> void {
+			AppendLog(">> funOnWrite:[%s]\r\n", value != 0 ? "ON" : "OFF");
+		};
+		m_pChannel->writeBit(softComponent, nAddr, bValue, funOnWrite);
+	}
+}
+
+void CMcDemoDlg::OnBnClickedCheckWriteBitValue()
+{
+	CButton* pButton = (CButton*)GetDlgItem(IDC_CHECK_WRITE_BIT_VALUE);
+	pButton->SetWindowText(pButton->GetCheck() ? "ON" : "OFF");
+}
+
diff --git a/SourceCode/Bond/McLibrarySDK/McDemo/McDemo/McDemo/mcdemodlg.h b/SourceCode/Bond/McLibrarySDK/McDemo/McDemo/McDemo/mcdemodlg.h
new file mode 100644
index 0000000..1178093
--- /dev/null
+++ b/SourceCode/Bond/McLibrarySDK/McDemo/McDemo/McDemo/mcdemodlg.h
@@ -0,0 +1,56 @@
+
+// McDemoDlg.h : 头文件
+//
+
+#pragma once
+
+
+// CMcDemoDlg 对话框
+class CMcDemoDlg : public CDialogEx
+{
+// 构造
+public:
+	CMcDemoDlg(CWnd* pParent = NULL);	// 标准构造函数
+	void AppendLog(CString strText);
+	void AppendLog(char* szMessage, ...);
+	void DataToHexString(const char* pData, const int size, CString& strOut);
+	int HexStringToData(CString& strHex, char* pszBuffer, const int nBufferSize);
+	void UpdateUISecsion1();
+	void UpdateUISecsion2();
+	void UpdateUISecsion3();
+
+// 对话框数据
+#ifdef AFX_DESIGN_TIME
+	enum { IDD = IDD_MCDEMO_DIALOG };
+#endif
+
+	protected:
+	virtual void DoDataExchange(CDataExchange* pDX);	// DDX/DDV 支持
+
+
+// 实现
+protected:
+	HICON m_hIcon;
+	McChannelListener m_mcChannellistener;
+	IMcChannel* m_pChannel;
+
+	// 生成的消息映射函数
+	virtual BOOL OnInitDialog();
+	afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
+	afx_msg void OnPaint();
+	afx_msg HCURSOR OnQueryDragIcon();
+	DECLARE_MESSAGE_MAP()
+public:
+	afx_msg void OnBnClickedButtonCreate();
+	afx_msg void OnBnClickedButtonSend();
+	afx_msg void OnBnClickedButtonClose();
+	afx_msg void OnBnClickedButtonDestroy();
+	afx_msg void OnBnClickedButtonRead();
+	afx_msg void OnBnClickedButtonRawdata();
+	afx_msg void OnBnClickedButtonWrite();
+	afx_msg void OnBnClickedButtonReadBit();
+	afx_msg void OnBnClickedCheckWriteBitValue();
+	afx_msg void OnBnClickedButtonWriteBit();
+	afx_msg void OnBnClickedButtonReadDword();
+	afx_msg void OnBnClickedButtonWriteDword();
+};
diff --git a/SourceCode/Bond/McLibrarySDK/McDemo/McDemo/McDemo/readme.txt b/SourceCode/Bond/McLibrarySDK/McDemo/McDemo/McDemo/readme.txt
new file mode 100644
index 0000000..9ca4860
--- /dev/null
+++ b/SourceCode/Bond/McLibrarySDK/McDemo/McDemo/McDemo/readme.txt
@@ -0,0 +1,67 @@
+锘�================================================================================
+    MICROSOFT 鍩虹绫诲簱 : McDemo 椤圭洰姒傝堪
+===============================================================================
+
+搴旂敤绋嬪簭鍚戝宸蹭负鎮ㄥ垱寤轰簡姝� McDemo 搴旂敤绋嬪簭銆傛搴旂敤绋嬪簭涓嶄粎婕旂ず Microsoft 鍩虹绫荤殑鍩烘湰浣跨敤鏂规硶锛岃繕鍙綔涓烘偍缂栧啓搴旂敤绋嬪簭鐨勮捣鐐广��
+
+鏈枃浠舵瑕佷粙缁嶇粍鎴� McDemo 搴旂敤绋嬪簭鐨勬瘡涓枃浠剁殑鍐呭銆�
+
+McDemo.vcxproj
+    杩欐槸浣跨敤搴旂敤绋嬪簭鍚戝鐢熸垚鐨� VC++ 椤圭洰鐨勪富椤圭洰鏂囦欢锛屽叾涓寘鍚敓鎴愯鏂囦欢鐨� Visual C++ 鐨勭増鏈俊鎭紝浠ュ強鏈夊叧浣跨敤搴旂敤绋嬪簭鍚戝閫夋嫨鐨勫钩鍙般�侀厤缃拰椤圭洰鍔熻兘鐨勪俊鎭��
+
+McDemo.vcxproj.filters
+    杩欐槸浣跨敤鈥滃簲鐢ㄧ▼搴忓悜瀵尖�濈敓鎴愮殑 VC++ 椤圭洰绛涢�夊櫒鏂囦欢銆傚畠鍖呭惈鏈夊叧椤圭洰鏂囦欢涓庣瓫閫夊櫒涔嬮棿鐨勫叧鑱斾俊鎭�傚湪 IDE 涓紝閫氳繃杩欑鍏宠仈锛屽湪鐗瑰畾鑺傜偣涓嬩互鍒嗙粍褰㈠紡鏄剧ず鍏锋湁鐩镐技鎵╁睍鍚嶇殑鏂囦欢銆備緥濡傦紝鈥�.cpp鈥濇枃浠朵笌鈥滄簮鏂囦欢鈥濈瓫閫夊櫒鍏宠仈銆�
+
+McDemo.h
+    杩欐槸搴旂敤绋嬪簭鐨勪富澶存枃浠躲��
+    鍏朵腑鍖呮嫭鍏朵粬椤圭洰鐗瑰畾鐨勬爣澶达紙鍖呮嫭 Resource.h锛夛紝骞跺0鏄� CMcDemoApp 搴旂敤绋嬪簭绫汇��
+
+McDemo.cpp
+    杩欐槸鍖呭惈搴旂敤绋嬪簭绫� CMcDemoApp 鐨勪富搴旂敤绋嬪簭婧愭枃浠躲��
+
+McDemo.rc
+    杩欐槸绋嬪簭浣跨敤鐨勬墍鏈� Microsoft Windows 璧勬簮鐨勫垪琛ㄣ�傚畠鍖呮嫭 RES 瀛愮洰褰曚腑瀛樺偍鐨勫浘鏍囥�佷綅鍥惧拰鍏夋爣銆傛鏂囦欢鍙互鐩存帴鍦� Microsoft Visual C++ 涓繘琛岀紪杈戙�傞」鐩祫婧愬寘鍚湪 2052 涓��
+
+res\McDemo.ico
+    杩欐槸鐢ㄤ綔搴旂敤绋嬪簭鍥炬爣鐨勫浘鏍囨枃浠躲�傛鍥炬爣鍖呮嫭鍦ㄤ富璧勬簮鏂囦欢 McDemo.rc 涓��
+
+res\McDemo.rc2
+    姝ゆ枃浠跺寘鍚笉鍦� Microsoft Visual C++ 涓繘琛岀紪杈戠殑璧勬簮銆傛偍搴旇灏嗕笉鍙敱璧勬簮缂栬緫鍣ㄧ紪杈戠殑鎵�鏈夎祫婧愭斁鍦ㄦ鏂囦欢涓��
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+搴旂敤绋嬪簭鍚戝鍒涘缓涓�涓璇濇绫伙細
+
+McDemoDlg.h銆丮cDemoDlg.cpp - 瀵硅瘽妗�
+    杩欎簺鏂囦欢鍖呭惈 CMcDemoDlg 绫汇�傛绫诲畾涔夊簲鐢ㄧ▼搴忕殑涓诲璇濇鐨勮涓恒�傚璇濇妯℃澘鍖呭惈鍦� McDemo.rc 涓紝璇ユ枃浠跺彲浠ュ湪 Microsoft Visual C++ 涓紪杈戙��
+
+/////////////////////////////////////////////////////////////////////////////
+
+鍏朵粬鍔熻兘锛�
+
+ActiveX 鎺т欢
+    璇ュ簲鐢ㄧ▼搴忓寘鍚浣跨敤 ActiveX 鎺т欢鐨勬敮鎸併��
+
+/////////////////////////////////////////////////////////////////////////////
+
+鍏朵粬鏍囧噯鏂囦欢:
+
+StdAfx.h, StdAfx.cpp
+    杩欎簺鏂囦欢鐢ㄤ簬鐢熸垚鍚嶄负 McDemo.pch 鐨勯缂栬瘧澶� (PCH) 鏂囦欢鍜屽悕涓� StdAfx.obj 鐨勯缂栬瘧绫诲瀷鏂囦欢銆�
+
+Resource.h
+    杩欐槸鏍囧噯澶存枃浠讹紝鍙敤浜庡畾涔夋柊鐨勮祫婧� ID銆侻icrosoft Visual C++ 灏嗚鍙栧苟鏇存柊姝ゆ枃浠躲��
+
+McDemo.manifest
+	Windows XP 浣跨敤搴旂敤绋嬪簭娓呭崟鏂囦欢鏉ユ弿杩扮壒瀹氱増鏈殑骞惰绋嬪簭闆嗙殑搴旂敤绋嬪簭渚濊禆椤广�傚姞杞界▼搴忎娇鐢ㄨ繖浜涗俊鎭潵浠庣▼搴忛泦缂撳瓨涓姞杞界浉搴旂殑绋嬪簭闆嗭紝骞朵繚鎶ゅ叾涓嶈搴旂敤绋嬪簭璁块棶銆傚簲鐢ㄧ▼搴忔竻鍗曞彲鑳戒細鍖呭惈鍦ㄥ唴锛屼互浣滀负涓庡簲鐢ㄧ▼搴忓彲鎵ц鏂囦欢瀹夎鍦ㄥ悓涓�鏂囦欢澶逛腑鐨勫閮� .manifest 鏂囦欢杩涜閲嶆柊鍒嗗彂锛屽畠杩樺彲鑳戒互璧勬簮鐨勫舰寮忓寘鍚湪鍙墽琛屾枃浠朵腑銆�
+/////////////////////////////////////////////////////////////////////////////
+
+鍏朵粬娉ㄩ噴:
+
+搴旂敤绋嬪簭鍚戝浣跨敤鈥淭ODO:鈥濇潵鎸囩ず搴旀坊鍔犳垨鑷畾涔夌殑婧愪唬鐮侀儴鍒嗐��
+
+濡傛灉搴旂敤绋嬪簭浣跨敤鍏变韩 DLL 涓殑 MFC锛屾偍灏嗛渶瑕侀噸鏂板垎鍙� MFC DLL銆傚鏋滃簲鐢ㄧ▼搴忔墍浣跨敤鐨勮瑷�涓庢搷浣滅郴缁熺殑鍖哄煙璁剧疆涓嶅悓锛屽垯杩橀渶瑕侀噸鏂板垎鍙戠浉搴旂殑鏈湴鍖栬祫婧� mfc110XXX.DLL銆�
+鏈夊叧涓婅堪璇濋鐨勬洿澶氫俊鎭紝璇峰弬瑙� MSDN 鏂囨。涓湁鍏抽噸鏂板垎鍙� Visual C++ 搴旂敤绋嬪簭鐨勯儴鍒嗐��
+
+/////////////////////////////////////////////////////////////////////////////
diff --git a/SourceCode/Bond/McLibrarySDK/McDemo/McDemo/McDemo/res/McDemo.ico b/SourceCode/Bond/McLibrarySDK/McDemo/McDemo/McDemo/res/McDemo.ico
new file mode 100644
index 0000000..d56fbcd
--- /dev/null
+++ b/SourceCode/Bond/McLibrarySDK/McDemo/McDemo/McDemo/res/McDemo.ico
Binary files differ
diff --git a/SourceCode/Bond/McLibrarySDK/McDemo/McDemo/McDemo/res/McDemo.rc2 b/SourceCode/Bond/McLibrarySDK/McDemo/McDemo/McDemo/res/McDemo.rc2
new file mode 100644
index 0000000..3581d57
--- /dev/null
+++ b/SourceCode/Bond/McLibrarySDK/McDemo/McDemo/McDemo/res/McDemo.rc2
Binary files differ
diff --git a/SourceCode/Bond/McLibrarySDK/McDemo/McDemo/McDemo/res/application.exe.manifest b/SourceCode/Bond/McLibrarySDK/McDemo/McDemo/McDemo/res/application.exe.manifest
new file mode 100644
index 0000000..b96c40d
--- /dev/null
+++ b/SourceCode/Bond/McLibrarySDK/McDemo/McDemo/McDemo/res/application.exe.manifest
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
+    <assemblyIdentity
+         name="XP style manifest"
+         processorArchitecture="amd64"
+         version="1.0.0.0"
+         type="win32"/>
+    <dependency>
+        <dependentAssembly>
+            <assemblyIdentity
+                type="win32"
+                name="Microsoft.Windows.Common-Controls"
+                version="6.0.0.0"
+                processorArchitecture="amd64"
+                publicKeyToken="6595b64144ccf1df"
+                language="*"
+            />
+        </dependentAssembly>
+    </dependency>
+</assembly>
\ No newline at end of file
diff --git a/SourceCode/Bond/McLibrarySDK/McDemo/McDemo/McDemo/resource.h b/SourceCode/Bond/McLibrarySDK/McDemo/McDemo/McDemo/resource.h
new file mode 100644
index 0000000..5f63b6d
--- /dev/null
+++ b/SourceCode/Bond/McLibrarySDK/McDemo/McDemo/McDemo/resource.h
Binary files differ
diff --git a/SourceCode/Bond/McLibrarySDK/McDemo/McDemo/McDemo/stdafx.cpp b/SourceCode/Bond/McLibrarySDK/McDemo/McDemo/McDemo/stdafx.cpp
new file mode 100644
index 0000000..f1e5cec
--- /dev/null
+++ b/SourceCode/Bond/McLibrarySDK/McDemo/McDemo/McDemo/stdafx.cpp
@@ -0,0 +1,8 @@
+
+// stdafx.cpp : 只包括标准包含文件的源文件
+// McDemo.pch 将作为预编译头
+// stdafx.obj 将包含预编译类型信息
+
+#include "stdafx.h"
+
+
diff --git a/SourceCode/Bond/McLibrarySDK/McDemo/McDemo/McDemo/stdafx.h b/SourceCode/Bond/McLibrarySDK/McDemo/McDemo/McDemo/stdafx.h
new file mode 100644
index 0000000..7d8a96a
--- /dev/null
+++ b/SourceCode/Bond/McLibrarySDK/McDemo/McDemo/McDemo/stdafx.h
@@ -0,0 +1,54 @@
+
+// stdafx.h : 标准系统包含文件的包含文件,
+// 或是经常使用但不常更改的
+// 特定于项目的包含文件
+
+#pragma once
+
+#ifndef VC_EXTRALEAN
+#define VC_EXTRALEAN            // 从 Windows 头中排除极少使用的资料
+#endif
+
+#include "targetver.h"
+
+#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS      // 某些 CString 构造函数将是显式的
+
+// 关闭 MFC 对某些常见但经常可放心忽略的警告消息的隐藏
+#define _AFX_ALL_WARNINGS
+
+#include <afxwin.h>         // MFC 核心组件和标准组件
+#include <afxext.h>         // MFC 扩展
+
+
+#include <afxdisp.h>        // MFC 自动化类
+
+
+
+#ifndef _AFX_NO_OLE_SUPPORT
+#include <afxdtctl.h>           // MFC 对 Internet Explorer 4 公共控件的支持
+#endif
+#ifndef _AFX_NO_AFXCMN_SUPPORT
+#include <afxcmn.h>             // MFC 对 Windows 公共控件的支持
+#endif // _AFX_NO_AFXCMN_SUPPORT
+
+#include <afxcontrolbars.h>     // 功能区和控件条的 MFC 支持
+
+
+
+
+
+
+
+
+
+#ifdef _UNICODE
+#if defined _M_IX86
+#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"")
+#elif defined _M_X64
+#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"")
+#else
+#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
+#endif
+#endif
+
+
diff --git a/SourceCode/Bond/McLibrarySDK/McDemo/McDemo/McDemo/targetver.h b/SourceCode/Bond/McLibrarySDK/McDemo/McDemo/McDemo/targetver.h
new file mode 100644
index 0000000..416cebf
--- /dev/null
+++ b/SourceCode/Bond/McLibrarySDK/McDemo/McDemo/McDemo/targetver.h
@@ -0,0 +1,8 @@
+#pragma once
+
+// 包括 SDKDDKVer.h 将定义可用的最高版本的 Windows 平台。
+
+// 如果要为以前的 Windows 平台生成应用程序,请包括 WinSDKVer.h,并将
+// 将 _WIN32_WINNT 宏设置为要支持的平台,然后再包括 SDKDDKVer.h。
+
+#include <SDKDDKVer.h>
diff --git a/SourceCode/Bond/McLibrarySDK/McDemo/McDemoDlg.cpp b/SourceCode/Bond/McLibrarySDK/McDemo/McDemoDlg.cpp
new file mode 100644
index 0000000..0484c24
--- /dev/null
+++ b/SourceCode/Bond/McLibrarySDK/McDemo/McDemoDlg.cpp
@@ -0,0 +1,794 @@
+
+// McDemoDlg.cpp : 实现文件
+//
+
+#include "stdafx.h"
+#include "McDemo.h"
+#include "McDemoDlg.h"
+#include "afxdialogex.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#endif
+
+
+#define MAX_MESSAGE_LENGTH		1024
+#define CHANNEL_NAME			_T("Test1")
+
+// 用于应用程序“关于”菜单项的 CAboutDlg 对话框
+
+class CAboutDlg : public CDialogEx
+{
+public:
+	CAboutDlg();
+
+// 对话框数据
+#ifdef AFX_DESIGN_TIME
+	enum { IDD = IDD_ABOUTBOX };
+#endif
+
+	protected:
+	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持
+
+// 实现
+protected:
+	DECLARE_MESSAGE_MAP()
+};
+
+CAboutDlg::CAboutDlg() : CDialogEx(IDD_ABOUTBOX)
+{
+}
+
+void CAboutDlg::DoDataExchange(CDataExchange* pDX)
+{
+	CDialogEx::DoDataExchange(pDX);
+}
+
+BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
+END_MESSAGE_MAP()
+
+
+// CMcDemoDlg 对话框
+
+
+
+CMcDemoDlg::CMcDemoDlg(CWnd* pParent /*=NULL*/)
+	: CDialogEx(IDD_MCDEMO_DIALOG, pParent)
+{
+	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
+	m_pChannel = NULL;
+}
+
+void CMcDemoDlg::DoDataExchange(CDataExchange* pDX)
+{
+	CDialogEx::DoDataExchange(pDX);
+}
+
+BEGIN_MESSAGE_MAP(CMcDemoDlg, CDialogEx)
+	ON_WM_SYSCOMMAND()
+	ON_WM_PAINT()
+	ON_WM_QUERYDRAGICON()
+	ON_BN_CLICKED(IDC_BUTTON_CREATE, &CMcDemoDlg::OnBnClickedButtonCreate)
+	ON_BN_CLICKED(IDC_BUTTON_SEND, &CMcDemoDlg::OnBnClickedButtonSend)
+	ON_BN_CLICKED(IDC_BUTTON_CLOSE, &CMcDemoDlg::OnBnClickedButtonClose)
+	ON_BN_CLICKED(IDC_BUTTON_DESTROY, &CMcDemoDlg::OnBnClickedButtonDestroy)
+	ON_BN_CLICKED(IDC_BUTTON_READ, &CMcDemoDlg::OnBnClickedButtonRead)
+	ON_BN_CLICKED(IDC_BUTTON_RAWDATA, &CMcDemoDlg::OnBnClickedButtonRawdata)
+	ON_BN_CLICKED(IDC_BUTTON_WRITE, &CMcDemoDlg::OnBnClickedButtonWrite)
+	ON_BN_CLICKED(IDC_BUTTON_READ_BIT, &CMcDemoDlg::OnBnClickedButtonReadBit)
+	ON_BN_CLICKED(IDC_CHECK_WRITE_BIT_VALUE, &CMcDemoDlg::OnBnClickedCheckWriteBitValue)
+	ON_BN_CLICKED(IDC_BUTTON_WRITE_BIT, &CMcDemoDlg::OnBnClickedButtonWriteBit)
+	ON_BN_CLICKED(IDC_BUTTON_READ_DWORD, &CMcDemoDlg::OnBnClickedButtonReadDword)
+	ON_BN_CLICKED(IDC_BUTTON_WRITE_DWORD, &CMcDemoDlg::OnBnClickedButtonWriteDword)
+	ON_WM_TIMER()
+END_MESSAGE_MAP()
+
+
+// CMcDemoDlg 消息处理程序
+
+BOOL CMcDemoDlg::OnInitDialog()
+{
+	CDialogEx::OnInitDialog();
+
+	// 将“关于...”菜单项添加到系统菜单中。
+
+	// IDM_ABOUTBOX 必须在系统命令范围内。
+	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
+	ASSERT(IDM_ABOUTBOX < 0xF000);
+
+	CMenu* pSysMenu = GetSystemMenu(FALSE);
+	if (pSysMenu != NULL)
+	{
+		BOOL bNameValid;
+		CString strAboutMenu;
+		bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
+		ASSERT(bNameValid);
+		if (!strAboutMenu.IsEmpty())
+		{
+			pSysMenu->AppendMenu(MF_SEPARATOR);
+			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
+		}
+	}
+
+	// 设置此对话框的图标。  当应用程序主窗口不是对话框时,框架将自动
+	//  执行此操作
+	SetIcon(m_hIcon, TRUE);			// 设置大图标
+	SetIcon(m_hIcon, FALSE);		// 设置小图标
+
+	// TODO: 在此添加额外的初始化代码
+
+
+	CIPAddressCtrl* pIpAddressCtrl = (CIPAddressCtrl*)GetDlgItem(IDC_IPADDRESS_SERVER);
+	pIpAddressCtrl->SetAddress(192, 168, 90, 17);
+	// pIpAddressCtrl->SetAddress(127, 0, 0, 1);
+	SetDlgItemInt(IDC_EDIT_SERVER_PORT, 8080);
+
+	((CButton*)GetDlgItem(IDC_RADIO2))->SetCheck(1);
+	//CString strText = _T("50 00 00 FF FF 03 00 0C 00 10 00 01 04 00 00 64 00 00 A8 01 00");
+	//SetDlgItemText(IDC_EDIT_RAW, strText);
+
+
+	// 软元件
+	std::vector<std::string> softComponents;
+	int softComponentsSize = MCL_GetSoftComponents(softComponents);
+	CComboBox* pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_SOFTITEM);
+	CComboBox* pComboBox2 = (CComboBox*)GetDlgItem(IDC_COMBO_SOFTITEM2);
+	for (auto item : softComponents) {
+		pComboBox->InsertString(pComboBox->GetCount(), item.c_str());
+		pComboBox2->InsertString(pComboBox2->GetCount(), item.c_str());
+	}
+	if (softComponentsSize > 0) {
+		pComboBox->SetCurSel(0);
+		pComboBox2->SetCurSel(0);
+	}
+
+
+	// 命令
+	std::vector<std::string> cmds;
+	int cmdsSize = MCL_GetCmds(cmds);
+	pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_CMD);
+	for (auto item : cmds) {
+		pComboBox->InsertString(pComboBox->GetCount(), item.c_str());
+	}
+	if (cmdsSize > 0) {
+		pComboBox->SetCurSel(0);
+	}
+
+
+
+	// 子命令
+	std::vector<std::string> subCmds;
+	int subCmdsSize = MCL_GetSubCmds(subCmds);
+	pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_SUBCMD);
+	for (auto item : subCmds) {
+		pComboBox->InsertString(pComboBox->GetCount(), item.c_str());
+	}
+	if (cmdsSize > 0) {
+		pComboBox->SetCurSel(0);
+	}
+
+
+	SetDlgItemInt(IDC_EDIT_HEAD_ADDR, 100);
+	SetDlgItemInt(IDC_EDIT_READ_COUNT, 1);
+	UpdateUISecsion1();
+	UpdateUISecsion2();
+	UpdateUISecsion3();
+
+	return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
+}
+
+void CMcDemoDlg::OnSysCommand(UINT nID, LPARAM lParam)
+{
+	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
+	{
+		CAboutDlg dlgAbout;
+		dlgAbout.DoModal();
+	}
+	else
+	{
+		CDialogEx::OnSysCommand(nID, lParam);
+	}
+}
+
+// 如果向对话框添加最小化按钮,则需要下面的代码
+//  来绘制该图标。  对于使用文档/视图模型的 MFC 应用程序,
+//  这将由框架自动完成。
+
+void CMcDemoDlg::OnPaint()
+{
+	if (IsIconic())
+	{
+		CPaintDC dc(this); // 用于绘制的设备上下文
+
+		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
+
+		// 使图标在工作区矩形中居中
+		int cxIcon = GetSystemMetrics(SM_CXICON);
+		int cyIcon = GetSystemMetrics(SM_CYICON);
+		CRect rect;
+		GetClientRect(&rect);
+		int x = (rect.Width() - cxIcon + 1) / 2;
+		int y = (rect.Height() - cyIcon + 1) / 2;
+
+		// 绘制图标
+		dc.DrawIcon(x, y, m_hIcon);
+	}
+	else
+	{
+		CDialogEx::OnPaint();
+	}
+}
+
+//当用户拖动最小化窗口时系统调用此函数取得光标
+//显示。
+HCURSOR CMcDemoDlg::OnQueryDragIcon()
+{
+	return static_cast<HCURSOR>(m_hIcon);
+}
+
+
+
+void CMcDemoDlg::OnBnClickedButtonCreate()
+{
+	m_mcChannellistener.funOnConnected = [&](IMcChannel* pChannel, int nErrorCode) -> void {
+		CString strText;
+		strText.Format(_T(">> funOnConnected, %s连接结果<code =  %d>\r\n"), pChannel->getName().c_str(), nErrorCode);
+		AppendLog(strText);
+
+		UpdateUISecsion1();
+		UpdateUISecsion2();
+		UpdateUISecsion3();
+	};
+	m_mcChannellistener.funOnClose = [&](IMcChannel* pChannel) -> void {
+		AppendLog(">> funOnClose, %s已关闭\r\n", pChannel->getName().c_str());
+		UpdateUISecsion1();
+		UpdateUISecsion2();
+		UpdateUISecsion3();
+	};
+	m_mcChannellistener.funOnClosing = [&](IMcChannel* pChannel) -> void {
+		AppendLog(">> funOnClosing, 正在关闭 %s\r\n", pChannel->getName().c_str());
+		UpdateUISecsion1();
+		UpdateUISecsion2();
+		UpdateUISecsion3();
+	};
+	m_mcChannellistener.funOnRead = [&](IMcChannel* pChannel, char* pData, unsigned int nDataSize, int nDecodeRet) -> void {
+		CString strText;
+		DataToHexString(pData, nDataSize, strText);
+		AppendLog(">> funOnRead:[%s]\r\n", strText);
+	};
+	m_mcChannellistener.funOnWrite = [&](IMcChannel* pChannel) -> void {
+		AppendLog(">> funOnWrite\r\n");
+	};
+
+
+	CIPAddressCtrl* pIpAddressCtrl = (CIPAddressCtrl*)GetDlgItem(IDC_IPADDRESS_SERVER);
+	BYTE b1, b2, b3, b4;
+	pIpAddressCtrl->GetAddress(b1, b2, b3, b4);
+	CString strIP;
+	strIP.Format("%d.%d.%d.%d", b1, b2, b3, b4);
+	UINT port = GetDlgItemInt(IDC_EDIT_SERVER_PORT);
+
+
+	m_pChannel = NULL;
+	if (0 == MCL_CreateChannel(m_pChannel, CHANNEL_NAME, (LPTSTR)(LPCTSTR)strIP, port, 0) && m_pChannel != NULL) {
+		m_pChannel->setChannelListener(&m_mcChannellistener);
+		CString strText;
+		strText.Format(_T(">> 创建通道(%s)成功\r\n"), m_pChannel->getName().c_str()),
+		AppendLog(strText);
+		//m_pChannel->connect();
+	}
+	else if(m_pChannel != NULL){
+		m_pChannel->setChannelListener(&m_mcChannellistener);
+		AppendLog(">> 找到现有通道(%s).\r\n", m_pChannel->getName().c_str());
+	}
+
+	UpdateUISecsion1();
+	UpdateUISecsion2();
+	UpdateUISecsion3();
+}
+
+void CMcDemoDlg::OnBnClickedButtonSend()
+{
+	
+	if (m_pChannel != NULL && m_pChannel->isConnected()) {
+		CString strText;
+		GetDlgItemText(IDC_EDIT_RAW, strText);
+		CButton* pButton = (CButton*)GetDlgItem(IDC_RADIO2);
+		if (pButton->GetCheck() == 1) {
+			char szBuffer[1024];
+			int nLen = HexStringToData(strText, szBuffer, 1024);
+			if (nLen > 0) {
+				m_pChannel->sendRawData(szBuffer, nLen);
+			}
+		}
+		else {
+			m_pChannel->sendRawData((LPTSTR)(LPCTSTR)strText, strText.GetLength());
+		}
+	}
+}
+
+void CMcDemoDlg::OnBnClickedButtonClose()
+{
+	if (m_pChannel != NULL) {
+		if (m_pChannel->isConnected()) {
+			m_pChannel->close();
+		}
+		else {
+			AppendLog(_T(">> 正在连接 %s, %s:%d\r\n"), m_pChannel->getName().c_str(), m_pChannel->getIp().c_str(), m_pChannel->getServerPort());
+			m_pChannel->connect();
+		}
+
+		UpdateUISecsion1();
+		UpdateUISecsion2();
+		UpdateUISecsion3();
+	}
+
+	/*
+	IMcChannel* pChannel = NULL;
+	if (0 == MCL_GetChannel(pChannel, CHANNEL_NAME) && pChannel != NULL) {
+		pChannel->close();
+	}*/
+}
+
+
+void CMcDemoDlg::OnBnClickedButtonDestroy()
+{
+	if (m_pChannel != NULL) {
+		MCL_DestroyChannel(m_pChannel->getName().c_str());
+		m_pChannel = NULL;
+		UpdateUISecsion1();
+		UpdateUISecsion2();
+		UpdateUISecsion3();
+	}
+}
+
+void CMcDemoDlg::AppendLog(CString strText)
+{
+	CEdit *pEdit = (CEdit *)GetDlgItem(IDC_EDIT_LOG);
+	if (pEdit == NULL) {
+		return;
+	}
+
+
+	// 超过指定行则删除最前面一行
+	int nLine = pEdit->GetLineCount();
+	if (nLine > 100) {
+		CString strOldText;
+		pEdit->GetWindowText(strOldText);
+
+		int nIndex = strOldText.Find(_T("\r\n"), 0);
+		for (int i = 0; i < 1111; i++) {
+			nIndex = strOldText.Find(_T("\r\n"), nIndex + 2);
+		}
+		pEdit->SetSel(0, nIndex);
+		pEdit->ReplaceSel(_T(""));
+	}
+
+
+	// 追加到最后
+	int length = pEdit->GetWindowTextLength();
+	pEdit->SetSel(length, length);
+	pEdit->ReplaceSel(strText);
+	pEdit->PostMessage(WM_VSCROLL, SB_BOTTOM, 0);
+}
+
+void CMcDemoDlg::AppendLog(char* szMessage, ...)
+{
+	if (!::IsWindow(GetSafeHwnd())) {
+		return;
+	}
+
+	CEdit *pEdit = (CEdit *)GetDlgItem(IDC_EDIT_LOG);
+	if (pEdit == NULL) {
+		return;
+	}
+
+	char szFormatMessage[MAX_MESSAGE_LENGTH];
+	va_list ap;
+	va_start(ap, szMessage);
+	_vsnprintf_s(szFormatMessage, MAX_MESSAGE_LENGTH, szMessage, ap);
+	va_end(ap);
+
+	// 超过指定行则删除最前面一行
+	int nLine = pEdit->GetLineCount();
+	if (nLine > 100) {
+		CString strOldText;
+		pEdit->GetWindowText(strOldText);
+
+		int nIndex = strOldText.Find(_T("\r\n"), 0);
+		for (int i = 0; i < 1111; i++) {
+			nIndex = strOldText.Find(_T("\r\n"), nIndex + 2);
+		}
+		pEdit->SetSel(0, nIndex);
+		pEdit->ReplaceSel(_T(""));
+	}
+
+
+	// 追加到最后
+	int length = pEdit->GetWindowTextLength();
+	pEdit->SetSel(length, length);
+	pEdit->ReplaceSel(szFormatMessage);
+	pEdit->PostMessage(WM_VSCROLL, SB_BOTTOM, 0);
+}
+
+void CMcDemoDlg::DataToHexString(const char* pData, const int size, CString& strOut)
+{
+	strOut.Empty();
+	for (int i = 0; i < size; i++) {
+		if (i < size - 1) {
+			strOut.AppendFormat(_T("%02X "), (BYTE)pData[i]);
+		}
+		else {
+			strOut.AppendFormat(_T("%02X"), (BYTE)pData[i]);
+		}
+	}
+}
+
+int CMcDemoDlg::HexStringToData(CString& strHex, char* pszBuffer, const int nBufferSize)
+{
+	int index = 0;
+	int nLength = strHex.GetLength();
+	CString strItem;
+	for (int i = 0; i < nLength; i++) {
+		if (strHex.GetAt(i) == ' ') {
+			if (!strItem.IsEmpty()) {
+				BYTE b = (BYTE)strtol(strItem, NULL, 16);
+				pszBuffer[index] = b;
+				index++;
+				if (index >= nBufferSize) {
+					break;
+				}
+				strItem.Empty();
+			}
+			continue;
+		}
+
+		strItem.AppendChar(strHex.GetAt(i));
+		if (strItem.GetLength() == 2) {
+			BYTE b = (BYTE)strtol(strItem, NULL, 16);
+			pszBuffer[index] = b;
+			index++;
+			if (index >= nBufferSize) {
+				break;
+			}
+			strItem.Empty();
+		}
+	}
+
+	return index;
+}
+
+void CMcDemoDlg::UpdateUISecsion1()
+{
+	if (!::IsWindow(GetSafeHwnd())) {
+		return;
+	}
+
+	GetDlgItem(IDC_BUTTON_CREATE)->EnableWindow(m_pChannel == NULL);
+	GetDlgItem(IDC_BUTTON_CLOSE)->EnableWindow(m_pChannel != NULL);
+	SetDlgItemText(IDC_BUTTON_CLOSE, (m_pChannel != NULL && m_pChannel->isConnected()) ? _T("Close") : _T("Open"));
+	GetDlgItem(IDC_BUTTON_DESTROY)->EnableWindow(m_pChannel != NULL);
+}
+
+void CMcDemoDlg::UpdateUISecsion2()
+{
+	if (!::IsWindow(GetSafeHwnd())) {
+		return;
+	}
+
+	BOOL bEnable = (m_pChannel != NULL && m_pChannel->isConnected());
+	GetDlgItem(IDC_RADIO1)->EnableWindow(bEnable);
+	GetDlgItem(IDC_RADIO2)->EnableWindow(bEnable);
+	GetDlgItem(IDC_EDIT_RAW)->EnableWindow(bEnable);
+	GetDlgItem(IDC_BUTTON_SEND)->EnableWindow(bEnable);
+	GetDlgItem(IDC_COMBO_CMD)->EnableWindow(bEnable);
+	GetDlgItem(IDC_COMBO_SUBCMD)->EnableWindow(bEnable);
+	GetDlgItem(IDC_COMBO_SOFTITEM)->EnableWindow(bEnable);
+	GetDlgItem(IDC_EDIT_HEAD_ADDR)->EnableWindow(bEnable);
+	GetDlgItem(IDC_EDIT_READ_COUNT)->EnableWindow(bEnable);
+	GetDlgItem(IDC_BUTTON_RAWDATA)->EnableWindow(bEnable);
+}
+
+void CMcDemoDlg::UpdateUISecsion3()
+{
+	if (!::IsWindow(GetSafeHwnd())) {
+		return;
+	}
+
+	GetDlgItem(IDC_COMBO_SOFTITEM2)->EnableWindow((m_pChannel != NULL && m_pChannel->isConnected()));
+	GetDlgItem(IDC_EDIT_HEAD_ADDR2)->EnableWindow((m_pChannel != NULL && m_pChannel->isConnected()));
+	GetDlgItem(IDC_BUTTON_READ_DWORD)->EnableWindow((m_pChannel != NULL && m_pChannel->isConnected()));
+	GetDlgItem(IDC_BUTTON_READ)->EnableWindow((m_pChannel != NULL && m_pChannel->isConnected()));
+	GetDlgItem(IDC_BUTTON_READ_BIT)->EnableWindow((m_pChannel != NULL && m_pChannel->isConnected()));
+	GetDlgItem(IDC_EDIT_WRITE_VALUE)->EnableWindow((m_pChannel != NULL && m_pChannel->isConnected()));
+	GetDlgItem(IDC_CHECK_WRITE_BIT_VALUE)->EnableWindow((m_pChannel != NULL && m_pChannel->isConnected()));
+	GetDlgItem(IDC_BUTTON_WRITE_DWORD)->EnableWindow((m_pChannel != NULL && m_pChannel->isConnected()));
+	GetDlgItem(IDC_BUTTON_WRITE)->EnableWindow((m_pChannel != NULL && m_pChannel->isConnected()));
+	GetDlgItem(IDC_BUTTON_WRITE_BIT)->EnableWindow((m_pChannel != NULL && m_pChannel->isConnected()));
+}
+
+void CMcDemoDlg::OnBnClickedButtonRawdata()
+{
+	/*
+	char szBuffer[] = {0x50, 0x00, 0x00, 0xff, 0xff, 0x03, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x01,
+	0x04, 0x00, 0x00, 0x64, 0x00, 0x00, 0xa8, 0x01, 0x00};
+
+
+	// 软元类型
+	static char szSoftItem[] = {0x90, 0xa8, 0x9c, 0x9d, 0xb0};
+	CComboBox* pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_SOFTITEM);
+	szBuffer[18] = szSoftItem[pComboBox->GetCurSel()];
+
+
+	// 首地址
+	int nHeadAddr = GetDlgItemInt(IDC_EDIT_HEAD_ADDR);
+	szBuffer[15] = nHeadAddr & 0xff;
+	szBuffer[16] = (nHeadAddr & 0xff00) >> 8;
+	szBuffer[17] = (nHeadAddr & 0xff0000) >> 16;
+
+
+	// 数量
+	int nReadCount = GetDlgItemInt(IDC_EDIT_READ_COUNT);
+	szBuffer[19] = nReadCount & 0xff;
+	szBuffer[20] = (nReadCount & 0xff00) >> 8;
+
+
+	// 命令
+	int nCmd = ((CComboBox*)GetDlgItem(IDC_COMBO_CMD))->GetCurSel();
+	if (nCmd == 0) {
+	// 成批读
+	szBuffer[11] = 0x01;
+	szBuffer[12] = 0x04;
+	}
+	else if (nCmd == 1) {
+	// 成批写
+	szBuffer[11] = 0x01;
+	szBuffer[12] = 0x14;
+	}
+	else if (nCmd == 2) {
+	// 随机读
+	szBuffer[11] = 0x03;
+	szBuffer[12] = 0x04;
+	}
+	else if (nCmd == 3) {
+	// 测试(随机写)
+	szBuffer[11] = 0x02;
+	szBuffer[12] = 0x14;
+	}
+	else if (nCmd == 4) {
+	// 监视登录数据
+	szBuffer[11] = 0x01;
+	szBuffer[12] = 0x08;
+	}
+	else if (nCmd == 5) {
+	// 监视
+	szBuffer[11] = 0x02;
+	szBuffer[12] = 0x08;
+	}
+
+
+	// 子命令
+	int nSubCmd = ((CComboBox*)GetDlgItem(IDC_COMBO_SUBCMD))->GetCurSel();
+	if (nSubCmd == 0) {
+	// 按字
+	szBuffer[13] = 0x00;
+	szBuffer[14] = 0x00;
+	}
+	else if (nSubCmd == 1) {
+	// 按位
+	szBuffer[13] = 0x00;
+	szBuffer[14] = 0x01;
+	}
+
+
+
+
+	CString strRawData;
+	DataToHexString(szBuffer, sizeof(szBuffer), strRawData);
+	SetDlgItemText(IDC_EDIT_RAW, strRawData);
+	*/
+
+
+	// 新方法
+	CComboBox* pComboBox = NULL;
+	CString strLbText;
+	pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_CMD);
+	pComboBox->GetLBText(pComboBox->GetCurSel(), strLbText);
+	std::string strCmd = (LPTSTR)(LPCTSTR)strLbText;
+	MC::CMD cmd;
+	MCL_GetCmd(strCmd, cmd);
+
+	pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_SUBCMD);
+	pComboBox->GetLBText(pComboBox->GetCurSel(), strLbText);
+	std::string strSubCmd = (LPTSTR)(LPCTSTR)strLbText;
+	MC::SUBCMD subCmd;
+	MCL_GetSubCmd(strSubCmd, subCmd);
+
+	pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_SOFTITEM);
+	pComboBox->GetLBText(pComboBox->GetCurSel(), strLbText);
+	std::string strSoftComponent = (LPTSTR)(LPCTSTR)strLbText;
+	MC::SOFT_COMPONENT softComponent;
+	MCL_GetSoftComponent(strSoftComponent, softComponent);
+
+	int nFirstAddr = GetDlgItemInt(IDC_EDIT_HEAD_ADDR);
+	int nOperateCount = GetDlgItemInt(IDC_EDIT_READ_COUNT);
+	char szRawData[1024];
+	char szAttach[4] = { 0x10, 0x11, 0x12, 0x13 };
+	int nDataSize = MCL_GetRawData(cmd, subCmd, softComponent, nFirstAddr, nOperateCount, NULL, 0, szRawData, sizeof(szRawData));
+
+	CString strRawData2;
+	DataToHexString(szRawData, nDataSize, strRawData2);
+	SetDlgItemText(IDC_EDIT_RAW, strRawData2);
+	// AfxMessageBox(strRawData2);
+}
+
+void CMcDemoDlg::OnBnClickedButtonRead()
+{
+	CComboBox* pComboBox;
+	CString strLbText;
+
+	pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_SOFTITEM2);
+	pComboBox->GetLBText(pComboBox->GetCurSel(), strLbText);
+	std::string strSoftComponent = (LPTSTR)(LPCTSTR)strLbText;
+	MC::SOFT_COMPONENT softComponent;
+	MCL_GetSoftComponent(strSoftComponent, softComponent);
+
+	int nAddr = GetDlgItemInt(IDC_EDIT_HEAD_ADDR2);
+
+	if (m_pChannel != NULL && m_pChannel->isConnected()) {
+		auto funOnRead = [&](IMcChannel* pChannel, int addr, DWORD value, int flag) -> void {
+			AppendLog(">> funOnRead:[%d]\r\n", value);
+			CString strText;
+			strText.Format(_T("Read Word(%d)"), value);
+			SetDlgItemText(IDC_BUTTON_READ, strText);
+		};
+		m_pChannel->readWord(softComponent, nAddr, funOnRead);
+	}
+}
+
+
+void CMcDemoDlg::OnBnClickedButtonReadBit()
+{
+	CComboBox* pComboBox;
+	CString strLbText;
+
+	pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_SOFTITEM2);
+	pComboBox->GetLBText(pComboBox->GetCurSel(), strLbText);
+	std::string strSoftComponent = (LPTSTR)(LPCTSTR)strLbText;
+	MC::SOFT_COMPONENT softComponent;
+	MCL_GetSoftComponent(strSoftComponent, softComponent);
+
+	int nAddr = GetDlgItemInt(IDC_EDIT_HEAD_ADDR2);
+
+	if (m_pChannel != NULL && m_pChannel->isConnected()) {
+		auto funOnRead = [&](IMcChannel* pChannel, int addr, DWORD value, int flag) -> void {
+			AppendLog(">> funOnRead:[%s]\r\n", value != 0 ? "ON" : "OFF");
+			CString strText;
+			strText.Format(_T("Read Bit(%s)"), value != 0 ? "ON" : "OFF");
+			SetDlgItemText(IDC_BUTTON_READ_BIT, strText);
+			TRACE("MC Read Bit(%s)\n", value != 0 ? "ON" : "OFF");
+		};
+		m_pChannel->readBit(softComponent, nAddr, funOnRead);
+	}
+}
+
+void CMcDemoDlg::OnBnClickedButtonWrite()
+{
+	CComboBox* pComboBox;
+	CString strLbText;
+
+	pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_SOFTITEM2);
+	pComboBox->GetLBText(pComboBox->GetCurSel(), strLbText);
+	std::string strSoftComponent = (LPTSTR)(LPCTSTR)strLbText;
+	MC::SOFT_COMPONENT softComponent;
+	MCL_GetSoftComponent(strSoftComponent, softComponent);
+
+	int nAddr = GetDlgItemInt(IDC_EDIT_HEAD_ADDR2);
+	int nValue = GetDlgItemInt(IDC_EDIT_WRITE_VALUE);
+
+	if (m_pChannel != NULL && m_pChannel->isConnected()) {
+		auto funOnWrite = [&](IMcChannel* pChannel, int addr, DWORD value, int flag) -> void {
+			AppendLog(">> funOnWrite:[%d]\r\n", value);
+		};
+		m_pChannel->writeWord(softComponent, nAddr, nValue, funOnWrite);
+	}
+}
+
+void CMcDemoDlg::OnBnClickedButtonReadDword()
+{
+	CComboBox* pComboBox;
+	CString strLbText;
+
+	pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_SOFTITEM2);
+	pComboBox->GetLBText(pComboBox->GetCurSel(), strLbText);
+	std::string strSoftComponent = (LPTSTR)(LPCTSTR)strLbText;
+	MC::SOFT_COMPONENT softComponent;
+	MCL_GetSoftComponent(strSoftComponent, softComponent);
+
+	int nAddr = GetDlgItemInt(IDC_EDIT_HEAD_ADDR2);
+
+	if (m_pChannel != NULL && m_pChannel->isConnected()) {
+		auto funOnRead = [&](IMcChannel* pChannel, int addr, DWORD value, int flag) -> void {
+			AppendLog(">> funOnRead:[%d]\r\n", value);
+			CString strText;
+			strText.Format(_T("Read DWORD(%d)"), value);
+			SetDlgItemText(IDC_BUTTON_READ_DWORD, strText);
+		};
+		m_pChannel->readDWord(softComponent, nAddr, funOnRead);
+	}
+	
+
+	// SetTimer(1, 500, NULL);
+}
+
+void CMcDemoDlg::OnBnClickedButtonWriteDword()
+{
+	CComboBox* pComboBox;
+	CString strLbText;
+
+	pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_SOFTITEM2);
+	pComboBox->GetLBText(pComboBox->GetCurSel(), strLbText);
+	std::string strSoftComponent = (LPTSTR)(LPCTSTR)strLbText;
+	MC::SOFT_COMPONENT softComponent;
+	MCL_GetSoftComponent(strSoftComponent, softComponent);
+
+	int nAddr = GetDlgItemInt(IDC_EDIT_HEAD_ADDR2);
+	int nValue = GetDlgItemInt(IDC_EDIT_WRITE_VALUE);
+
+	if (m_pChannel != NULL && m_pChannel->isConnected()) {
+		auto funOnWrite = [&](IMcChannel* pChannel, int addr, DWORD value, int flag) -> void {
+			AppendLog(">> funOnWrite:[%d]\r\n", value);
+		};
+		m_pChannel->writeDWord(softComponent, nAddr, nValue, funOnWrite);
+	}
+}
+
+void CMcDemoDlg::OnBnClickedButtonWriteBit()
+{
+	CComboBox* pComboBox;
+	CString strLbText;
+
+	pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_SOFTITEM2);
+	pComboBox->GetLBText(pComboBox->GetCurSel(), strLbText);
+	std::string strSoftComponent = (LPTSTR)(LPCTSTR)strLbText;
+	MC::SOFT_COMPONENT softComponent;
+	MCL_GetSoftComponent(strSoftComponent, softComponent);
+
+	int nAddr = GetDlgItemInt(IDC_EDIT_HEAD_ADDR2);
+	CButton* pButton = (CButton*)GetDlgItem(IDC_CHECK_WRITE_BIT_VALUE);
+	BOOL bValue = pButton->GetCheck();;
+
+	if (m_pChannel != NULL && m_pChannel->isConnected()) {
+		auto funOnWrite = [&](IMcChannel* pChannel, int addr, DWORD value, int flag) -> void {
+			AppendLog(">> funOnWrite:[%s]\r\n", value != 0 ? "ON" : "OFF");
+		};
+		m_pChannel->writeBit(softComponent, nAddr, bValue, funOnWrite);
+	}
+}
+
+void CMcDemoDlg::OnBnClickedCheckWriteBitValue()
+{
+	CButton* pButton = (CButton*)GetDlgItem(IDC_CHECK_WRITE_BIT_VALUE);
+	pButton->SetWindowText(pButton->GetCheck() ? "ON" : "OFF");
+}
+
+
+
+void CMcDemoDlg::OnTimer(UINT_PTR nIDEvent)
+{
+	// TODO: 在此添加消息处理程序代码和/或调用默认值
+	if (1 == nIDEvent) {
+		auto funOnReadData = [&](IMcChannel* pChannel, int addr, char *pData, unsigned int nDataSize, int flag) -> void {
+			CString s = "Packer funOnReadData [";
+			for (int i = 0; i < nDataSize; i++) {
+				s.AppendFormat(" %x", (BYTE)pData[i]);
+			}
+			TRACE(s);
+		};
+		TRACE("Packer readData");
+		m_pChannel->readData(MC::SOFT_COMPONENT::B, 0x2000, 5,
+			funOnReadData);
+	}
+
+	CDialogEx::OnTimer(nIDEvent);
+}
diff --git a/SourceCode/Bond/McLibrarySDK/McDemo/McDemoDlg.h b/SourceCode/Bond/McLibrarySDK/McDemo/McDemoDlg.h
new file mode 100644
index 0000000..0c49d57
--- /dev/null
+++ b/SourceCode/Bond/McLibrarySDK/McDemo/McDemoDlg.h
@@ -0,0 +1,57 @@
+
+// McDemoDlg.h : 头文件
+//
+
+#pragma once
+
+
+// CMcDemoDlg 对话框
+class CMcDemoDlg : public CDialogEx
+{
+// 构造
+public:
+	CMcDemoDlg(CWnd* pParent = NULL);	// 标准构造函数
+	void AppendLog(CString strText);
+	void AppendLog(char* szMessage, ...);
+	void DataToHexString(const char* pData, const int size, CString& strOut);
+	int HexStringToData(CString& strHex, char* pszBuffer, const int nBufferSize);
+	void UpdateUISecsion1();
+	void UpdateUISecsion2();
+	void UpdateUISecsion3();
+
+// 对话框数据
+#ifdef AFX_DESIGN_TIME
+	enum { IDD = IDD_MCDEMO_DIALOG };
+#endif
+
+	protected:
+	virtual void DoDataExchange(CDataExchange* pDX);	// DDX/DDV 支持
+
+
+// 实现
+protected:
+	HICON m_hIcon;
+	McChannelListener m_mcChannellistener;
+	IMcChannel* m_pChannel;
+
+	// 生成的消息映射函数
+	virtual BOOL OnInitDialog();
+	afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
+	afx_msg void OnPaint();
+	afx_msg HCURSOR OnQueryDragIcon();
+	DECLARE_MESSAGE_MAP()
+public:
+	afx_msg void OnBnClickedButtonCreate();
+	afx_msg void OnBnClickedButtonSend();
+	afx_msg void OnBnClickedButtonClose();
+	afx_msg void OnBnClickedButtonDestroy();
+	afx_msg void OnBnClickedButtonRead();
+	afx_msg void OnBnClickedButtonRawdata();
+	afx_msg void OnBnClickedButtonWrite();
+	afx_msg void OnBnClickedButtonReadBit();
+	afx_msg void OnBnClickedCheckWriteBitValue();
+	afx_msg void OnBnClickedButtonWriteBit();
+	afx_msg void OnBnClickedButtonReadDword();
+	afx_msg void OnBnClickedButtonWriteDword();
+	afx_msg void OnTimer(UINT_PTR nIDEvent);
+};
diff --git a/SourceCode/Bond/McLibrarySDK/McDemo/mcdemo.cpp b/SourceCode/Bond/McLibrarySDK/McDemo/mcdemo.cpp
new file mode 100644
index 0000000..6812cce
--- /dev/null
+++ b/SourceCode/Bond/McLibrarySDK/McDemo/mcdemo.cpp
@@ -0,0 +1,121 @@
+
+// McDemo.cpp : 定义应用程序的类行为。
+//
+
+#include "stdafx.h"
+#include "McDemo.h"
+#include "McDemoDlg.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#endif
+
+
+// CMcDemoApp
+
+BEGIN_MESSAGE_MAP(CMcDemoApp, CWinApp)
+	ON_COMMAND(ID_HELP, &CWinApp::OnHelp)
+END_MESSAGE_MAP()
+
+
+// CMcDemoApp 构造
+
+CMcDemoApp::CMcDemoApp()
+{
+	// 支持重新启动管理器
+	m_dwRestartManagerSupportFlags = AFX_RESTART_MANAGER_SUPPORT_RESTART;
+
+	// TODO: 在此处添加构造代码,
+	// 将所有重要的初始化放置在 InitInstance 中
+}
+
+
+// 唯一的一个 CMcDemoApp 对象
+
+CMcDemoApp theApp;
+
+
+// CMcDemoApp 初始化
+
+BOOL CMcDemoApp::InitInstance()
+{
+	// 如果一个运行在 Windows XP 上的应用程序清单指定要
+	// 使用 ComCtl32.dll 版本 6 或更高版本来启用可视化方式,
+	//则需要 InitCommonControlsEx()。  否则,将无法创建窗口。
+	INITCOMMONCONTROLSEX InitCtrls;
+	InitCtrls.dwSize = sizeof(InitCtrls);
+	// 将它设置为包括所有要在应用程序中使用的
+	// 公共控件类。
+	InitCtrls.dwICC = ICC_WIN95_CLASSES;
+	InitCommonControlsEx(&InitCtrls);
+
+	CWinApp::InitInstance();
+
+
+	AfxEnableControlContainer();
+
+	// 创建 shell 管理器,以防对话框包含
+	// 任何 shell 树视图控件或 shell 列表视图控件。
+	CShellManager *pShellManager = new CShellManager;
+
+	// 激活“Windows Native”视觉管理器,以便在 MFC 控件中启用主题
+	CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerWindows));
+
+	// 标准初始化
+	// 如果未使用这些功能并希望减小
+	// 最终可执行文件的大小,则应移除下列
+	// 不需要的特定初始化例程
+	// 更改用于存储设置的注册表项
+	// TODO: 应适当修改该字符串,
+	// 例如修改为公司或组织名
+	SetRegistryKey(_T("应用程序向导生成的本地应用程序"));
+
+
+	// 初始化
+	MCL_Initialize();
+
+
+	CMcDemoDlg dlg;
+	m_pMainWnd = &dlg;
+	INT_PTR nResponse = dlg.DoModal();
+	if (nResponse == IDOK)
+	{
+		// TODO: 在此放置处理何时用
+		//  “确定”来关闭对话框的代码
+	}
+	else if (nResponse == IDCANCEL)
+	{
+		// TODO: 在此放置处理何时用
+		//  “取消”来关闭对话框的代码
+	}
+	else if (nResponse == -1)
+	{
+		TRACE(traceAppMsg, 0, "警告: 对话框创建失败,应用程序将意外终止。\n");
+		TRACE(traceAppMsg, 0, "警告: 如果您在对话框上使用 MFC 控件,则无法 #define _AFX_NO_MFC_CONTROLS_IN_DIALOGS。\n");
+	}
+
+	// 删除上面创建的 shell 管理器。
+	if (pShellManager != NULL)
+	{
+		delete pShellManager;
+	}
+
+#ifndef _AFXDLL
+	ControlBarCleanUp();
+#endif
+
+	// 由于对话框已关闭,所以将返回 FALSE 以便退出应用程序,
+	//  而不是启动应用程序的消息泵。
+	return FALSE;
+}
+
+
+
+int CMcDemoApp::ExitInstance()
+{
+	// TODO: 在此添加专用代码和/或调用基类
+	MCL_Term();
+
+
+	return CWinApp::ExitInstance();
+}
diff --git a/SourceCode/Bond/McLibrarySDK/McDemo/mcdemo.vcxproj b/SourceCode/Bond/McLibrarySDK/McDemo/mcdemo.vcxproj
new file mode 100644
index 0000000..e7a2a7b
--- /dev/null
+++ b/SourceCode/Bond/McLibrarySDK/McDemo/mcdemo.vcxproj
@@ -0,0 +1,226 @@
+锘�<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{09A3010B-32B2-45EF-AAE1-4311997C99CD}</ProjectGuid>
+    <RootNamespace>McDemo</RootNamespace>
+    <WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
+    <Keyword>MFCProj</Keyword>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>v140</PlatformToolset>
+    <CharacterSet>Unicode</CharacterSet>
+    <UseOfMfc>Dynamic</UseOfMfc>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>v140</PlatformToolset>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+    <UseOfMfc>Dynamic</UseOfMfc>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>v140</PlatformToolset>
+    <CharacterSet>MultiByte</CharacterSet>
+    <UseOfMfc>Dynamic</UseOfMfc>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>v140</PlatformToolset>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>MultiByte</CharacterSet>
+    <UseOfMfc>Dynamic</UseOfMfc>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="Shared">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <LinkIncremental>true</LinkIncremental>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <LinkIncremental>true</LinkIncremental>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <LinkIncremental>false</LinkIncremental>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <LinkIncremental>false</LinkIncremental>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>Use</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_WINDOWS;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+    </Link>
+    <Midl>
+      <MkTypLibCompatible>false</MkTypLibCompatible>
+      <ValidateAllParameters>true</ValidateAllParameters>
+      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+    </Midl>
+    <ResourceCompile>
+      <Culture>0x0804</Culture>
+      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+    </ResourceCompile>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <ClCompile>
+      <PrecompiledHeader>Use</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>_WINDOWS;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+    </Link>
+    <Midl>
+      <MkTypLibCompatible>false</MkTypLibCompatible>
+      <ValidateAllParameters>true</ValidateAllParameters>
+      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+    </Midl>
+    <ResourceCompile>
+      <Culture>0x0804</Culture>
+      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+    </ResourceCompile>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <PrecompiledHeader>Use</PrecompiledHeader>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <PreprocessorDefinitions>WIN32;_WINDOWS;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+    <Midl>
+      <MkTypLibCompatible>false</MkTypLibCompatible>
+      <ValidateAllParameters>true</ValidateAllParameters>
+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+    </Midl>
+    <ResourceCompile>
+      <Culture>0x0804</Culture>
+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+    </ResourceCompile>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <PrecompiledHeader>Use</PrecompiledHeader>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <PreprocessorDefinitions>_WINDOWS;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+    <Midl>
+      <MkTypLibCompatible>false</MkTypLibCompatible>
+      <ValidateAllParameters>true</ValidateAllParameters>
+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+    </Midl>
+    <ResourceCompile>
+      <Culture>0x0804</Culture>
+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+    </ResourceCompile>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <Text Include="ReadMe.txt" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="..\McLibrarySDK\include\IMcChannel.h" />
+    <ClInclude Include="..\McLibrarySDK\include\McLib.h" />
+    <ClInclude Include="McDemo.h" />
+    <ClInclude Include="McDemoDlg.h" />
+    <ClInclude Include="Resource.h" />
+    <ClInclude Include="stdafx.h" />
+    <ClInclude Include="targetver.h" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="McDemo.cpp" />
+    <ClCompile Include="McDemoDlg.cpp" />
+    <ClCompile Include="stdafx.cpp">
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ResourceCompile Include="McDemo.rc" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="res\McDemo.rc2" />
+  </ItemGroup>
+  <ItemGroup>
+    <Image Include="res\McDemo.ico" />
+  </ItemGroup>
+  <ItemGroup>
+    <Manifest Include="res\application.exe.manifest" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+  <ProjectExtensions>
+    <VisualStudio>
+      <UserProperties RESOURCE_FILE="McDemo.rc" />
+    </VisualStudio>
+  </ProjectExtensions>
+</Project>
\ No newline at end of file
diff --git a/SourceCode/Bond/McLibrarySDK/McDemo/readme.txt b/SourceCode/Bond/McLibrarySDK/McDemo/readme.txt
new file mode 100644
index 0000000..9ca4860
--- /dev/null
+++ b/SourceCode/Bond/McLibrarySDK/McDemo/readme.txt
@@ -0,0 +1,67 @@
+锘�================================================================================
+    MICROSOFT 鍩虹绫诲簱 : McDemo 椤圭洰姒傝堪
+===============================================================================
+
+搴旂敤绋嬪簭鍚戝宸蹭负鎮ㄥ垱寤轰簡姝� McDemo 搴旂敤绋嬪簭銆傛搴旂敤绋嬪簭涓嶄粎婕旂ず Microsoft 鍩虹绫荤殑鍩烘湰浣跨敤鏂规硶锛岃繕鍙綔涓烘偍缂栧啓搴旂敤绋嬪簭鐨勮捣鐐广��
+
+鏈枃浠舵瑕佷粙缁嶇粍鎴� McDemo 搴旂敤绋嬪簭鐨勬瘡涓枃浠剁殑鍐呭銆�
+
+McDemo.vcxproj
+    杩欐槸浣跨敤搴旂敤绋嬪簭鍚戝鐢熸垚鐨� VC++ 椤圭洰鐨勪富椤圭洰鏂囦欢锛屽叾涓寘鍚敓鎴愯鏂囦欢鐨� Visual C++ 鐨勭増鏈俊鎭紝浠ュ強鏈夊叧浣跨敤搴旂敤绋嬪簭鍚戝閫夋嫨鐨勫钩鍙般�侀厤缃拰椤圭洰鍔熻兘鐨勪俊鎭��
+
+McDemo.vcxproj.filters
+    杩欐槸浣跨敤鈥滃簲鐢ㄧ▼搴忓悜瀵尖�濈敓鎴愮殑 VC++ 椤圭洰绛涢�夊櫒鏂囦欢銆傚畠鍖呭惈鏈夊叧椤圭洰鏂囦欢涓庣瓫閫夊櫒涔嬮棿鐨勫叧鑱斾俊鎭�傚湪 IDE 涓紝閫氳繃杩欑鍏宠仈锛屽湪鐗瑰畾鑺傜偣涓嬩互鍒嗙粍褰㈠紡鏄剧ず鍏锋湁鐩镐技鎵╁睍鍚嶇殑鏂囦欢銆備緥濡傦紝鈥�.cpp鈥濇枃浠朵笌鈥滄簮鏂囦欢鈥濈瓫閫夊櫒鍏宠仈銆�
+
+McDemo.h
+    杩欐槸搴旂敤绋嬪簭鐨勪富澶存枃浠躲��
+    鍏朵腑鍖呮嫭鍏朵粬椤圭洰鐗瑰畾鐨勬爣澶达紙鍖呮嫭 Resource.h锛夛紝骞跺0鏄� CMcDemoApp 搴旂敤绋嬪簭绫汇��
+
+McDemo.cpp
+    杩欐槸鍖呭惈搴旂敤绋嬪簭绫� CMcDemoApp 鐨勪富搴旂敤绋嬪簭婧愭枃浠躲��
+
+McDemo.rc
+    杩欐槸绋嬪簭浣跨敤鐨勬墍鏈� Microsoft Windows 璧勬簮鐨勫垪琛ㄣ�傚畠鍖呮嫭 RES 瀛愮洰褰曚腑瀛樺偍鐨勫浘鏍囥�佷綅鍥惧拰鍏夋爣銆傛鏂囦欢鍙互鐩存帴鍦� Microsoft Visual C++ 涓繘琛岀紪杈戙�傞」鐩祫婧愬寘鍚湪 2052 涓��
+
+res\McDemo.ico
+    杩欐槸鐢ㄤ綔搴旂敤绋嬪簭鍥炬爣鐨勫浘鏍囨枃浠躲�傛鍥炬爣鍖呮嫭鍦ㄤ富璧勬簮鏂囦欢 McDemo.rc 涓��
+
+res\McDemo.rc2
+    姝ゆ枃浠跺寘鍚笉鍦� Microsoft Visual C++ 涓繘琛岀紪杈戠殑璧勬簮銆傛偍搴旇灏嗕笉鍙敱璧勬簮缂栬緫鍣ㄧ紪杈戠殑鎵�鏈夎祫婧愭斁鍦ㄦ鏂囦欢涓��
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+搴旂敤绋嬪簭鍚戝鍒涘缓涓�涓璇濇绫伙細
+
+McDemoDlg.h銆丮cDemoDlg.cpp - 瀵硅瘽妗�
+    杩欎簺鏂囦欢鍖呭惈 CMcDemoDlg 绫汇�傛绫诲畾涔夊簲鐢ㄧ▼搴忕殑涓诲璇濇鐨勮涓恒�傚璇濇妯℃澘鍖呭惈鍦� McDemo.rc 涓紝璇ユ枃浠跺彲浠ュ湪 Microsoft Visual C++ 涓紪杈戙��
+
+/////////////////////////////////////////////////////////////////////////////
+
+鍏朵粬鍔熻兘锛�
+
+ActiveX 鎺т欢
+    璇ュ簲鐢ㄧ▼搴忓寘鍚浣跨敤 ActiveX 鎺т欢鐨勬敮鎸併��
+
+/////////////////////////////////////////////////////////////////////////////
+
+鍏朵粬鏍囧噯鏂囦欢:
+
+StdAfx.h, StdAfx.cpp
+    杩欎簺鏂囦欢鐢ㄤ簬鐢熸垚鍚嶄负 McDemo.pch 鐨勯缂栬瘧澶� (PCH) 鏂囦欢鍜屽悕涓� StdAfx.obj 鐨勯缂栬瘧绫诲瀷鏂囦欢銆�
+
+Resource.h
+    杩欐槸鏍囧噯澶存枃浠讹紝鍙敤浜庡畾涔夋柊鐨勮祫婧� ID銆侻icrosoft Visual C++ 灏嗚鍙栧苟鏇存柊姝ゆ枃浠躲��
+
+McDemo.manifest
+	Windows XP 浣跨敤搴旂敤绋嬪簭娓呭崟鏂囦欢鏉ユ弿杩扮壒瀹氱増鏈殑骞惰绋嬪簭闆嗙殑搴旂敤绋嬪簭渚濊禆椤广�傚姞杞界▼搴忎娇鐢ㄨ繖浜涗俊鎭潵浠庣▼搴忛泦缂撳瓨涓姞杞界浉搴旂殑绋嬪簭闆嗭紝骞朵繚鎶ゅ叾涓嶈搴旂敤绋嬪簭璁块棶銆傚簲鐢ㄧ▼搴忔竻鍗曞彲鑳戒細鍖呭惈鍦ㄥ唴锛屼互浣滀负涓庡簲鐢ㄧ▼搴忓彲鎵ц鏂囦欢瀹夎鍦ㄥ悓涓�鏂囦欢澶逛腑鐨勫閮� .manifest 鏂囦欢杩涜閲嶆柊鍒嗗彂锛屽畠杩樺彲鑳戒互璧勬簮鐨勫舰寮忓寘鍚湪鍙墽琛屾枃浠朵腑銆�
+/////////////////////////////////////////////////////////////////////////////
+
+鍏朵粬娉ㄩ噴:
+
+搴旂敤绋嬪簭鍚戝浣跨敤鈥淭ODO:鈥濇潵鎸囩ず搴旀坊鍔犳垨鑷畾涔夌殑婧愪唬鐮侀儴鍒嗐��
+
+濡傛灉搴旂敤绋嬪簭浣跨敤鍏变韩 DLL 涓殑 MFC锛屾偍灏嗛渶瑕侀噸鏂板垎鍙� MFC DLL銆傚鏋滃簲鐢ㄧ▼搴忔墍浣跨敤鐨勮瑷�涓庢搷浣滅郴缁熺殑鍖哄煙璁剧疆涓嶅悓锛屽垯杩橀渶瑕侀噸鏂板垎鍙戠浉搴旂殑鏈湴鍖栬祫婧� mfc110XXX.DLL銆�
+鏈夊叧涓婅堪璇濋鐨勬洿澶氫俊鎭紝璇峰弬瑙� MSDN 鏂囨。涓湁鍏抽噸鏂板垎鍙� Visual C++ 搴旂敤绋嬪簭鐨勯儴鍒嗐��
+
+/////////////////////////////////////////////////////////////////////////////
diff --git a/SourceCode/Bond/McLibrarySDK/McDemo/res/McDemo.ico b/SourceCode/Bond/McLibrarySDK/McDemo/res/McDemo.ico
new file mode 100644
index 0000000..d56fbcd
--- /dev/null
+++ b/SourceCode/Bond/McLibrarySDK/McDemo/res/McDemo.ico
Binary files differ
diff --git a/SourceCode/Bond/McLibrarySDK/McDemo/res/McDemo.rc2 b/SourceCode/Bond/McLibrarySDK/McDemo/res/McDemo.rc2
new file mode 100644
index 0000000..3581d57
--- /dev/null
+++ b/SourceCode/Bond/McLibrarySDK/McDemo/res/McDemo.rc2
Binary files differ
diff --git a/SourceCode/Bond/McLibrarySDK/McDemo/res/application.exe.manifest b/SourceCode/Bond/McLibrarySDK/McDemo/res/application.exe.manifest
new file mode 100644
index 0000000..b96c40d
--- /dev/null
+++ b/SourceCode/Bond/McLibrarySDK/McDemo/res/application.exe.manifest
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
+    <assemblyIdentity
+         name="XP style manifest"
+         processorArchitecture="amd64"
+         version="1.0.0.0"
+         type="win32"/>
+    <dependency>
+        <dependentAssembly>
+            <assemblyIdentity
+                type="win32"
+                name="Microsoft.Windows.Common-Controls"
+                version="6.0.0.0"
+                processorArchitecture="amd64"
+                publicKeyToken="6595b64144ccf1df"
+                language="*"
+            />
+        </dependentAssembly>
+    </dependency>
+</assembly>
\ No newline at end of file
diff --git a/SourceCode/Bond/McLibrarySDK/McDemo/resource.h b/SourceCode/Bond/McLibrarySDK/McDemo/resource.h
new file mode 100644
index 0000000..5f63b6d
--- /dev/null
+++ b/SourceCode/Bond/McLibrarySDK/McDemo/resource.h
Binary files differ
diff --git a/SourceCode/Bond/McLibrarySDK/McDemo/stdafx.cpp b/SourceCode/Bond/McLibrarySDK/McDemo/stdafx.cpp
new file mode 100644
index 0000000..f1e5cec
--- /dev/null
+++ b/SourceCode/Bond/McLibrarySDK/McDemo/stdafx.cpp
@@ -0,0 +1,8 @@
+
+// stdafx.cpp : 只包括标准包含文件的源文件
+// McDemo.pch 将作为预编译头
+// stdafx.obj 将包含预编译类型信息
+
+#include "stdafx.h"
+
+
diff --git a/SourceCode/Bond/McLibrarySDK/McDemo/stdafx.h b/SourceCode/Bond/McLibrarySDK/McDemo/stdafx.h
new file mode 100644
index 0000000..7d8a96a
--- /dev/null
+++ b/SourceCode/Bond/McLibrarySDK/McDemo/stdafx.h
@@ -0,0 +1,54 @@
+
+// stdafx.h : 标准系统包含文件的包含文件,
+// 或是经常使用但不常更改的
+// 特定于项目的包含文件
+
+#pragma once
+
+#ifndef VC_EXTRALEAN
+#define VC_EXTRALEAN            // 从 Windows 头中排除极少使用的资料
+#endif
+
+#include "targetver.h"
+
+#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS      // 某些 CString 构造函数将是显式的
+
+// 关闭 MFC 对某些常见但经常可放心忽略的警告消息的隐藏
+#define _AFX_ALL_WARNINGS
+
+#include <afxwin.h>         // MFC 核心组件和标准组件
+#include <afxext.h>         // MFC 扩展
+
+
+#include <afxdisp.h>        // MFC 自动化类
+
+
+
+#ifndef _AFX_NO_OLE_SUPPORT
+#include <afxdtctl.h>           // MFC 对 Internet Explorer 4 公共控件的支持
+#endif
+#ifndef _AFX_NO_AFXCMN_SUPPORT
+#include <afxcmn.h>             // MFC 对 Windows 公共控件的支持
+#endif // _AFX_NO_AFXCMN_SUPPORT
+
+#include <afxcontrolbars.h>     // 功能区和控件条的 MFC 支持
+
+
+
+
+
+
+
+
+
+#ifdef _UNICODE
+#if defined _M_IX86
+#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"")
+#elif defined _M_X64
+#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"")
+#else
+#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
+#endif
+#endif
+
+
diff --git a/SourceCode/Bond/McLibrarySDK/McDemo/targetver.h b/SourceCode/Bond/McLibrarySDK/McDemo/targetver.h
new file mode 100644
index 0000000..416cebf
--- /dev/null
+++ b/SourceCode/Bond/McLibrarySDK/McDemo/targetver.h
@@ -0,0 +1,8 @@
+#pragma once
+
+// 包括 SDKDDKVer.h 将定义可用的最高版本的 Windows 平台。
+
+// 如果要为以前的 Windows 平台生成应用程序,请包括 WinSDKVer.h,并将
+// 将 _WIN32_WINNT 宏设置为要支持的平台,然后再包括 SDKDDKVer.h。
+
+#include <SDKDDKVer.h>
diff --git a/SourceCode/Bond/McLibrarySDK/Readme.docx b/SourceCode/Bond/McLibrarySDK/Readme.docx
new file mode 100644
index 0000000..5674d3a
--- /dev/null
+++ b/SourceCode/Bond/McLibrarySDK/Readme.docx
Binary files differ
diff --git a/SourceCode/Bond/McLibrarySDK/Readme.pdf b/SourceCode/Bond/McLibrarySDK/Readme.pdf
new file mode 100644
index 0000000..45bf87c
--- /dev/null
+++ b/SourceCode/Bond/McLibrarySDK/Readme.pdf
Binary files differ
diff --git a/SourceCode/Bond/McLibrarySDK/include/IMcChannel.h b/SourceCode/Bond/McLibrarySDK/include/IMcChannel.h
new file mode 100644
index 0000000..b920320
--- /dev/null
+++ b/SourceCode/Bond/McLibrarySDK/include/IMcChannel.h
@@ -0,0 +1,131 @@
+#pragma once
+#include <string>
+#include <functional>
+
+
+#define TIMEOUT		-99
+
+class IMcChannel;
+typedef std::function<void(IMcChannel*)> ONCLOSE;
+typedef std::function<void(IMcChannel*)> ONCLOSING;
+typedef std::function<void(IMcChannel*, int nErrorCode)> ONCONNECTED;
+typedef std::function<void(IMcChannel*, char *pData, unsigned int nDataSize, int nDecodeRet)> ONREADRAWDATA;
+typedef std::function<void(IMcChannel*)> ONWRITERAWDATA;
+typedef std::function<void(IMcChannel*, int addr, DWORD value, int flag)> ONREAD;
+typedef std::function<void(IMcChannel*, int addr, char *pData, unsigned int nDataSize, int flag)> ONREADDATA;
+typedef std::function<void(IMcChannel*, int addr, DWORD value, int flag)> ONWRITE;
+
+typedef struct _McChannelListener
+{
+	ONCLOSE				funOnClose;
+	ONCLOSING			funOnClosing;
+	ONCONNECTED			funOnConnected;
+	ONREADRAWDATA		funOnRead;
+	ONWRITERAWDATA		funOnWrite;
+} McChannelListener;
+
+namespace MC {
+#define LERROR		4
+#define LWARN		3
+#define LINFO		2
+#define LDEBUG		1
+
+	/** @brief 命令*/
+	typedef enum CMD
+	{
+		/** @brief 成批读 */
+		BATCH_READ = 0x0401,
+
+		/** @brief 成批写 */
+		BATCH_WRITE = 0x1401,
+
+		/** @brief 随机读 */
+		RANDOM_READ = 0x0403,
+
+		/** @brief 测试(随机写) */
+		TEST_RANDOM_WRITE = 0x0402,
+
+		/** @brief 监视注册数据 */
+		MONITOR_REGISTER_DATA = 0x0801,
+
+		/** @brief 监视 */
+		MONITOR = 0x0802,
+
+	} CMD;
+
+
+	/** @brief 子命令*/
+	typedef enum SUBCMD
+	{
+		/** @brief 按字 */
+		SC_WORD = 0x0000,
+
+		/** @brief 按位 */
+		SC_BIT = 0x0001,
+
+	} SUBCMD;
+
+
+	/** @brief 软元件类型*/
+	typedef enum SOFT_COMPONENT
+	{
+		/** @brief 内部继电器(M*) */
+		M = 0x90,
+
+		/** @brief 数据寄存器(D*) */
+		D = 0xa8,
+
+		/** @brief 链接寄存器(W*) */
+		W = 0xb4,
+
+		/** @brief 输入(X*) */
+		X = 0x9c,
+
+		/** @brief 输出(Y*) */
+		Y = 0x9d,
+
+		/** @brief 锁存继电器(L*) */
+		L = 0x92,
+
+		/** @brief 步进继电器(S*) */
+		S = 0x98,
+
+		/** @brief 链接继电器(B*) */
+		B = 0xA0,
+
+		/** @brief 报警器(F*) */
+		F = 0x93,
+
+		/** @brief 文件寄存器(ZR*) */
+		ZR = 0xB0,
+
+	} SOFT_COMPONENT;
+}
+
+class IMcChannel
+{
+public:
+	virtual void setChannelListener(McChannelListener *pListener) = 0;
+	virtual void setActionInterval(int millisecond) = 0;
+	virtual std::string &getName() = 0;
+	virtual std::string &getIp() = 0;
+	virtual unsigned int getServerPort() = 0;
+	virtual unsigned int getLocalPort() = 0;
+	virtual bool isConnected() = 0;
+	virtual int connect() = 0;
+	virtual int close() = 0;
+	virtual int sendRawData(char *pData, int nDataSize) = 0;
+	virtual int readData(MC::SOFT_COMPONENT softComponent, unsigned int addr, unsigned int nReadLen, ONREADDATA funOnReadData) = 0;
+	virtual int readData2(MC::SOFT_COMPONENT softComponent, unsigned int addr, unsigned int nReadLen, int executeTime, ONREADDATA funOnReadData) = 0;
+	virtual int readDWord(MC::SOFT_COMPONENT softComponent, unsigned int addr, ONREAD funOnRead) = 0;
+	virtual int readWord(MC::SOFT_COMPONENT softComponent, unsigned int addr, ONREAD funOnRead) = 0;
+	virtual int readWordIfIdle(MC::SOFT_COMPONENT softComponent, unsigned int addr, ONREAD funOnRead) = 0;
+	virtual int readBit(MC::SOFT_COMPONENT softComponent, unsigned int addr, ONREAD funOnRead) = 0;
+	virtual int writeData(MC::SOFT_COMPONENT softComponent, unsigned int addr, const char* pData, unsigned int nDataLen, ONWRITE funOnWrite) = 0;
+	virtual int writeWord(MC::SOFT_COMPONENT softComponent, unsigned int addr, WORD value, ONWRITE funOnWrite) = 0;
+	virtual int writeDWord(MC::SOFT_COMPONENT softComponent, unsigned int addr, DWORD value, ONWRITE funOnWrite) = 0;
+	virtual int writeBit(MC::SOFT_COMPONENT softComponent, unsigned int addr, BOOL value, ONWRITE funOnWrite) = 0;
+	virtual int writeBit2(MC::SOFT_COMPONENT softComponent, unsigned int addr, BOOL value, int executeTime, ONWRITE funOnWrite) = 0;
+	virtual int writeBitIfIdle(MC::SOFT_COMPONENT softComponent, unsigned int addr, BOOL value, ONWRITE funOnWrite) = 0;
+};
+
diff --git a/SourceCode/Bond/McLibrarySDK/include/McLib.h b/SourceCode/Bond/McLibrarySDK/include/McLib.h
new file mode 100644
index 0000000..138959d
--- /dev/null
+++ b/SourceCode/Bond/McLibrarySDK/include/McLib.h
@@ -0,0 +1,84 @@
+#pragma once
+#include <functional>
+#include <vector>
+#include "IMcChannel.h"
+
+#ifdef _COMPILE_AS_LIB
+#warning "compiling as lib!"
+#else
+#ifdef _DEBUG
+#ifndef _WIN64
+#pragma comment(lib, "../McLibrarySDK/lib/Win32/Debug/McLibrary.lib")
+#else 
+#pragma comment(lib, "../McLibrarySDK/lib/x64/Debug/McLibrary.lib")
+#endif
+#else 
+#ifndef _WIN64
+#pragma comment(lib, "../McLibrarySDK/lib/Win32/Release/McLibrary.lib")
+#else 
+#pragma comment(lib, "../McLibrarySDK/lib/x64/Release/McLibrary.lib")
+#endif
+#endif
+#endif // !BUILD_AS_LIB
+
+
+///////////////////////////////////////////////////////////////////////////////////
+//// Define C linkage if using a C++ compiler
+///////////////////////////////////////////////////////////////////////////////////
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+	///////////////////////////////////////////////////////////////////////////////////
+	//// Determine callling convention baesd on compiler
+	///////////////////////////////////////////////////////////////////////////////////
+#ifdef __BORLANDC__
+
+#ifdef __WIN32__
+#define EXPORTED __declspec(dllexport) __stdcall
+#else
+#define EXPORTED FAR PASCAL __export
+#endif // WIN32
+
+#else // __BORLANDC__
+
+
+#ifdef WIN32
+#define EXPORTED __declspec(dllexport)
+#else
+#define EXPORTED FAR PASCAL __export
+#endif // WIN32
+
+#endif //__BORLANDC__
+
+
+
+	/////////////////////////////////////////////////////////////////////////////////////
+	//// 导出函数
+	////////////////////////////////////////////////////////////////////////////////////
+	int			EXPORTED	MCL_Initialize();
+	int			EXPORTED	MCL_Term();
+	int			EXPORTED	MCL_SetTimeout(int timeout);
+	int			EXPORTED	MCL_SetMaxActionSize(int actionSize);
+	int			EXPORTED	MCL_SetPacketSize(int size);
+	int			EXPORTED	MCL_CreateChannel(IMcChannel*& pChannel, const char* pszName, const char* pszIp,
+		const unsigned int nServerPort, const unsigned int nLocalPort = 0);
+	int			EXPORTED	MCL_DestroyChannel(const char* pszName);
+	int			EXPORTED	MCL_GetChannel(IMcChannel*& pChannel, const char* pszName);
+	int			EXPORTED	MCL_GetCmds(std::vector<std::string>& cmds);
+	int			EXPORTED	MCL_GetCmdString(IN MC::CMD cmd, OUT std::string& strCmd);
+	int			EXPORTED	MCL_GetCmd(IN std::string& strCmd, OUT MC::CMD& cmd);
+	int			EXPORTED	MCL_GetSubCmds(std::vector<std::string>& subCmds);
+	int			EXPORTED	MCL_GetSubCmdString(IN MC::SUBCMD subcmd, OUT std::string& strSubCmd);
+	int			EXPORTED	MCL_GetSubCmd(IN std::string& strSubCmd, OUT MC::SUBCMD& subcmd);
+	int			EXPORTED	MCL_GetSoftComponents(std::vector<std::string>& softComponents);
+	int			EXPORTED	MCL_GetSoftComponentString(std::vector<std::string>& softComponents);
+	int			EXPORTED	MCL_GetSoftComponent(IN std::string& strSoftComponent, OUT MC::SOFT_COMPONENT& softComponent);
+	int			EXPORTED	MCL_GetRawData(MC::CMD cmd, MC::SUBCMD subCmd, MC::SOFT_COMPONENT softComponent,
+								unsigned int firstAddr, int count, char* pszAttach, const unsigned int nAttachSize, char* pszBuffer, const unsigned int nBufferSize);
+
+#ifdef __cplusplus
+};
+
+#endif //__cplusplus
+

--
Gitblit v1.9.3