From e51c6d1360f9679dd8e4dd3379ce0db1886badbf Mon Sep 17 00:00:00 2001
From: LAPTOP-SNT8I5JK\Boounion <Chenluhua@qq.com>
Date: 星期一, 28 七月 2025 17:36:57 +0800
Subject: [PATCH] Merge branch 'EAPSimulator' into clh

---
 Document/MASTER学习资料/LingSignal2.txt                             |   58 
 Document/MASTER学习资料/LingSignal.bmp                              |    0 
 SourceCode/Bond/GangBond2860.sln                                |   14 
 SourceCode/Bond/Servo/CVariable.h                               |   37 
 SourceCode/Bond/EAPSimulator/CAddIDSDlg.h                       |   32 
 SourceCode/Bond/EAPSimulator/CLinkReportDlg.h                   |   36 
 SourceCode/Bond/Servo/HsmsPassive.cpp                           |  561 ++++-
 Document/ESWIN_EAS_Bonder_Inline_Mapping_Address_v1.1.8(1).xlsx |    0 
 SourceCode/Bond/EAPSimulator/CReport.cpp                        |   98 +
 SourceCode/Bond/Servo/CCollectionEvent.cpp                      |  113 +
 Document/MASTER学习资料/LingSignal - 副本.bmp                         |    0 
 SourceCode/Bond/EAPSimulator/EAPSimulator.h                     |   40 
 SourceCode/Bond/EAPSimulator/CHsmsActive.cpp                    |  286 ++
 SourceCode/Bond/EAPSimulator/CTerminalDisplayDlg.cpp            |   73 
 SourceCode/Bond/EAPSimulator/EAPSimulatorDlg.cpp                |  357 +++
 SourceCode/Bond/EAPSimulator/EAPSimulator.vcxproj               |  247 ++
 SourceCode/Bond/EAPSimulator/res/EAPSimulator.ico               |    0 
 SourceCode/Bond/Servo/Servo.rc                                  |    0 
 SourceCode/Bond/EAPSimulator/res/EAPSimulator.rc2               |    0 
 SourceCode/Bond/Servo/CReport.cpp                               |   98 +
 SourceCode/Bond/Servo/ServoDlg.h                                |    2 
 SourceCode/Bond/EAPSimulator/CTerminalDisplayDlg.h              |   27 
 SourceCode/Bond/EAPSimulator/Log.cpp                            |  214 ++
 SourceCode/Bond/Servo/HsmsPassive.h                             |   84 
 SourceCode/Bond/x64/Debug/VariableList.txt                      |   37 
 SourceCode/Bond/EAPSimulator/targetver.h                        |    8 
 SourceCode/Bond/EAPSimulator/EAPSimulator.vcxproj.filters       |  153 +
 SourceCode/Bond/EAPSimulator/LogEdit.h                          |   26 
 SourceCode/Bond/Servo/CPageCollectionEvent.h                    |   34 
 SourceCode/Bond/EAPSimulator/CEDEventReportDlg.cpp              |   71 
 SourceCode/Bond/Servo/CPageVarialbles.cpp                       |  133 +
 SourceCode/Bond/Servo/Servo.vcxproj.filters                     |   12 
 Document/MASTER学习资料/SECS通讯整理.xlsx                               |    0 
 SourceCode/Bond/x64/Debug/CollectionEventList.txt               |   39 
 SourceCode/Bond/Servo/CPageReport.h                             |   34 
 SourceCode/Bond/EAPSimulator/CVariable.h                        |   37 
 SourceCode/Bond/Servo/CMyStatusbar.cpp                          |   27 
 SourceCode/Bond/EAPSimulator/CEDEventReportDlg.h                |   26 
 SourceCode/Bond/Servo/CPageReport.cpp                           |  126 +
 SourceCode/Bond/EAPSimulator/CLinkReportDetailDlg.cpp           |   65 
 SourceCode/Bond/EAPSimulator/CModel.cpp                         |  300 +++
 SourceCode/Bond/EAPSimulator/pch.h                              |   17 
 SourceCode/Bond/Servo/Servo.vcxproj                             |   12 
 SourceCode/Bond/Servo/CMyStatusbar.h                            |    2 
 .gitignore                                                      |    2 
 SourceCode/Bond/EAPSimulator/CDefineReportsDlg.h                |   40 
 SourceCode/Bond/Servo/resource.h                                |    0 
 SourceCode/Bond/Servo/Servo.vcxproj.user                        |    2 
 SourceCode/Bond/EAPSimulator/framework.h                        |   49 
 SourceCode/Bond/EAPSimulator/CHsmsActive.h                      |   74 
 SourceCode/Bond/EAPSimulator/EAPSimulatorDlg.h                  |   57 
 SourceCode/Bond/Servo/CMaster.h                                 |    9 
 Document/simulator/SEComSimulator.Conf                          |    9 
 SourceCode/Bond/EAPSimulator/Common.h                           |    6 
 SourceCode/Bond/EAPSimulator/CReport.h                          |   28 
 SourceCode/Bond/EAPSimulator/Resource.h                         |   58 
 SourceCode/Bond/EAPSimulator/EAPSimulator.vcxproj.user          |    6 
 SourceCode/Bond/EAPSimulator/CModel.h                           |   43 
 SourceCode/Bond/Servo/CMaster.cpp                               |   25 
 SourceCode/Bond/EAPSimulator/CLinkReportDetailDlg.h             |   31 
 SourceCode/Bond/EAPSimulator/Context.cpp                        |  184 +
 SourceCode/Bond/x64/Debug/ReportList.txt                        |   17 
 SourceCode/Bond/EAPSimulator/CAddIDSDlg.cpp                     |   65 
 SourceCode/Bond/EAPSimulator/CCollectionEvent.h                 |   33 
 SourceCode/Bond/EAPSimulator/EAPSimulator.cpp                   |  133 +
 SourceCode/Bond/HSMSSDK/Include/HSMSSDK.h                       |    4 
 SourceCode/Bond/EAPSimulator/LogEdit.cpp                        |  117 +
 SourceCode/Bond/EAPSimulator/pch.cpp                            |    5 
 SourceCode/Bond/EAPSimulator/Context.h                          |   48 
 SourceCode/Bond/Servo/CPageCollectionEvent.cpp                  |  126 +
 SourceCode/Bond/EAPSimulator/CDefineReportsDlg.cpp              |  193 ++
 SourceCode/Bond/EAPSimulator/EAPSimulator.rc                    |    0 
 SourceCode/Bond/Servo/Model.cpp                                 |   33 
 SourceCode/Bond/Servo/ServoDlg.cpp                              |   53 
 SourceCode/Bond/Servo/CCollectionEvent.h                        |   34 
 SourceCode/Bond/HSMSSDK/Include/IActive.h                       |   41 
 SourceCode/Bond/HSMSSDK/Include/ISECS2Item.h                    |    3 
 Document/VariableList.txt                                       |   37 
 SourceCode/Bond/EAPSimulator/CCollectionEvent.cpp               |  110 +
 SourceCode/Bond/Servo/CPageVarialbles.h                         |   36 
 SourceCode/Bond/EAPSimulator/CVariable.cpp                      |   90 
 SourceCode/Bond/Servo/CReport.h                                 |   28 
 SourceCode/Bond/Servo/CVariable.cpp                             |   90 
 SourceCode/Bond/EAPSimulator/Log.h                              |   61 
 SourceCode/Bond/EAPSimulator/CLinkReportDlg.cpp                 |  205 ++
 SourceCode/Bond/EAPSimulator/res/application.exe.manifest       |   20 
 Document/Panel Bonder八零联合 SecsTest CheckList_v3.0.xlsx          |    0 
 SourceCode/Bond/Servo/CBonder.cpp                               |   13 
 88 files changed, 5,573 insertions(+), 181 deletions(-)

diff --git a/.gitignore b/.gitignore
index 1630a76..0999df4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -57,4 +57,4 @@
 SourceCode/Bond/x64/Debug/Config/robot_offset.ini
 *.tlog
 *.pch
-SourceCode/Bond/EAPSimulator/x64/Debug/
+SourceCode/Bond/EAPSimulator/x64/
diff --git "a/Document/ESWIN_EAS_Bonder_Inline_Mapping_Address_v1.1.8\0501\051.xlsx" "b/Document/ESWIN_EAS_Bonder_Inline_Mapping_Address_v1.1.8\0501\051.xlsx"
new file mode 100644
index 0000000..01341f2
--- /dev/null
+++ "b/Document/ESWIN_EAS_Bonder_Inline_Mapping_Address_v1.1.8\0501\051.xlsx"
Binary files differ
diff --git "a/Document/MASTER\345\255\246\344\271\240\350\265\204\346\226\231/LingSignal - \345\211\257\346\234\254.bmp" "b/Document/MASTER\345\255\246\344\271\240\350\265\204\346\226\231/LingSignal - \345\211\257\346\234\254.bmp"
new file mode 100644
index 0000000..6c41ca3
--- /dev/null
+++ "b/Document/MASTER\345\255\246\344\271\240\350\265\204\346\226\231/LingSignal - \345\211\257\346\234\254.bmp"
Binary files differ
diff --git "a/Document/MASTER\345\255\246\344\271\240\350\265\204\346\226\231/LingSignal.bmp" "b/Document/MASTER\345\255\246\344\271\240\350\265\204\346\226\231/LingSignal.bmp"
new file mode 100644
index 0000000..48efdae
--- /dev/null
+++ "b/Document/MASTER\345\255\246\344\271\240\350\265\204\346\226\231/LingSignal.bmp"
Binary files differ
diff --git "a/Document/MASTER\345\255\246\344\271\240\350\265\204\346\226\231/LingSignal2.txt" "b/Document/MASTER\345\255\246\344\271\240\350\265\204\346\226\231/LingSignal2.txt"
new file mode 100644
index 0000000..ac3e3b2
--- /dev/null
+++ "b/Document/MASTER\345\255\246\344\271\240\350\265\204\346\226\231/LingSignal2.txt"
@@ -0,0 +1,58 @@
+| 淇″彿鍚嶇О                            | EAS瑙掕壊锛堣/鍐欙級 | 璇存槑                |
+| ------------------------------- | ---------- | ----------------- |
+| Downstream Inline               | 璇�          | 涓嬫父Inline鐘舵�侊紝璁惧鍛婄煡涓绘満 |
+| Downstream Trouble              | 璇�          | 涓嬫父寮傚父閫氱煡锛岃澶囧彂缁欎富鏈�     |
+| Interlock                       | 璇�          | 浜掗攣鐘舵�侊紝璁惧鍙嶉         |
+| Send Able                       | 璇�          | 璁惧鏄惁鍑嗗濂藉彂閫丟lass淇″彿  |
+| Send Start                      | 鍐�          | 涓绘満鎸囦护璁惧寮�濮嬪彂閫丟lass   |
+| Job Transfer                    | 鍐�          | 涓绘満鎸囦护璁惧杩涜Job杞Щ     |
+| Send Complete                   | 璇�          | 璁惧鍙嶉鍙戦�佸畬鎴愪俊鍙�        |
+| Shutter State                   | 璇�          | 璁惧鎸℃澘鐘舵�侊紝璁惧鍙嶉       |
+| Pin State                       | 璇�          | 璁惧閽堣剼鐘舵��            |
+| Slot Pair Flag                  | 璇�          | 璁惧鍙嶉Slot閰嶅鐘舵��      |
+| Arm Slot Pair Flag              | 璇�          | 鏈烘鑷係lot閰嶅鐘舵��       |
+| Exchange Possible               | 璇�          | 璁惧鍙嶉鏄惁鍏佽浜ゆ崲        |
+| Exchange Execute                | 鍐�          | 涓绘満涓嬪彂鎵ц浜ゆ崲鎸囦护        |
+| Cancel Request                  | 鍐�          | 涓绘満鍙栨秷褰撳墠鎿嶄綔璇锋眰        |
+| Cancel Ack                      | 璇�          | 璁惧纭鍙栨秷鎿嶄綔          |
+| Cancel Nck                      | 璇�          | 璁惧鎷掔粷鍙栨秷鎿嶄綔          |
+| Abort Request                   | 鍐�          | 涓绘満璇锋眰涓鎿嶄綔          |
+| Abort Ack                       | 璇�          | 璁惧纭涓鎿嶄綔          |
+| Abort Nck                       | 璇�          | 璁惧鎷掔粷涓鎿嶄綔          |
+| Resume Request                  | 鍐�          | 涓绘満璇锋眰鎭㈠鎿嶄綔          |
+| Resume Ack                      | 璇�          | 璁惧纭鎭㈠鎿嶄綔          |
+| Resume Nak                      | 璇�          | 璁惧鎷掔粷鎭㈠鎿嶄綔          |
+| Abnormal                        | 璇�          | 璁惧寮傚父淇″彿            |
+| Empty                           | 璇�          | 璁惧绌虹姸鎬�             |
+| Idle                            | 璇�          | 璁惧绌洪棽鐘舵��            |
+| Run                             | 璇�          | 璁惧杩愯鐘舵��            |
+| Complete                        | 璇�          | 璁惧瀹屾垚鐘舵��            |
+| Lift Up or Pin Up               | 璇�          | 璁惧鎶崌鐘舵��            |
+| Lift Down or Pin Down           | 璇�          | 璁惧涓嬮檷鐘舵��            |
+| Stopper Up or Shutter Open      | 璇�          | 璁惧鎸℃澘寮�鐘舵��           |
+| Stopper Down or Shutter Close   | 璇�          | 璁惧鎸℃澘鍏崇姸鎬�           |
+| Manual Operation                | 璇�          | 璁惧鎵嬪姩鎿嶄綔鐘舵��          |
+| Body Moving                     | 璇�          | 璁惧鍔ㄤ綔涓姸鎬�           |
+| Glass Exist #1(Check Sensor on) | 璇�          | 鐜荤拑瀛樺湪浼犳劅鍣ㄤ俊鍙�         |
+| Glass Exist #2(Check Sensor on) | 璇�          | 鐜荤拑瀛樺湪浼犳劅鍣ㄤ俊鍙�         |
+| Glass Exist #1 Exist            | 璇�          | 鐜荤拑瀹為檯瀛樺湪鐘舵��          |
+| Glass Exist #2 Exist            | 璇�          | 鐜荤拑瀹為檯瀛樺湪鐘舵��          |
+| Arm Stretch complete            | 璇�          | 鏈烘鑷備几灞曞畬鎴�           |
+| Arm Vacuum                      | 璇�          | 鏈烘鑷傚惛闄勭姸鎬�           |
+| Conveyor State                  | 璇�          | 浼犻�佸甫鐘舵��             |
+| Arm Fold complete               | 璇�          | 鏈烘鑷傛姌鍙犲畬鎴�           |
+| Make Define #1\~#9              | 璇�          | 璁惧鑷畾涔変俊鍙凤紝涓�鑸澶囧弽棣�    |
+
+
+
+鎬荤粨
+| 浣犻渶瑕佽繖涓や釜淇″彿鍚楋紵 | 绛旀鏄細蹇呴』鍚屾椂鐢ㄣ��
+| 鈥� | 鈥� |
+| Robot CMD | 鈥滃啓鎼繍鍔ㄤ綔鍙傛暟鈥� |
+| Indexer Operation Mode Command | 鈥滃彂鍚姩鍛戒护鈥� |
+
+Load port Status涓婃姤jobData
+杈规NG, Job Data Change report, 瑕佸師璺��鍥�
+
+sh600975 sz002818 sh600727 sh600829
+
diff --git "a/Document/MASTER\345\255\246\344\271\240\350\265\204\346\226\231/SECS\351\200\232\350\256\257\346\225\264\347\220\206.xlsx" "b/Document/MASTER\345\255\246\344\271\240\350\265\204\346\226\231/SECS\351\200\232\350\256\257\346\225\264\347\220\206.xlsx"
new file mode 100644
index 0000000..f48f0e0
--- /dev/null
+++ "b/Document/MASTER\345\255\246\344\271\240\350\265\204\346\226\231/SECS\351\200\232\350\256\257\346\225\264\347\220\206.xlsx"
Binary files differ
diff --git "a/Document/Panel Bonder\345\205\253\351\233\266\350\201\224\345\220\210 SecsTest CheckList_v3.0.xlsx" "b/Document/Panel Bonder\345\205\253\351\233\266\350\201\224\345\220\210 SecsTest CheckList_v3.0.xlsx"
index 33de0ae..6b16c1a 100644
--- "a/Document/Panel Bonder\345\205\253\351\233\266\350\201\224\345\220\210 SecsTest CheckList_v3.0.xlsx"
+++ "b/Document/Panel Bonder\345\205\253\351\233\266\350\201\224\345\220\210 SecsTest CheckList_v3.0.xlsx"
Binary files differ
diff --git a/Document/VariableList.txt b/Document/VariableList.txt
new file mode 100644
index 0000000..1c92863
--- /dev/null
+++ b/Document/VariableList.txt
@@ -0,0 +1,37 @@
+SVID,SV Name,SV Format,SV Remark
+100,PortTransferState,U1,"0=OutOfService\r\n1=TransferBlocked\r\n2=ReadyToLoad\r\n3=ReadyToUnload\r\n4=InService\r\n5=TransferReady"
+300,AccessMode,U1,"1=Manual\r\n2=Auto"
+500,Clock,A50,
+600,CurrentControlState,U1,"0:Offline:equipment\r\n1:Offline-Attempt\r\n2:Online\r\n3:Offline:host\r\n4:Online:Local\r\n5:Online:Remote"
+601,PreviousControlState,U1,
+700,CurrentProcessState,U1,"0:DOWN\r\n1:IDLE\r\n2.SETUP\r\n3.EXCUTING\r\n4.MAINTAIN\r\n5.ALARM"
+701,PreviousProcessState,U1,
+800,EFEMPPExecName,A20,
+801,EQPPExecName,A20,
+1000,CJobSpace,U1,
+2000,RbRAxisTorque,I2,鏈哄櫒浜篟杞存壄鐭�
+2001,RbLAxisTorque,l2,鏈哄櫒浜篖杞存壄鐭�
+2002,RbZAxisTorque,l2,鏈哄櫒浜篫杞存壄鐭�
+2003,RbTHAxisTorque,l2,鏈哄櫒浜篢H杞存壄鐭�
+2004,RbXAxisTorque,l2,鏈哄櫒浜篨杞存壄鐭�
+2005,AxisX111,l2,X111鐩告満鍓嶇Щ鏍界數鏈烘壄鐭�
+2006,AxisX112,l2,X112鐩告満鍚庣Щ鏍界數鏈烘壄鐭�
+2007,AxisU113,l2,U113浜у搧鏃嬭浆鐢垫満鎵煩
+2008,AxisX114,l2,X114浜у搧宸︽暣鍒楃數鏈烘壄鐭�
+2009,AxisY121,l2,Y121浜у搧鍙虫暣鍒楃數鏈烘壄鐭�
+2010,AxisY122,l2,Y122浜у搧鍓嶆暣鍒楃數鏈烘壄鐭�
+2011,AxisY123,l2,Y123浜у搧鍚庨樀鍒楃數鏈烘壄鐭�
+2012,MainAir,U2,鎬昏繘姘斿帇鍔涘��
+2013,MainVacuum,l2,鎬荤湡绌哄帇鍔涘��
+2014,RbMainVacuum,l2,鏈哄櫒浜虹湡绌哄��
+2015,LPMainVacuum,l2,LP鐪熺┖鍊�#D265
+2016,LPMainAir,U2,LP鍘嬬┖鍊�
+2017,ALVacuum,l2,Aligner鐪熺┖鍊�
+2018,FFU1RPM,U2,FFU1杞��
+2019,FFU2RPM,U2,FFU2杞��
+2020,FFU3RPM,U2,FFU3杞��
+2021,FFU4RPM,U2,FFU4杞��
+2022,ESDValue,I2,闈欑數妫�娴嬪��
+2023,OCREnable,U2,"OCR浣胯兘锛歄:寮�鍚� 1锛氬睆钄�"
+2024,CCDEnable,U2,"CCD浣胯兘锛歄:寮�鍚� 1锛氬睆钄�"
+2025,FFUParameter,U2,FFU璁惧畾鍊�
diff --git a/Document/simulator/SEComSimulator.Conf b/Document/simulator/SEComSimulator.Conf
index a2608bb..19954d1 100644
--- a/Document/simulator/SEComSimulator.Conf
+++ b/Document/simulator/SEComSimulator.Conf
@@ -10,7 +10,7 @@
         <IDENTITY>Host</IDENTITY>
       </DRVINFO>
       <LOGINFO>
-        <DIR>D:\Chenluhua\dazi\a</DIR>
+        <DIR>D:\Chenluhua\dazi\A</DIR>
         <SECSIMODE>D</SECSIMODE>
         <SECSIIMODE>D</SECSIIMODE>
         <XMLMODE />
@@ -20,16 +20,15 @@
       </LOGINFO>
       <SECSMODE MODE="HSMS">
         <HSMS>
-          <HSMSMODE>Active</HSMSMODE>
+          <HSMSMODE>Passive</HSMSMODE>
           <REMOTEIP>127.0.0.1</REMOTEIP>
           <REMOTEPORT>7000</REMOTEPORT>
-          <LOCALPORT>
-          </LOCALPORT>
+          <LOCALPORT>7001</LOCALPORT>
         </HSMS>
         <SECS1>
           <MASTER>True</MASTER>
           <COMPORT>COM1</COMPORT>
-          <AUTOBAUD>False</AUTOBAUD>
+          <AUTOBAUD>True</AUTOBAUD>
           <BAUDRATE>9600</BAUDRATE>
           <INTERLEAVE>False</INTERLEAVE>
           <RETRYCOUNT>3</RETRYCOUNT>
diff --git a/SourceCode/Bond/EAPSimulator/CAddIDSDlg.cpp b/SourceCode/Bond/EAPSimulator/CAddIDSDlg.cpp
new file mode 100644
index 0000000..d11ccf3
--- /dev/null
+++ b/SourceCode/Bond/EAPSimulator/CAddIDSDlg.cpp
@@ -0,0 +1,65 @@
+锘�// CAddIDSDlg.cpp: 瀹炵幇鏂囦欢
+//
+
+#include "pch.h"
+#include "EAPSimulator.h"
+#include "CAddIDSDlg.h"
+#include "afxdialogex.h"
+
+
+// CAddIDSDlg 瀵硅瘽妗�
+
+IMPLEMENT_DYNAMIC(CAddIDSDlg, CDialogEx)
+
+CAddIDSDlg::CAddIDSDlg(CWnd* pParent /*=nullptr*/)
+	: CDialogEx(IDD_DIALOG_ADD_IDS, pParent)
+{
+	m_nId = 0;
+}
+
+CAddIDSDlg::~CAddIDSDlg()
+{
+}
+
+void CAddIDSDlg::DoDataExchange(CDataExchange* pDX)
+{
+	CDialogEx::DoDataExchange(pDX);
+}
+
+
+BEGIN_MESSAGE_MAP(CAddIDSDlg, CDialogEx)
+	ON_BN_CLICKED(IDOK, &CAddIDSDlg::OnBnClickedOk)
+END_MESSAGE_MAP()
+
+
+// CAddIDSDlg 娑堟伅澶勭悊绋嬪簭
+
+void CAddIDSDlg::SetTitle(const char* pszTitle)
+{
+	m_strTitle = pszTitle;
+}
+
+BOOL CAddIDSDlg::OnInitDialog()
+{
+	CDialogEx::OnInitDialog();
+
+	// TODO:  鍦ㄦ娣诲姞棰濆鐨勫垵濮嬪寲
+	SetWindowText(m_strTitle);
+	SetDlgItemText(IDC_GROUP_IDS, m_strTitle);
+
+	return TRUE;  // return TRUE unless you set the focus to a control
+				  // 寮傚父: OCX 灞炴�ч〉搴旇繑鍥� FALSE
+}
+
+unsigned int CAddIDSDlg::GetId()
+{
+	return m_nId;
+}
+
+
+void CAddIDSDlg::OnBnClickedOk()
+{
+	m_nId = GetDlgItemInt(IDC_EDIT_ID);
+
+	CDialogEx::OnOK();
+}
diff --git a/SourceCode/Bond/EAPSimulator/CAddIDSDlg.h b/SourceCode/Bond/EAPSimulator/CAddIDSDlg.h
new file mode 100644
index 0000000..1bf0c8f
--- /dev/null
+++ b/SourceCode/Bond/EAPSimulator/CAddIDSDlg.h
@@ -0,0 +1,32 @@
+锘�#pragma once
+
+
+// CAddIDSDlg 瀵硅瘽妗�
+
+class CAddIDSDlg : public CDialogEx
+{
+	DECLARE_DYNAMIC(CAddIDSDlg)
+
+public:
+	CAddIDSDlg(CWnd* pParent = nullptr);   // 鏍囧噯鏋勯�犲嚱鏁�
+	virtual ~CAddIDSDlg();
+	void SetTitle(const char* pszTitle);
+	unsigned int GetId();
+
+private:
+	CString m_strTitle;
+	unsigned int m_nId;
+
+// 瀵硅瘽妗嗘暟鎹�
+#ifdef AFX_DESIGN_TIME
+	enum { IDD = IDD_DIALOG_ADD_IDS };
+#endif
+
+protected:
+	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 鏀寔
+
+	DECLARE_MESSAGE_MAP()
+public:
+	virtual BOOL OnInitDialog();
+	afx_msg void OnBnClickedOk();
+};
diff --git a/SourceCode/Bond/EAPSimulator/CCollectionEvent.cpp b/SourceCode/Bond/EAPSimulator/CCollectionEvent.cpp
new file mode 100644
index 0000000..abb12d4
--- /dev/null
+++ b/SourceCode/Bond/EAPSimulator/CCollectionEvent.cpp
@@ -0,0 +1,110 @@
+#include "pch.h"
+#include "CCollectionEvent.h"
+
+
+namespace SERVO {
+	CCollectionEvent::CCollectionEvent()
+	{
+		m_nCEID = 0;
+	}
+
+	CCollectionEvent::CCollectionEvent(unsigned int id, const char* pszName, const char* pszDescription, std::vector<unsigned int>& prtids)
+	{
+		m_nCEID = id;
+		m_strName = pszName;
+		m_strDescription = pszDescription;
+		for (auto item : prtids) {
+			m_rptids.push_back(item);
+		}
+	}
+
+	CCollectionEvent::~CCollectionEvent()
+	{
+
+	}
+
+	unsigned int CCollectionEvent::getEventId()
+	{
+		return m_nCEID;
+	}
+
+	std::string& CCollectionEvent::getName()
+	{
+		return m_strName;
+	}
+
+	std::string& CCollectionEvent::getDescription()
+	{
+		return m_strDescription;
+	}
+
+	BOOL CCollectionEvent::addReport(CReport* pReport)
+	{
+		ASSERT(pReport);
+		if (getReport(pReport->getReportId()) != nullptr) {
+			return FALSE;
+		}
+
+		m_reports.push_back(pReport);
+		return TRUE;
+	}
+
+	BOOL CCollectionEvent::deleteReport(unsigned int nReportId)
+	{
+		BOOL bDelete = FALSE;
+		for (auto iter = m_reports.begin(); iter != m_reports.end(); ++iter) {
+			if (nReportId == (*iter)->getReportId()) {
+				m_reports.erase(iter);
+				bDelete = TRUE;
+				break;
+			}
+		}
+
+		return bDelete;
+	}
+
+	CReport* CCollectionEvent::getReport(unsigned int nReportId)
+	{
+		for (auto item : m_reports) {
+			if (nReportId == item->getReportId()) {
+				return item;
+			}
+		}
+
+		return nullptr;
+	}
+
+	void CCollectionEvent::setReport(unsigned int nReportId)
+	{
+		m_rptids.clear();
+		if (nReportId != 0) {
+			m_rptids.push_back(nReportId);
+		}
+	}
+
+	std::vector<CReport*>& CCollectionEvent::getReports()
+	{
+		return m_reports;
+	}
+
+	std::vector<unsigned int>& CCollectionEvent::getReportIds()
+	{
+		return m_rptids;
+	}
+
+	std::string CCollectionEvent::getReportIdsText()
+	{
+		std::string strResult, strName;
+		for (int i = 0; i < m_rptids.size(); i++) {
+			strResult += std::to_string(m_rptids[i]);// (getReport(m_rptids[i]) ?
+			if (nullptr == getReport(m_rptids[i])) {
+				strResult += "";
+			}
+			if (i != m_rptids.size() - 1) {
+				strResult += ",";
+			}
+		}
+
+		return strResult;
+	}
+}
diff --git a/SourceCode/Bond/EAPSimulator/CCollectionEvent.h b/SourceCode/Bond/EAPSimulator/CCollectionEvent.h
new file mode 100644
index 0000000..bfb6418
--- /dev/null
+++ b/SourceCode/Bond/EAPSimulator/CCollectionEvent.h
@@ -0,0 +1,33 @@
+#pragma once
+#include "CReport.h"
+#include <vector>
+
+
+namespace SERVO {
+	class CCollectionEvent
+	{
+	public:
+		CCollectionEvent();
+		CCollectionEvent(unsigned int id, const char* pszName, const char* pszDescription, std::vector<unsigned int>& prtids);
+		virtual ~CCollectionEvent();
+
+	public:
+		unsigned int getEventId();
+		std::string& getName();
+		std::string& getDescription();
+		std::vector<CReport*>& getReports();
+		std::vector<unsigned int>& getReportIds();
+		std::string getReportIdsText();
+		BOOL addReport(CReport* pReport);
+		BOOL deleteReport(unsigned int nReportId);
+		CReport* getReport(unsigned int nReportId);
+		void setReport(unsigned int nReportId);
+
+	private:
+		unsigned int m_nCEID;
+		std::string m_strName;
+		std::string m_strDescription;
+		std::vector<unsigned int> m_rptids;
+		std::vector<CReport*> m_reports;
+	};
+}
diff --git a/SourceCode/Bond/EAPSimulator/CDefineReportsDlg.cpp b/SourceCode/Bond/EAPSimulator/CDefineReportsDlg.cpp
new file mode 100644
index 0000000..5ff5f39
--- /dev/null
+++ b/SourceCode/Bond/EAPSimulator/CDefineReportsDlg.cpp
@@ -0,0 +1,193 @@
+锘�// CDefineReportsDlg.cpp: 瀹炵幇鏂囦欢
+//
+
+#include "pch.h"
+#include "EAPSimulator.h"
+#include "CDefineReportsDlg.h"
+#include "afxdialogex.h"
+#include "CAddIDSDlg.h"
+
+
+// CDefineReportsDlg 瀵硅瘽妗�
+
+IMPLEMENT_DYNAMIC(CDefineReportsDlg, CDialogEx)
+
+CDefineReportsDlg::CDefineReportsDlg(CWnd* pParent /*=nullptr*/)
+	: CDialogEx(IDD_DIALOG_DEFINE_REPORTS, pParent)
+{
+
+}
+
+CDefineReportsDlg::~CDefineReportsDlg()
+{
+}
+
+void CDefineReportsDlg::DoDataExchange(CDataExchange* pDX)
+{
+	CDialogEx::DoDataExchange(pDX);
+}
+
+
+BEGIN_MESSAGE_MAP(CDefineReportsDlg, CDialogEx)
+	ON_BN_CLICKED(IDC_BUTTON_ADD_RPTID, &CDefineReportsDlg::OnBnClickedButtonAddRptid)
+	ON_LBN_SELCHANGE(IDC_LIST1, &CDefineReportsDlg::OnLbnSelchangeList1)
+	ON_BN_CLICKED(IDC_BUTTON_DEL_REPORT, &CDefineReportsDlg::OnBnClickedButtonDelReport)
+	ON_BN_CLICKED(IDC_BUTTON_ADD_VID, &CDefineReportsDlg::OnBnClickedButtonAddVid)
+	ON_LBN_SELCHANGE(IDC_LIST2, &CDefineReportsDlg::OnLbnSelchangeList2)
+	ON_BN_CLICKED(IDC_BUTTON_DEL_VID, &CDefineReportsDlg::OnBnClickedButtonDelVid)
+	ON_BN_CLICKED(IDC_BUTTON_SEND, &CDefineReportsDlg::OnBnClickedButtonSend)
+END_MESSAGE_MAP()
+
+
+// CDefineReportsDlg 娑堟伅澶勭悊绋嬪簭
+void CDefineReportsDlg::OnBnClickedButtonAddRptid()
+{
+	CAddIDSDlg dlg;
+	dlg.SetTitle("RPTID");
+	dlg.DoModal();
+	int PRTID = dlg.GetId();
+	addReport(PRTID);
+}
+
+void CDefineReportsDlg::OnBnClickedButtonAddVid()
+{
+	CString strReportId;
+	CListBox* pListBox = (CListBox*)GetDlgItem(IDC_LIST1);
+	int nSel = pListBox->GetCurSel();
+	if (nSel >= 0) {
+		pListBox->GetText(nSel, strReportId);
+		int RPTID = atoi(strReportId);
+
+		CAddIDSDlg dlg;
+		dlg.SetTitle("RPTID");
+		dlg.DoModal();
+		unsigned int VID = dlg.GetId();;
+		addVid(RPTID, VID);
+	}
+
+
+}
+
+void CDefineReportsDlg::OnLbnSelchangeList1()
+{
+	CString strReportId;
+	int RPTID = -1;
+	CListBox* pListBox = (CListBox*)GetDlgItem(IDC_LIST1);
+	int nSel = pListBox->GetCurSel();
+	if (nSel >= 0) {
+		pListBox->GetText(nSel, strReportId);
+		RPTID = atoi(strReportId);
+	}
+
+	GetDlgItem(IDC_BUTTON_DEL_REPORT)->EnableWindow(nSel >= 0);
+	GetDlgItem(IDC_BUTTON_ADD_VID)->EnableWindow(nSel >= 0);
+
+	CListBox* pListBox2 = (CListBox*)GetDlgItem(IDC_LIST2);
+	pListBox2->ResetContent();
+	auto iter = m_mapReport.find(RPTID);
+	if (iter != m_mapReport.end()) {
+		auto& vids = m_mapReport[RPTID];
+		for (auto item : vids) {
+			pListBox2->AddString(std::to_string(item).c_str());
+		}
+	}
+}
+
+void CDefineReportsDlg::OnBnClickedButtonDelReport()
+{
+	CString strReportId;
+	CListBox* pListBox = (CListBox*)GetDlgItem(IDC_LIST1);
+	int nSel = pListBox->GetCurSel();
+	if (nSel >= 0) {
+		pListBox->GetText(nSel, strReportId);
+		int RPTID = atoi(strReportId);
+		delReport(RPTID);
+		pListBox->DeleteString(nSel);
+		((CListBox*)GetDlgItem(IDC_LIST2))->ResetContent();
+	}
+
+	nSel = pListBox->GetCurSel();
+	GetDlgItem(IDC_BUTTON_DEL_REPORT)->EnableWindow(nSel >= 0);
+	GetDlgItem(IDC_BUTTON_ADD_VID)->EnableWindow(nSel >= 0);
+}
+
+void CDefineReportsDlg::OnLbnSelchangeList2()
+{
+	CListBox* pListBox2 = (CListBox*)GetDlgItem(IDC_LIST2);
+	int nSel = pListBox2->GetCurSel();
+	GetDlgItem(IDC_BUTTON_DEL_VID)->EnableWindow(nSel >= 0);
+}
+
+void CDefineReportsDlg::OnBnClickedButtonDelVid()
+{
+	CString strRPTID, strVID;
+	CListBox* pListBox1 = (CListBox*)GetDlgItem(IDC_LIST1);
+	CListBox* pListBox2 = (CListBox*)GetDlgItem(IDC_LIST2);
+	int nSel1 = pListBox1->GetCurSel();
+	int nSel2 = pListBox2->GetCurSel();
+	if (nSel1 >= 0 && nSel2 >= 0) {
+		pListBox1->GetText(nSel1, strRPTID);
+		pListBox2->GetText(nSel2, strVID);
+		int RPTID = atoi(strRPTID);
+		int VID = atoi(strVID);
+		delVid(RPTID, VID);
+		pListBox2->DeleteString(nSel2);
+	}
+
+	nSel2 = pListBox2->GetCurSel();
+	GetDlgItem(IDC_BUTTON_DEL_VID)->EnableWindow(nSel2 >= 0);
+}
+
+void CDefineReportsDlg::addReport(int RPTID)
+{
+	auto iter = m_mapReport.find(RPTID);
+	if (iter == m_mapReport.end()) {
+		std::vector<unsigned int> vids;
+		m_mapReport[RPTID] = vids;
+	}
+
+	CListBox* pListBox = (CListBox*)GetDlgItem(IDC_LIST1);
+	pListBox->AddString(std::to_string(RPTID).c_str());
+}
+
+bool CDefineReportsDlg::addVid(unsigned int RPTID, unsigned int vid)
+{
+	auto iter = m_mapReport.find(RPTID);
+	if (iter == m_mapReport.end()) {
+		return false;
+	}
+
+	auto& vids = m_mapReport[RPTID];
+	vids.push_back(vid);
+	CListBox* pListBox = (CListBox*)GetDlgItem(IDC_LIST2);
+	pListBox->AddString(std::to_string(vid).c_str());
+
+	return true;
+}
+
+void CDefineReportsDlg::delReport(int RPTID)
+{
+	auto iter = m_mapReport.find(RPTID);
+	if (iter != m_mapReport.end()) {
+		m_mapReport.erase(iter);
+	}
+}
+
+void CDefineReportsDlg::delVid(int RPTID, int VID)
+{
+	auto iter = m_mapReport.find(RPTID);
+	if (iter != m_mapReport.end()) {
+		auto& vids = iter->second;
+		for (auto iter2 = vids.begin(); iter2 != vids.end(); iter2++) {
+			if ((*iter2) == VID) {
+				vids.erase(iter2);
+				break;
+			}
+		}
+	}
+}
+
+void CDefineReportsDlg::OnBnClickedButtonSend()
+{
+	theApp.m_model.m_pHsmsActive->hsmsDefineReports(m_mapReport);
+}
diff --git a/SourceCode/Bond/EAPSimulator/CDefineReportsDlg.h b/SourceCode/Bond/EAPSimulator/CDefineReportsDlg.h
new file mode 100644
index 0000000..e37af56
--- /dev/null
+++ b/SourceCode/Bond/EAPSimulator/CDefineReportsDlg.h
@@ -0,0 +1,40 @@
+锘�#pragma once
+#include <map>
+#include <vector>
+
+// CDefineReportsDlg 瀵硅瘽妗�
+
+class CDefineReportsDlg : public CDialogEx
+{
+	DECLARE_DYNAMIC(CDefineReportsDlg)
+
+public:
+	CDefineReportsDlg(CWnd* pParent = nullptr);   // 鏍囧噯鏋勯�犲嚱鏁�
+	virtual ~CDefineReportsDlg();
+	void addReport(int RPTID);
+	void delReport(int RPTID);
+	bool addVid(unsigned int RPTID, unsigned int vid);
+	void delVid(int RPTID, int VID);
+
+private:
+	std::map<unsigned int, std::vector<unsigned int>> m_mapReport;
+
+
+// 瀵硅瘽妗嗘暟鎹�
+#ifdef AFX_DESIGN_TIME
+	enum { IDD = IDD_DIALOG_DEFINE_REPORTS };
+#endif
+
+protected:
+	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 鏀寔
+
+	DECLARE_MESSAGE_MAP()
+public:
+	afx_msg void OnBnClickedButtonAddRptid();
+	afx_msg void OnLbnSelchangeList1();
+	afx_msg void OnBnClickedButtonDelReport();
+	afx_msg void OnBnClickedButtonAddVid();
+	afx_msg void OnLbnSelchangeList2();
+	afx_msg void OnBnClickedButtonDelVid();
+	afx_msg void OnBnClickedButtonSend();
+};
diff --git a/SourceCode/Bond/EAPSimulator/CEDEventReportDlg.cpp b/SourceCode/Bond/EAPSimulator/CEDEventReportDlg.cpp
new file mode 100644
index 0000000..6851b13
--- /dev/null
+++ b/SourceCode/Bond/EAPSimulator/CEDEventReportDlg.cpp
@@ -0,0 +1,71 @@
+锘�// CEDEventReportDlg.cpp: 瀹炵幇鏂囦欢
+//
+
+#include "pch.h"
+#include "EAPSimulator.h"
+#include "CEDEventReportDlg.h"
+#include "afxdialogex.h"
+#include <vector>
+
+
+// CEDEventReportDlg 瀵硅瘽妗�
+
+IMPLEMENT_DYNAMIC(CEDEventReportDlg, CDialogEx)
+
+CEDEventReportDlg::CEDEventReportDlg(CWnd* pParent /*=nullptr*/)
+	: CDialogEx(IDD_DIALOG_ED_EVENT_REPORT, pParent)
+{
+
+}
+
+CEDEventReportDlg::~CEDEventReportDlg()
+{
+}
+
+void CEDEventReportDlg::DoDataExchange(CDataExchange* pDX)
+{
+	CDialogEx::DoDataExchange(pDX);
+}
+
+
+BEGIN_MESSAGE_MAP(CEDEventReportDlg, CDialogEx)
+	ON_BN_CLICKED(IDC_BUTTON_SEND, &CEDEventReportDlg::OnBnClickedButtonSend)
+END_MESSAGE_MAP()
+
+
+// CEDEventReportDlg 娑堟伅澶勭悊绋嬪簭
+
+
+BOOL CEDEventReportDlg::OnInitDialog()
+{
+	CDialogEx::OnInitDialog();
+
+	CButton* pButton = (CButton*)GetDlgItem(IDC_RADIO_ENABLE);
+	pButton->SetCheck(BST_CHECKED);
+
+
+	return TRUE;  // return TRUE unless you set the focus to a control
+				  // 寮傚父: OCX 灞炴�ч〉搴旇繑鍥� FALSE
+}
+
+void CEDEventReportDlg::OnBnClickedButtonSend()
+{
+	CButton* pButton = (CButton*)GetDlgItem(IDC_RADIO_ENABLE);
+	bool bEnable = pButton->GetCheck() == BST_CHECKED;
+
+	CString strText, strId;
+	GetDlgItemText(IDC_EDIT_CEID, strText);
+	std::vector<int> ids;
+	if (!strText.IsEmpty()) {
+		int i = 0;
+		while (1) {
+			if (!AfxExtractSubString(strId, (LPCTSTR)strText, i++, ',')) {
+				break;
+			}
+			ids.push_back(atoi(strId));
+		}
+	}
+
+
+	theApp.m_model.m_pHsmsActive->hsmsEDEventReport(bEnable, ids);
+}
diff --git a/SourceCode/Bond/EAPSimulator/CEDEventReportDlg.h b/SourceCode/Bond/EAPSimulator/CEDEventReportDlg.h
new file mode 100644
index 0000000..8150dd1
--- /dev/null
+++ b/SourceCode/Bond/EAPSimulator/CEDEventReportDlg.h
@@ -0,0 +1,26 @@
+锘�#pragma once
+
+
+// CEDEventReportDlg 瀵硅瘽妗�
+
+class CEDEventReportDlg : public CDialogEx
+{
+	DECLARE_DYNAMIC(CEDEventReportDlg)
+
+public:
+	CEDEventReportDlg(CWnd* pParent = nullptr);   // 鏍囧噯鏋勯�犲嚱鏁�
+	virtual ~CEDEventReportDlg();
+
+// 瀵硅瘽妗嗘暟鎹�
+#ifdef AFX_DESIGN_TIME
+	enum { IDD = IDD_DIALOG_ED_EVENT_REPORT };
+#endif
+
+protected:
+	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 鏀寔
+
+	DECLARE_MESSAGE_MAP()
+public:
+	virtual BOOL OnInitDialog();
+	afx_msg void OnBnClickedButtonSend();
+};
diff --git a/SourceCode/Bond/EAPSimulator/CHsmsActive.cpp b/SourceCode/Bond/EAPSimulator/CHsmsActive.cpp
new file mode 100644
index 0000000..6d74a5c
--- /dev/null
+++ b/SourceCode/Bond/EAPSimulator/CHsmsActive.cpp
@@ -0,0 +1,286 @@
+#include "pch.h"
+#include "CHsmsActive.h"
+#include "Log.h"
+
+
+CHsmsActive::CHsmsActive()
+{
+	m_listener = {};
+	m_pActive = nullptr;
+	m_nSessionId = 0;
+	m_nSystemByte = 0;
+}
+
+CHsmsActive::~CHsmsActive()
+{
+
+}
+
+void CHsmsActive::setListener(ACTIVEListener listener)
+{
+	m_listener = listener;
+}
+
+int CHsmsActive::init(const char* pszIp, int port)
+{
+	m_strIp = pszIp;
+	m_nPort = port;
+
+	auto onStatusChanged = [&](void* pFrom, ACTIVESTATE state) -> void {
+		if (m_listener.onStateChanged != nullptr) {
+			m_listener.onStateChanged(this, state);
+		}
+
+		if (ACTIVESTATE::NOT_SELECTED == state) {
+			LOGI("Active state changed(NOT_SELECTED).");
+			hsmsSelectRequest();
+		}
+		else if (ACTIVESTATE::SELECTED == state) {
+			LOGI("Active state changed(SELECTED).");
+			hsmsEstablishCommunications();
+		}
+		else if (ACTIVESTATE::NOT_CONNECTED == state) {
+			LOGI("Active state changed(NOT_CONNECTED).");
+			m_pActive->disconnect();
+		}
+	};
+	auto onRecvSysMessage = [&](void* pFrom, IMessage* pMessage) -> void {
+		LOGI("onRecvSysMessage(sessionId:%d, sType:%d).", 
+			pMessage->getHeader()->sessionId, pMessage->getHeader()->sType);
+		TRACE("sessionId:%d, sType:%d\n", pMessage->getHeader()->sessionId, pMessage->getHeader()->sType);
+	};
+
+	auto onError = [&](void* pFrom, int error) -> void {
+		TRACE("onError:%d\n", error);
+	};
+
+	auto onRecvRawData = [&](void* pFrom, const char* pszData, int size) {
+		TRACE("onRec ,vRawData:<0x%x, %d>\n", pszData, size);
+	};
+
+	auto onRecvDataMessage = [&](void* pFrom, IMessage* pMessage) -> void {
+		HEADER* pHeader = pMessage->getHeader();
+		int nStream = (pHeader->stream & 0x7F);
+
+		TRACE("收到消息 S%dF%d================\n", pHeader->stream & 0x7F, pHeader->function);
+		TRACE("Body:%s\n", pMessage->toString());
+		LOGI("onRecvDataMessage(%s).", pMessage->toString());
+
+		if (nStream == 5 && pHeader->function == 1) {
+			// S1F1
+			replyAck(5, 2, pMessage->getHeader()->systemBytes, 0, _T("ACK0"));
+		}
+	};
+
+	ActiveListener listener;
+	listener.funStateChanged = onStatusChanged;
+	listener.funRecvRawData = onRecvRawData;
+	listener.funRecvDataMessage = onRecvDataMessage;
+	listener.funRecvSysMessage = onRecvSysMessage;
+	listener.funError = onError;
+	int nRet = HSMS_CreateActive(m_pActive, _T(""), m_strIp.c_str(), m_nPort);
+	if (nRet == 0 && m_pActive != nullptr) {
+		m_pActive->setListener(listener);
+		m_pActive->connect();
+	}
+
+	return 0;
+}
+
+int CHsmsActive::term()
+{
+	if (m_pActive != nullptr) {
+		::HSMS_DestroyActive(m_pActive);
+		m_pActive = nullptr;
+	}
+
+	return 0;
+}
+
+int CHsmsActive::hsmsSelectRequest()
+{
+	IMessage* pMessage = nullptr;
+	int nRet = HSMS_CreateMessageWithSType(pMessage, MSG_SELECT_REQ, ++m_nSystemByte);
+	m_pActive->sendMessage(pMessage);
+	HSMS_Destroy1Message(pMessage);
+
+	return 0;
+}
+
+int CHsmsActive::hsmsDeselectRequest()
+{
+	IMessage* pMessage = nullptr;
+	int nRet = HSMS_CreateMessageWithSType(pMessage, MSG_DESELECT_REQ, ++m_nSystemByte);
+	m_pActive->sendMessage(pMessage);
+	HSMS_Destroy1Message(pMessage);
+
+	return 0;
+}
+
+int CHsmsActive::hsmsEstablishCommunications()
+{
+	IMessage* pMessage = nullptr;
+	int nRet = HSMS_Create1Message(pMessage, m_nSessionId, 1 | REPLY, 13, ++m_nSystemByte);
+	m_pActive->sendMessage(pMessage);
+	HSMS_Destroy1Message(pMessage);
+
+	return 0;
+}
+
+int CHsmsActive::hsmsAreYouThere()
+{
+	IMessage* pMessage = nullptr;
+	int nRet = HSMS_Create1Message(pMessage, m_nSessionId, 1 | REPLY, 1, ++m_nSystemByte);
+	m_pActive->sendMessage(pMessage);
+	HSMS_Destroy1Message(pMessage);
+
+	return 0;
+}
+
+int CHsmsActive::hsmsDatetimeSync()
+{
+	CTime time = CTime::GetCurrentTime();
+	char szTime[256];
+	sprintf_s(szTime, 256, _T("%4d%02d%02d%02d%02d%02d00"), time.GetYear(),
+		time.GetMonth(), time.GetDay(), time.GetHour(), time.GetMinute(), time.GetSecond());
+
+	IMessage* pMessage = nullptr;
+	int nRet = HSMS_Create1Message(pMessage, m_nSessionId, 2 | REPLY, 31, ++m_nSystemByte);
+	ISECS2Item* pItem = pMessage->getBody();
+	pItem->setString((const char*)szTime, _T("Date time"));
+	m_pActive->sendMessage(pMessage);
+	HSMS_Destroy1Message(pMessage);
+
+	return 0;
+}
+
+int CHsmsActive::hsmsTerminalDisplay(BYTE tid, const char* pszText)
+{
+	char szTid[1];
+	szTid[0] = tid;
+
+	IMessage* pMessage = nullptr;
+	int nRet = HSMS_Create1Message(pMessage, m_nSessionId, 10 | REPLY, 3, ++m_nSystemByte);
+	ISECS2Item* pItem = pMessage->getBody();
+	pItem->addBinaryItem(szTid, 1, _T("TID"));
+	pItem->addItem(pszText, _T("TEXT"));
+	m_pActive->sendMessage(pMessage);
+	HSMS_Destroy1Message(pMessage);
+
+	return 0;
+}
+
+int CHsmsActive::hsmsEDEventReport(bool bEnable, std::vector<int>& ids)
+{
+	IMessage* pMessage = nullptr;
+	int nRet = HSMS_Create1Message(pMessage, m_nSessionId, 2 | REPLY, 37, ++m_nSystemByte);
+	ISECS2Item* pItem = pMessage->getBody();
+	pItem->addBoolItem(bEnable, "CEED");
+	ISECS2Item* pItem2 = pItem->addItem();
+	for (auto item : ids) {
+		pItem2->addU4Item(item, "CEID");
+	}
+	m_pActive->sendMessage(pMessage);
+	HSMS_Destroy1Message(pMessage);
+
+	return 0;
+}
+
+int CHsmsActive::hsmsEDAlarmReport(bool bEnable, unsigned int id)
+{
+	char szEnable[2] = {128, 0};
+
+	IMessage* pMessage = nullptr;
+	int nRet = HSMS_Create1Message(pMessage, m_nSessionId, 5 | REPLY, 3, ++m_nSystemByte);
+	ISECS2Item* pItem = pMessage->getBody();
+	pItem->addBinaryItem(&szEnable[bEnable ? 0 : 1], 1, "ALED");
+	pItem->addU4Item(id, "ALID");
+	m_pActive->sendMessage(pMessage);
+	HSMS_Destroy1Message(pMessage);
+
+	return 0;
+}
+
+int CHsmsActive::hsmsDefineReports(std::map<unsigned int, std::vector<unsigned int>>& mapReport)
+{
+	IMessage* pMessage = nullptr;
+	int nRet = HSMS_Create1Message(pMessage, m_nSessionId, 2 | REPLY, 33, ++m_nSystemByte);
+	ISECS2Item* pItem = pMessage->getBody();
+	pItem->addU4Item(1, "DATAID");
+	ISECS2Item* pItemReportList = pItem->addItem();
+	for (auto item : mapReport) {
+		ISECS2Item* pItemReport = pItemReportList->addItem();
+		pItemReport->addU4Item(item.first, "RPTID");
+		ISECS2Item* pItemVidList = pItemReport->addItem();
+		for (auto vid : item.second) {
+			pItemVidList->addU4Item(vid, "VID");
+		}
+	}
+	m_pActive->sendMessage(pMessage);
+	HSMS_Destroy1Message(pMessage);
+
+	return 0;
+}
+
+int CHsmsActive::hsmsLinkEventReport(std::map<unsigned int, std::vector<unsigned int>>& mapEvent)
+{
+	if (mapEvent.empty()) return 0;
+
+	IMessage* pMessage = nullptr;
+	int nRet = HSMS_Create1Message(pMessage, m_nSessionId, 2 | REPLY, 35, ++m_nSystemByte);
+	ISECS2Item* pItem = pMessage->getBody();
+	pItem->addU4Item(1, "DATAID");
+	ISECS2Item* pItemEventList = pItem->addItem();
+	for (auto item : mapEvent) {
+		ISECS2Item* pItemEvent = pItemEventList->addItem();
+		pItemEvent->addU4Item(item.first, "CEID");
+		ISECS2Item* pItemRptidList = pItemEvent->addItem();
+		for (auto vid : item.second) {
+			pItemRptidList->addU4Item(vid, "RPTID");
+		}
+	}
+	m_pActive->sendMessage(pMessage);
+	HSMS_Destroy1Message(pMessage);
+
+	return 0;
+}
+
+int CHsmsActive::hsmsConfigureSpooling(std::map<unsigned int, std::set<unsigned int>>& spoolingConfig)
+{
+	IMessage* pMessage = nullptr;
+	int nRet = HSMS_Create1Message(pMessage, m_nSessionId, 2 | REPLY, 43, ++m_nSystemByte);
+	if (spoolingConfig.size() > 0) {
+		for (auto s : spoolingConfig) {
+			ISECS2Item* pItemStreamList = pMessage->getBody()->addItem();
+			pItemStreamList->addU1Item(s.first, "STRID");
+			ISECS2Item* pItemFcnList = pItemStreamList->addItem();
+			for (auto f : s.second) {
+				pItemFcnList->addU1Item(f, "FCNID");
+			}
+		}
+	}
+
+	m_pActive->sendMessage(pMessage);
+	HSMS_Destroy1Message(pMessage);
+
+	return 0;
+}
+
+int CHsmsActive::replyAck0(IMessage* pMessage)
+{
+	return 0;
+}
+
+// 通用的reply ack函数
+void CHsmsActive::replyAck(int s, int f, unsigned int systemBytes, BYTE ack, const char* pszAckName)
+{
+	IMessage* pMessage = NULL;
+	HSMS_Create1Message(pMessage, m_nSessionId, s, f, systemBytes);
+	ASSERT(pMessage);
+	ISECS2Item* pItem = pMessage->getBody();
+	pItem->setBinary((const char*)&ack, 1, pszAckName);
+	m_pActive->sendMessage(pMessage);
+	LOGI("<HSMS>[SECS Msg SEND]S%dF%d (SysByte=%u)", s, f, systemBytes);
+	HSMS_Destroy1Message(pMessage);
+}
+
diff --git a/SourceCode/Bond/EAPSimulator/CHsmsActive.h b/SourceCode/Bond/EAPSimulator/CHsmsActive.h
new file mode 100644
index 0000000..e171c75
--- /dev/null
+++ b/SourceCode/Bond/EAPSimulator/CHsmsActive.h
@@ -0,0 +1,74 @@
+#pragma once
+#include <string>
+#include <vector>
+#include <map>
+#include <set>
+#include "CCollectionEvent.h"
+
+
+typedef std::function<void(void* pFrom, ACTIVESTATE state)> STATECHANGED;
+typedef struct _ACTIVEListener
+{
+	STATECHANGED			onStateChanged;
+} ACTIVEListener;
+
+class CHsmsActive
+{
+public:
+	CHsmsActive();
+	~CHsmsActive();
+
+public:
+	void setListener(ACTIVEListener listener);
+	int init(const char* pszIp, int port);
+	int term();
+
+public:
+	// Select
+	int hsmsSelectRequest();
+
+	// Deselect Request
+	int hsmsDeselectRequest();
+
+	// 建立通讯(S1F13)
+	int hsmsEstablishCommunications();
+
+	// Are You There
+	int hsmsAreYouThere();
+
+	// Date time sync
+	int hsmsDatetimeSync();
+
+	// terminal display
+	int hsmsTerminalDisplay(BYTE tid, const char* pszText);
+
+	// Enable/Disable Event Report
+	int hsmsEDEventReport(bool bEnable, std::vector<int>& ids);
+
+	// Enable/Disable Alarm Report
+	int hsmsEDAlarmReport(bool bEnable, unsigned int id);
+
+	// Define reports
+	int hsmsDefineReports(std::map<unsigned int, std::vector<unsigned int>>& mapReport);
+	
+	// Line Event Report
+	int hsmsLinkEventReport(std::map<unsigned int, std::vector<unsigned int>>& mapEvent);
+
+	// Configure Spooling
+	int hsmsConfigureSpooling(std::map<unsigned int, std::set<unsigned int>>& spoolingConfig);
+
+	// 通过的reply函数
+	void replyAck(int s, int f, unsigned int systemBytes, BYTE ack, const char* pszAckName);
+
+	// reply ack0
+	int replyAck0(IMessage* pMessage);
+
+private:
+	ACTIVEListener m_listener;
+	IActive* m_pActive;
+	std::string m_strIp;
+	int m_nPort;
+	unsigned short m_nSessionId;
+	unsigned int m_nSystemByte;
+};
+
diff --git a/SourceCode/Bond/EAPSimulator/CLinkReportDetailDlg.cpp b/SourceCode/Bond/EAPSimulator/CLinkReportDetailDlg.cpp
new file mode 100644
index 0000000..dc2c082
--- /dev/null
+++ b/SourceCode/Bond/EAPSimulator/CLinkReportDetailDlg.cpp
@@ -0,0 +1,65 @@
+锘�// CLinkReportDetailDlg.cpp: 瀹炵幇鏂囦欢
+//
+
+#include "pch.h"
+#include "EAPSimulator.h"
+#include "CLinkReportDetailDlg.h"
+#include "afxdialogex.h"
+
+
+// CLinkReportDetailDlg 瀵硅瘽妗�
+
+IMPLEMENT_DYNAMIC(CLinkReportDetailDlg, CDialogEx)
+
+CLinkReportDetailDlg::CLinkReportDetailDlg(CWnd* pParent /*=nullptr*/)
+	: CDialogEx(IDD_DIALOG_LINK_REPORT_DETAIL, pParent)
+{
+	m_pEvent = nullptr;
+}
+
+CLinkReportDetailDlg::~CLinkReportDetailDlg()
+{
+}
+
+void CLinkReportDetailDlg::DoDataExchange(CDataExchange* pDX)
+{
+	CDialogEx::DoDataExchange(pDX);
+}
+
+
+BEGIN_MESSAGE_MAP(CLinkReportDetailDlg, CDialogEx)
+	ON_BN_CLICKED(IDOK, &CLinkReportDetailDlg::OnBnClickedOk)
+END_MESSAGE_MAP()
+
+
+// CLinkReportDetailDlg 娑堟伅澶勭悊绋嬪簭
+
+void CLinkReportDetailDlg::SetCollectionEvent(SERVO::CCollectionEvent* pEvent)
+{
+	m_pEvent = pEvent;
+}
+
+BOOL CLinkReportDetailDlg::OnInitDialog()
+{
+	CDialogEx::OnInitDialog();
+
+	
+	ASSERT(m_pEvent);
+	SetDlgItemInt(IDC_EDIT_CEID, m_pEvent->getEventId());
+	SetDlgItemText(IDC_EDIT_CE_NAME, m_pEvent->getName().c_str());
+	SetDlgItemText(IDC_EDIT_CE_DESCRIPTIONS, m_pEvent->getDescription().c_str());
+	SetDlgItemText(IDC_EDIT_CE_RPTID, m_pEvent->getReportIdsText().c_str());
+
+	return TRUE;  // return TRUE unless you set the focus to a control
+				  // 寮傚父: OCX 灞炴�ч〉搴旇繑鍥� FALSE
+}
+
+void CLinkReportDetailDlg::OnBnClickedOk()
+{
+	ASSERT(m_pEvent);
+
+	UINT RPTID = GetDlgItemInt(IDC_EDIT_CE_RPTID);
+	m_pEvent->setReport(RPTID);
+
+	CDialogEx::OnOK();
+}
diff --git a/SourceCode/Bond/EAPSimulator/CLinkReportDetailDlg.h b/SourceCode/Bond/EAPSimulator/CLinkReportDetailDlg.h
new file mode 100644
index 0000000..db98f5d
--- /dev/null
+++ b/SourceCode/Bond/EAPSimulator/CLinkReportDetailDlg.h
@@ -0,0 +1,31 @@
+锘�#pragma once
+#include "CCollectionEvent.h"
+
+
+// CLinkReportDetailDlg 瀵硅瘽妗�
+
+class CLinkReportDetailDlg : public CDialogEx
+{
+	DECLARE_DYNAMIC(CLinkReportDetailDlg)
+
+public:
+	CLinkReportDetailDlg(CWnd* pParent = nullptr);   // 鏍囧噯鏋勯�犲嚱鏁�
+	virtual ~CLinkReportDetailDlg();
+	void SetCollectionEvent(SERVO::CCollectionEvent* pEvent);
+
+private:
+	SERVO::CCollectionEvent* m_pEvent;
+
+// 瀵硅瘽妗嗘暟鎹�
+#ifdef AFX_DESIGN_TIME
+	enum { IDD = IDD_DIALOG_LINK_REPORT_DETAIL };
+#endif
+
+protected:
+	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 鏀寔
+
+	DECLARE_MESSAGE_MAP()
+public:
+	virtual BOOL OnInitDialog();
+	afx_msg void OnBnClickedOk();
+};
diff --git a/SourceCode/Bond/EAPSimulator/CLinkReportDlg.cpp b/SourceCode/Bond/EAPSimulator/CLinkReportDlg.cpp
new file mode 100644
index 0000000..5655fa1
--- /dev/null
+++ b/SourceCode/Bond/EAPSimulator/CLinkReportDlg.cpp
@@ -0,0 +1,205 @@
+锘�// CLinkReportDlg.cpp: 瀹炵幇鏂囦欢
+//
+
+#include "pch.h"
+#include "EAPSimulator.h"
+#include "CLinkReportDlg.h"
+#include "afxdialogex.h"
+#include <string.h>  
+#include <regex>
+#include "CLinkReportDetailDlg.h"
+
+
+// CLinkReportDlg 瀵硅瘽妗�
+
+IMPLEMENT_DYNAMIC(CLinkReportDlg, CDialogEx)
+
+CLinkReportDlg::CLinkReportDlg(CWnd* pParent /*=nullptr*/)
+	: CDialogEx(IDD_DIALOG_LINK_REPORT, pParent)
+{
+
+}
+
+CLinkReportDlg::~CLinkReportDlg()
+{
+}
+
+void CLinkReportDlg::DoDataExchange(CDataExchange* pDX)
+{
+	CDialogEx::DoDataExchange(pDX);
+}
+
+
+BEGIN_MESSAGE_MAP(CLinkReportDlg, CDialogEx)
+	ON_NOTIFY(NM_DBLCLK, IDC_LIST1, &CLinkReportDlg::OnListCtrlDoubleClick)
+	ON_BN_CLICKED(IDC_BUTTON_SEND, &CLinkReportDlg::OnBnClickedButtonSend)
+	ON_WM_DESTROY()
+END_MESSAGE_MAP()
+
+
+// CLinkReportDlg 娑堟伅澶勭悊绋嬪簭
+BOOL CLinkReportDlg::OnInitDialog()
+{
+	CDialogEx::OnInitDialog();
+
+	CListCtrl* pListCtrl = (CListCtrl*)GetDlgItem(IDC_LIST1);
+	DWORD dwStyle = pListCtrl->GetExtendedStyle();
+	dwStyle |= LVS_EX_FULLROWSELECT;
+	dwStyle |= LVS_EX_GRIDLINES;
+	pListCtrl->SetExtendedStyle(dwStyle);
+	pListCtrl->ModifyStyle(0, LVS_SHOWSELALWAYS);
+
+	HIMAGELIST imageList = ImageList_Create(24, 24, ILC_COLOR24, 1, 1);
+	ListView_SetImageList(pListCtrl->GetSafeHwnd(), imageList, LVSIL_SMALL);
+	pListCtrl->InsertColumn(0, _T(""), LVCFMT_RIGHT, 0);
+	pListCtrl->InsertColumn(1, _T("CEID"), LVCFMT_LEFT, 120);
+	pListCtrl->InsertColumn(2, _T("CD Name"), LVCFMT_LEFT, 120);
+	pListCtrl->InsertColumn(3, _T("Descriptions"), LVCFMT_LEFT, 180);
+	pListCtrl->InsertColumn(4, _T("Attached RPTID"), LVCFMT_LEFT, 120);
+	pListCtrl->SetColumnWidth(4, LVSCW_AUTOSIZE_USEHEADER);
+
+
+	CString strFile;
+	strFile.Format(_T("%s\\CollectionEventList.txt"), (LPTSTR)(LPCTSTR)theApp.m_strAppDir);
+	loadCollectionEvents((LPTSTR)(LPCTSTR)strFile);
+
+	for (auto item : m_collectionEvents) {
+		int index = pListCtrl->InsertItem(pListCtrl->GetItemCount(), _T(""));
+		pListCtrl->SetItemData(index, (DWORD_PTR)item);
+		pListCtrl->SetItemText(index, 1, std::to_string(item->getEventId()).c_str());
+		pListCtrl->SetItemText(index, 2, item->getName().c_str());
+		pListCtrl->SetItemText(index, 3, item->getDescription().c_str());
+		pListCtrl->SetItemText(index, 4, item->getReportIdsText().c_str());
+	}
+
+
+	return TRUE;  // return TRUE unless you set the focus to a control
+				  // 寮傚父: OCX 灞炴�ч〉搴旇繑鍥� FALSE
+}
+
+int CLinkReportDlg::loadCollectionEvents(const char* pszFilepath)
+{
+	CStdioFile file;
+	if (!file.Open(pszFilepath, CFile::modeRead)) {
+		return -1;
+	}
+
+	std::regex pattern("^\\d+,[^,]*,[^,]*,\\(\\d+(,\\d+)*\\).*");  // 鍖归厤浠ユ暟瀛�+閫楀彿寮�澶寸殑瀛楃涓�
+	std::vector<SERVO::CCollectionEvent*> events;
+	int index, last;
+	CString strLine, strRPTIDs;
+	CString strId, strName, strDescription;
+	while (file.ReadString(strLine)) {
+		if (!std::regex_match((LPTSTR)(LPCTSTR)strLine, pattern)) {
+			continue;
+		}
+
+		last = 0;
+		index = strLine.Find(",", last);
+		if (index < 0) continue;
+		strId = strLine.Left(index);
+		last = index + 1;
+
+		index = strLine.Find(",", last);
+		if (index < 0) continue;
+		strName = strLine.Mid(last, index - last);
+		last = index + 1;
+
+		index = strLine.Find(",", last);
+		if (index < 0) continue;
+		strDescription = strLine.Mid(last, index - last);
+		strRPTIDs = strLine.Right(strLine.GetLength() - index - 1);
+		strRPTIDs.Delete(0);
+		strRPTIDs.Delete(strRPTIDs.GetLength() - 1);
+		auto prtids = parseVidList(strRPTIDs);
+
+		SERVO::CCollectionEvent* pEvent = new SERVO::CCollectionEvent(
+			atoi(strId), (LPTSTR)(LPCTSTR)strName, (LPTSTR)(LPCTSTR)strDescription, prtids);
+		events.push_back(pEvent);
+	}
+
+	if (!events.empty()) {
+		clearAllCollectionEvent();
+		for (auto item : events) {
+			m_collectionEvents.push_back(item);
+		}
+	}
+
+
+	file.Close();
+	return 0;
+}
+
+std::vector<unsigned int> CLinkReportDlg::parseVidList(CString& strNums)
+{
+	// 1. 鍏堝幓鎺夊彲鑳藉嚭鐜扮殑绌虹櫧绗︼紙绌烘牸銆佸埗琛ㄧ绛夛級
+	strNums.Trim();
+
+	// 2锔�.
+	std::vector<unsigned int> result;
+	int i = 0;
+	CString strVid;
+	while (1) {
+		if (!AfxExtractSubString(strVid, (LPCTSTR)strNums, i, ',')) {
+			break;
+		}
+		if (!strVid.IsEmpty())                 // 闃插尽鎬ф鏌�
+			result.push_back(std::stoi((LPTSTR)(LPCTSTR)strVid));
+		i++;
+
+	}
+
+	return result;
+}
+
+void CLinkReportDlg::clearAllCollectionEvent()
+{
+	for (auto item : m_collectionEvents) {
+		delete item;
+	}
+	m_collectionEvents.clear();
+}
+
+void CLinkReportDlg::OnListCtrlDoubleClick(NMHDR* pNMHDR, LRESULT* pResult)
+{
+	LPNMITEMACTIVATE pNMItem = (LPNMITEMACTIVATE)pNMHDR;
+	int nItem = pNMItem->iItem;
+	if (nItem >= 0) {
+		CListCtrl* pListCtrl = (CListCtrl*)GetDlgItem(IDC_LIST1);
+		SERVO::CCollectionEvent* pEvent = (SERVO::CCollectionEvent*)pListCtrl->GetItemData(nItem);
+		CLinkReportDetailDlg dlg;
+		dlg.SetCollectionEvent(pEvent);
+		if (IDOK == dlg.DoModal()) {
+			pListCtrl->SetItemText(nItem, 4, pEvent->getReportIdsText().c_str());
+		}
+	}
+
+	*pResult = 0;
+}
+
+void CLinkReportDlg::OnBnClickedButtonSend()
+{
+	std::vector<SERVO::CCollectionEvent*> events;
+	CListCtrl* pListCtrl = (CListCtrl*)GetDlgItem(IDC_LIST1);
+	POSITION pos = pListCtrl->GetFirstSelectedItemPosition();
+	while (pos) {
+		int nItem = pListCtrl->GetNextSelectedItem(pos);
+		SERVO::CCollectionEvent* pEvent = (SERVO::CCollectionEvent*)pListCtrl->GetItemData(nItem);
+		events.push_back(pEvent);
+	}
+
+	std::map<unsigned int, std::vector<unsigned int>> mapEvent;
+	for (auto item : events) {
+		std::vector<unsigned int> RPTIDs = item->getReportIds();
+		mapEvent[item->getEventId()] = RPTIDs;
+	}
+
+
+	theApp.m_model.m_pHsmsActive->hsmsLinkEventReport(mapEvent);
+}
+
+void CLinkReportDlg::OnDestroy()
+{
+	CDialogEx::OnDestroy();
+	clearAllCollectionEvent();
+}
diff --git a/SourceCode/Bond/EAPSimulator/CLinkReportDlg.h b/SourceCode/Bond/EAPSimulator/CLinkReportDlg.h
new file mode 100644
index 0000000..434a28c
--- /dev/null
+++ b/SourceCode/Bond/EAPSimulator/CLinkReportDlg.h
@@ -0,0 +1,36 @@
+锘�#pragma once
+#include "CCollectionEvent.h"
+
+
+// CLinkReportDlg 瀵硅瘽妗�
+
+class CLinkReportDlg : public CDialogEx
+{
+	DECLARE_DYNAMIC(CLinkReportDlg)
+
+public:
+	CLinkReportDlg(CWnd* pParent = nullptr);   // 鏍囧噯鏋勯�犲嚱鏁�
+	virtual ~CLinkReportDlg();
+	int loadCollectionEvents(const char* pszFilepath);
+	std::vector<unsigned int> parseVidList(CString& strNums);
+	void clearAllCollectionEvent();
+
+
+private:
+	std::vector<SERVO::CCollectionEvent*> m_collectionEvents;
+
+// 瀵硅瘽妗嗘暟鎹�
+#ifdef AFX_DESIGN_TIME
+	enum { IDD = IDD_DIALOG_LINK_REPORT };
+#endif
+
+protected:
+	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 鏀寔
+
+	DECLARE_MESSAGE_MAP()
+public:
+	virtual BOOL OnInitDialog();
+	afx_msg void OnListCtrlDoubleClick(NMHDR* pNMHDR, LRESULT* pResult);
+	afx_msg void OnBnClickedButtonSend();
+	afx_msg void OnDestroy();
+};
diff --git a/SourceCode/Bond/EAPSimulator/CModel.cpp b/SourceCode/Bond/EAPSimulator/CModel.cpp
new file mode 100644
index 0000000..1772e10
--- /dev/null
+++ b/SourceCode/Bond/EAPSimulator/CModel.cpp
@@ -0,0 +1,300 @@
+#include "pch.h"
+#include "CModel.h"
+#include "Log.h"
+#include "Common.h"
+
+
+CModel::CModel()
+{
+	m_pObservableEmitter = nullptr;
+	m_pObservable = nullptr;
+	m_pHsmsActive = nullptr;
+}
+
+CModel::~CModel()
+{
+}
+
+IObservable* CModel::getObservable()
+{
+	if (m_pObservable == nullptr) {
+		m_pObservable = RX_AllocaObservable([&](IObservableEmitter* e) -> void {
+			m_pObservableEmitter = e;			// 保存发射器
+			});
+	}
+
+	return m_pObservable;
+}
+
+void CModel::setWorkDir(const char* pszWorkDir)
+{
+	m_strWorkDir = pszWorkDir;
+}
+
+int CModel::init()
+{
+	CString strIniFile;
+
+
+
+	// Log
+	CString strLogDir;
+	strLogDir.Format(_T("%s\\Log"), (LPTSTR)(LPCTSTR)m_strWorkDir);
+	::CreateDirectory(strLogDir, NULL);
+	CLog::GetLog()->SetOnLogCallback([&](int level, const char* pszMessage) -> void {
+		notifyTextAndInt(RX_CODE_LOG, pszMessage, level);
+		});
+	CLog::GetLog()->SetAutoAppendTimeString(TRUE);
+	CLog::GetLog()->SetOutputTarget(OT_FILE);
+	CLog::GetLog()->SetLogsDir(strLogDir);
+	CLog::GetLog()->SetEquipmentId(_T("EAP"));
+	LOGI("\r\n\r\n~~~ Prog Start! ~~~");
+
+
+	return 0;
+}
+
+int CModel::term()
+{
+	CLog::GetLog()->SetOnLogCallback(nullptr);
+	if (m_pHsmsActive != nullptr) {
+		m_pHsmsActive->term();
+		delete m_pHsmsActive;
+	}
+
+	return 0;
+}
+
+int CModel::connectEq(const char* pszIp, int port)
+{
+	if (m_pHsmsActive != nullptr) {
+		m_pHsmsActive->term();
+		delete m_pHsmsActive;
+	}
+
+	ACTIVEListener listener;
+	listener.onStateChanged = [&](void* pFrom, ACTIVESTATE state) -> void {
+		notifyInt(RX_CODE_ACTIVE_STATUS_CHANGED, (int)state);
+	};
+
+	m_pHsmsActive = new CHsmsActive();
+	m_pHsmsActive->setListener(listener);
+	m_pHsmsActive->init(pszIp, port);
+	return 0;
+}
+
+int CModel::disconnect()
+{
+	if (m_pHsmsActive == nullptr) {
+		return -1;
+	}
+
+	m_pHsmsActive->hsmsDeselectRequest();
+	return 0;
+}
+
+int CModel::notify(int code)
+{
+	/* code */
+	if (m_pObservableEmitter != NULL) {
+		IAny* pAny = RX_AllocaAny();
+		if (pAny != NULL) {
+			pAny->addRef();
+			pAny->setCode(code);
+			m_pObservableEmitter->onNext(pAny);
+			pAny->release();
+		}
+	}
+
+	return 1;
+}
+
+int CModel::notifyPtr(int code, void* ptr/* = NULL*/)
+{
+	/* code */
+	if (m_pObservableEmitter != NULL) {
+		IAny* pAny = RX_AllocaAny();
+		if (pAny != NULL) {
+			pAny->addRef();
+			pAny->setCode(code);
+			pAny->setPtrValue("ptr", ptr);
+			m_pObservableEmitter->onNext(pAny);
+			pAny->release();
+		}
+	}
+
+	return 1;
+}
+
+int CModel::notifyObj(int code, IRxObject* pObj)
+{
+	/* code */
+	if (m_pObservableEmitter != NULL) {
+		IAny* pAny = RX_AllocaAny();
+		if (pAny != NULL) {
+			pAny->addRef();
+			pAny->setCode(code);
+			pAny->setObject("obj", pObj);
+			m_pObservableEmitter->onNext(pAny);
+			pAny->release();
+		}
+	}
+
+	return 1;
+}
+
+int CModel::notifyObjAndPtr(int code, IRxObject* pObj, void* ptr)
+{
+	/* code */
+	if (m_pObservableEmitter != NULL) {
+		IAny* pAny = RX_AllocaAny();
+		if (pAny != NULL) {
+			pAny->addRef();
+			pAny->setCode(code);
+			pAny->setObject("obj", pObj);
+			pAny->setPtrValue("ptr", ptr);
+			m_pObservableEmitter->onNext(pAny);
+			pAny->release();
+		}
+	}
+
+	return 1;
+}
+
+int CModel::notifyInt(int code, int exCode)
+{
+	if (m_pObservableEmitter != NULL) {
+		IAny* pAny = RX_AllocaAny();
+		if (pAny != NULL) {
+			pAny->addRef();
+			pAny->setCode(code);
+			pAny->setIntValue("exCode", exCode);
+			m_pObservableEmitter->onNext(pAny);
+			pAny->release();
+		}
+	}
+
+	return 0;
+}
+
+int CModel::notifyInt2(int code, int exCode, int exCode2)
+{
+	if (m_pObservableEmitter != NULL) {
+		IAny* pAny = RX_AllocaAny();
+		if (pAny != NULL) {
+			pAny->addRef();
+			pAny->setCode(code);
+			pAny->setIntValue("exCode", exCode);
+			pAny->setIntValue("exCode2", exCode2);
+			m_pObservableEmitter->onNext(pAny);
+			pAny->release();
+		}
+	}
+
+	return 0;
+}
+
+int CModel::notifyDouble(int code, double dValue)
+{
+	if (m_pObservableEmitter != NULL) {
+		IAny* pAny = RX_AllocaAny();
+		if (pAny != NULL) {
+			pAny->addRef();
+			pAny->setCode(code);
+			pAny->setDoubleValue("value", dValue);
+			m_pObservableEmitter->onNext(pAny);
+			pAny->release();
+		}
+	}
+
+	return 0;
+}
+
+int CModel::notifyObjAndInt(int code, IRxObject* pObj1, IRxObject* pObj2, int exCode)
+{
+	if (m_pObservableEmitter != NULL) {
+		IAny* pAny = RX_AllocaAny();
+		if (pAny != NULL) {
+			pAny->addRef();
+			pAny->setCode(code);
+			if (pObj1 != nullptr) pAny->setObject("obj", pObj1);
+			if (pObj2 != nullptr) pAny->setObject("obj2", pObj2);
+			pAny->setIntValue("exCode", exCode);
+			m_pObservableEmitter->onNext(pAny);
+			pAny->release();
+		}
+	}
+
+	return 0;
+}
+
+int CModel::notifyText(int code, const char* pszText)
+{
+	if (m_pObservableEmitter != NULL) {
+		IAny* pAny = RX_AllocaAny();
+		if (pAny != NULL) {
+			pAny->addRef();
+			pAny->setCode(code);
+			pAny->setStringValue("text", pszText);
+			m_pObservableEmitter->onNext(pAny);
+			pAny->release();
+		}
+	}
+
+	return 0;
+}
+
+int CModel::notifyTextAndInt(int code, const char* pszText, int exCode)
+{
+	if (m_pObservableEmitter != NULL) {
+		IAny* pAny = RX_AllocaAny();
+		if (pAny != NULL) {
+			pAny->addRef();
+			pAny->setCode(code);
+			pAny->setStringValue("text", pszText);
+			pAny->setIntValue("exCode", exCode);
+			m_pObservableEmitter->onNext(pAny);
+			pAny->release();
+		}
+	}
+
+	return 0;
+}
+
+int CModel::notifyPtrAndInt(int code, void* ptr1, void* ptr2, int exCode)
+{
+	if (m_pObservableEmitter != NULL) {
+		IAny* pAny = RX_AllocaAny();
+		if (pAny != NULL) {
+			pAny->addRef();
+			pAny->setCode(code);
+			pAny->setPtrValue("ptr", ptr1);
+			pAny->setPtrValue("ptr1", ptr1);
+			pAny->setPtrValue("ptr2", ptr2);
+			pAny->setIntValue("exCode", exCode);
+			m_pObservableEmitter->onNext(pAny);
+			pAny->release();
+		}
+	}
+
+	return 0;
+}
+
+int CModel::notifyMesMsg(int code, int stream, int function, const char* pszText)
+{
+	if (m_pObservableEmitter != NULL) {
+		IAny* pAny = RX_AllocaAny();
+		if (pAny != NULL) {
+			pAny->addRef();
+			pAny->setCode(code);
+			pAny->setIntValue("stream", stream);
+			pAny->setIntValue("function", function);
+			pAny->setStringValue("text", pszText);
+			m_pObservableEmitter->onNext(pAny);
+			pAny->release();
+		}
+	}
+
+	return 0;
+}
+
diff --git a/SourceCode/Bond/EAPSimulator/CModel.h b/SourceCode/Bond/EAPSimulator/CModel.h
new file mode 100644
index 0000000..8b547fe
--- /dev/null
+++ b/SourceCode/Bond/EAPSimulator/CModel.h
@@ -0,0 +1,43 @@
+#pragma once
+#include "CHsmsActive.h"
+
+class CModel
+{
+public:
+	CModel();
+	~CModel();
+
+public:
+	IObservable* getObservable();
+	void setWorkDir(const char* pszWorkDir);
+	int init();
+	int term();
+	int connectEq(const char* pszIp, int port);
+	int disconnect();
+
+public:
+	int notify(int code);
+	int notifyPtr(int code, void* ptr = NULL);
+	int notifyObj(int code, IRxObject* pObj);
+	int notifyObjAndPtr(int code, IRxObject* pObj, void* ptr);
+	int notifyObjAndInt(int code, IRxObject* pObj1, IRxObject* pObj2, int exCode);
+	int notifyInt(int code, int exCode);
+	int notifyInt2(int code, int exCode, int exCode2);
+	int notifyDouble(int code, double dValue);
+	int notifyText(int code, const char* pszText);
+	int notifyPtrAndInt(int code, void* ptr1, void* ptr2, int exCode);
+	int notifyTextAndInt(int code, const char* pszText, int exCode);
+	int notifyMesMsg(int code, int stream, int function, const char* pszText);
+
+public:
+	CHsmsActive* m_pHsmsActive;
+
+private:
+	IObservable* m_pObservable;
+	IObservableEmitter* m_pObservableEmitter;
+	CString m_strWorkDir;
+	CString m_strDataDir;
+};
+
+
+
diff --git a/SourceCode/Bond/EAPSimulator/CReport.cpp b/SourceCode/Bond/EAPSimulator/CReport.cpp
new file mode 100644
index 0000000..d5bc103
--- /dev/null
+++ b/SourceCode/Bond/EAPSimulator/CReport.cpp
@@ -0,0 +1,98 @@
+#include "pch.h"
+#include "CReport.h"
+
+
+namespace SERVO {
+	CReport::CReport()
+	{
+		m_nReportId = 0;
+	}
+
+	CReport::CReport(unsigned int reportId, std::vector<unsigned int>& vids)
+	{
+		m_nReportId = reportId;
+		for (auto vid : vids) {
+			m_vids.push_back(vid);
+		}
+	}
+
+	CReport::~CReport()
+	{
+
+	}
+
+	unsigned int CReport::getReportId()
+	{
+		return m_nReportId;
+	}
+
+	BOOL CReport::addVariable(CVariable* pVariable)
+	{
+		ASSERT(pVariable);
+		if (getVariable(pVariable->getVarialbleId()) != nullptr) {
+			return FALSE;
+		}
+
+		m_variabels.push_back(pVariable);
+		return TRUE;
+	}
+
+	BOOL CReport::deleteVarialble(unsigned int nVarialbleId)
+	{
+		BOOL bDelete = FALSE;
+		for (auto iter = m_variabels.begin(); iter != m_variabels.end(); ++iter) {
+			if (nVarialbleId == (*iter)->getVarialbleId()) {
+				m_variabels.erase(iter);
+				bDelete = TRUE;
+				break;
+			}
+		}
+
+		return bDelete;
+	}
+
+	CVariable* CReport::getVariable(unsigned int nVarialbleId)
+	{
+		for (auto item : m_variabels) {
+			if (nVarialbleId == item->getVarialbleId()) {
+				return item;
+			}
+		}
+
+		return nullptr;
+	}
+
+	std::vector<CVariable*>& CReport::getVariables()
+	{
+		return m_variabels;
+	}
+
+	std::string CReport::getVariablesIdsText()
+	{
+		std::string strResult, strName;
+		for (int i = 0; i < m_vids.size(); i++) {
+			strResult += std::to_string(m_vids[i]);
+			strResult += "(";
+			strResult += (getVariableName(m_vids[i], strName) ?
+				strName : _T("null"));
+			strResult += ")";
+			if (i != m_vids.size() - 1) {
+				strResult += ",";
+			}
+		}
+
+		return strResult;
+	}
+
+	bool CReport::getVariableName(unsigned int vid, std::string& strName)
+	{
+		for (auto item : m_variabels) {
+			if (item->getVarialbleId() == vid) {
+				strName = item->getName();
+				return true;
+			}
+		}
+
+		return false;
+	}
+}
diff --git a/SourceCode/Bond/EAPSimulator/CReport.h b/SourceCode/Bond/EAPSimulator/CReport.h
new file mode 100644
index 0000000..191d539
--- /dev/null
+++ b/SourceCode/Bond/EAPSimulator/CReport.h
@@ -0,0 +1,28 @@
+#pragma once
+#include "CVariable.h"
+#include <vector>
+
+namespace SERVO {
+	class CReport
+	{
+	public:
+		CReport();
+		CReport(unsigned int reportId, std::vector<unsigned int>& vids);
+		virtual ~CReport();
+
+	public:
+		unsigned int getReportId();
+		BOOL addVariable(CVariable* pVariable);
+		BOOL deleteVarialble(unsigned int nVarialbleId);
+		CVariable* getVariable(unsigned int nVarialbleId);
+		std::vector<CVariable*>& getVariables();
+		std::string getVariablesIdsText();
+		bool getVariableName(unsigned int vid, std::string& strName);
+
+	private:
+		unsigned int m_nReportId;
+		std::vector<unsigned int> m_vids;
+		std::vector<CVariable*> m_variabels;
+	};
+}
+
diff --git a/SourceCode/Bond/EAPSimulator/CTerminalDisplayDlg.cpp b/SourceCode/Bond/EAPSimulator/CTerminalDisplayDlg.cpp
new file mode 100644
index 0000000..50cfe62
--- /dev/null
+++ b/SourceCode/Bond/EAPSimulator/CTerminalDisplayDlg.cpp
@@ -0,0 +1,73 @@
+锘�// CTerminalDisplayDlg.cpp: 瀹炵幇鏂囦欢
+//
+
+#include "pch.h"
+#include "EAPSimulator.h"
+#include "CTerminalDisplayDlg.h"
+#include "afxdialogex.h"
+
+
+// CTerminalDisplayDlg 瀵硅瘽妗�
+
+IMPLEMENT_DYNAMIC(CTerminalDisplayDlg, CDialogEx)
+
+CTerminalDisplayDlg::CTerminalDisplayDlg(CWnd* pParent /*=nullptr*/)
+	: CDialogEx(IDD_DIALOG_TERMINAL_DISPLAY, pParent)
+{
+
+}
+
+CTerminalDisplayDlg::~CTerminalDisplayDlg()
+{
+}
+
+void CTerminalDisplayDlg::DoDataExchange(CDataExchange* pDX)
+{
+	CDialogEx::DoDataExchange(pDX);
+}
+
+
+BEGIN_MESSAGE_MAP(CTerminalDisplayDlg, CDialogEx)
+	ON_EN_CHANGE(IDC_EDIT_TEXT, &CTerminalDisplayDlg::OnEnChangeEditText)
+	ON_BN_CLICKED(IDC_BUTTON_SEND, &CTerminalDisplayDlg::OnBnClickedButtonSend)
+END_MESSAGE_MAP()
+
+
+// CTerminalDisplayDlg 娑堟伅澶勭悊绋嬪簭
+
+
+BOOL CTerminalDisplayDlg::OnInitDialog()
+{
+	CDialogEx::OnInitDialog();
+
+	
+	// 娣诲姞缁堢id
+	CComboBox* pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_TID);
+	pComboBox->InsertString(0, _T("0(鍏ㄩ儴)"));
+	pComboBox->InsertString(1, _T("1(缁堢1)"));
+	pComboBox->InsertString(2, _T("2(缁堢2)"));
+	pComboBox->InsertString(3, _T("3(缁堢3)"));
+	pComboBox->InsertString(4, _T("4(缁堢4)"));
+	pComboBox->SetCurSel(0);
+
+
+	return TRUE;  // return TRUE unless you set the focus to a control
+				  // 寮傚父: OCX 灞炴�ч〉搴旇繑鍥� FALSE
+}
+
+void CTerminalDisplayDlg::OnEnChangeEditText()
+{
+	CString strText;
+	GetDlgItemText(IDC_EDIT_TEXT, strText);
+	GetDlgItem(IDC_BUTTON_SEND)->EnableWindow(!strText.IsEmpty());
+}
+
+void CTerminalDisplayDlg::OnBnClickedButtonSend()
+{
+	CComboBox* pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_TID);
+	BYTE tid = (BYTE)pComboBox->GetCurSel();
+	CString strText;
+	GetDlgItemText(IDC_EDIT_TEXT, strText);
+
+	theApp.m_model.m_pHsmsActive->hsmsTerminalDisplay(tid, (LPTSTR)(LPCTSTR)strText);
+}
diff --git a/SourceCode/Bond/EAPSimulator/CTerminalDisplayDlg.h b/SourceCode/Bond/EAPSimulator/CTerminalDisplayDlg.h
new file mode 100644
index 0000000..8e0e310
--- /dev/null
+++ b/SourceCode/Bond/EAPSimulator/CTerminalDisplayDlg.h
@@ -0,0 +1,27 @@
+锘�#pragma once
+
+
+// CTerminalDisplayDlg 瀵硅瘽妗�
+
+class CTerminalDisplayDlg : public CDialogEx
+{
+	DECLARE_DYNAMIC(CTerminalDisplayDlg)
+
+public:
+	CTerminalDisplayDlg(CWnd* pParent = nullptr);   // 鏍囧噯鏋勯�犲嚱鏁�
+	virtual ~CTerminalDisplayDlg();
+
+// 瀵硅瘽妗嗘暟鎹�
+#ifdef AFX_DESIGN_TIME
+	enum { IDD = IDD_DIALOG_TERMINAL_DISPLAY };
+#endif
+
+protected:
+	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 鏀寔
+
+	DECLARE_MESSAGE_MAP()
+public:
+	virtual BOOL OnInitDialog();
+	afx_msg void OnEnChangeEditText();
+	afx_msg void OnBnClickedButtonSend();
+};
diff --git a/SourceCode/Bond/EAPSimulator/CVariable.cpp b/SourceCode/Bond/EAPSimulator/CVariable.cpp
new file mode 100644
index 0000000..465f927
--- /dev/null
+++ b/SourceCode/Bond/EAPSimulator/CVariable.cpp
@@ -0,0 +1,90 @@
+#include "pch.h"
+#include "CVariable.h"
+
+
+namespace SERVO {
+	CVariable::CVariable()
+	{
+		m_nVarialbeId = 0;
+		m_format = SVFromat::U1;
+	}
+
+	CVariable::CVariable(const char* pszId, const char* pszName, const char* pszFormat, const char* pszRemark)
+	{
+		m_nVarialbeId = atoi(pszId);
+		m_strName = pszName;
+		m_format = toFormat(pszFormat);
+		m_strRemark = pszRemark;
+		TRACE("CVariable .....%d,%s,%d,%s\n", m_nVarialbeId, m_strName.c_str(),
+			m_format, m_strRemark.c_str());
+
+	}
+
+	CVariable::~CVariable()
+	{
+
+	}
+
+	SVFromat CVariable::toFormat(const char* pszFormat)
+	{
+		if (_strcmpi("U1", pszFormat) == 0) {
+			return SVFromat::U1;
+		}
+		if (_strcmpi("U2", pszFormat) == 0) {
+			return SVFromat::U2;
+		}
+		if (_strcmpi("I2", pszFormat) == 0) {
+			return SVFromat::I2;
+		}
+		if (_strcmpi("A50", pszFormat) == 0) {
+			return SVFromat::A50;
+		}
+		if (_strcmpi("A20", pszFormat) == 0) {
+			return SVFromat::A20;
+		}
+
+		return SVFromat::U1;
+	}
+
+
+	std::string CVariable::formatToString(SVFromat format)
+	{
+		if (SVFromat::U1 == format) {
+			return "U1";
+		}
+		if (SVFromat::U2 == format) {
+			return "U1";
+		}
+		if (SVFromat::I2 == format) {
+			return "I2";
+		}
+		if (SVFromat::A50 == format) {
+			return "A50";
+		}
+		if (SVFromat::A20 == format) {
+			return "A20";
+		}
+
+		return "U1";
+	}
+
+	unsigned int CVariable::getVarialbleId()
+	{
+		return m_nVarialbeId;
+	}
+
+	std::string& CVariable::getName()
+	{
+		return m_strName;
+	}
+
+	SVFromat CVariable::getFormat()
+	{
+		return m_format;
+	}
+
+	std::string& CVariable::getRemark()
+	{
+		return m_strRemark;
+	}
+}
\ No newline at end of file
diff --git a/SourceCode/Bond/EAPSimulator/CVariable.h b/SourceCode/Bond/EAPSimulator/CVariable.h
new file mode 100644
index 0000000..7bac823
--- /dev/null
+++ b/SourceCode/Bond/EAPSimulator/CVariable.h
@@ -0,0 +1,37 @@
+#pragma once
+#include <string>
+
+
+namespace SERVO {
+	// 变量格式
+	enum class SVFromat {
+		U1 = 0,
+		U2,
+		I2,
+		A20,
+		A50
+	};
+
+	class CVariable
+	{
+	public:
+		CVariable();
+		CVariable(const char* pszId, const char* pszName, const char* pszFormat, const char* pszRemark);
+		~CVariable();
+
+	public:
+		static SVFromat toFormat(const char* pszFormat);
+		static std::string formatToString(SVFromat format);
+		unsigned int getVarialbleId();
+		std::string& getName();
+		SVFromat getFormat();
+		std::string& getRemark();
+
+	private:
+		unsigned int m_nVarialbeId;
+		std::string m_strName;
+		SVFromat m_format;
+		std::string m_strRemark;
+	};
+}
+
diff --git a/SourceCode/Bond/EAPSimulator/Common.h b/SourceCode/Bond/EAPSimulator/Common.h
new file mode 100644
index 0000000..121f282
--- /dev/null
+++ b/SourceCode/Bond/EAPSimulator/Common.h
@@ -0,0 +1,6 @@
+#pragma once
+
+
+#define RX_CODE_TEST					0
+#define RX_CODE_LOG						1000
+#define RX_CODE_ACTIVE_STATUS_CHANGED	1001
\ No newline at end of file
diff --git a/SourceCode/Bond/EAPSimulator/Context.cpp b/SourceCode/Bond/EAPSimulator/Context.cpp
new file mode 100644
index 0000000..b77a4bc
--- /dev/null
+++ b/SourceCode/Bond/EAPSimulator/Context.cpp
@@ -0,0 +1,184 @@
+#include "pch.h"
+#include "Context.h"
+#include <dbghelp.h>
+
+#pragma comment(lib, "dbghelp.lib")
+
+
+void PrintStackTrace()
+{
+	void* stack[62]; // 最多抓62层
+	USHORT frames = CaptureStackBackTrace(0, 62, stack, NULL);
+
+	HANDLE process = GetCurrentProcess();
+	SymInitialize(process, NULL, TRUE);
+	for (USHORT i = 0; i < frames; ++i) {
+		DWORD64 address = (DWORD64)(stack[i]);
+		char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)];
+		PSYMBOL_INFO symbol = (PSYMBOL_INFO)buffer;
+		symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
+		symbol->MaxNameLen = MAX_SYM_NAME;
+
+		if (SymFromAddr(process, address, 0, symbol)) {
+			TRACE(">>>> name:%s\n", symbol->Name);
+		}
+		else {
+			TRACE(">>>> name:%s\n", "SymFromAddr failed");
+		}
+	}
+
+	SymCleanup(process);
+}
+CContext::CContext()
+{
+	m_onReleaseCallback = nullptr;
+	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);
+}
+
+void CContext::setOnRelease(ONRELEASECALLBACK fOnRelease)
+{
+	m_onReleaseCallback = fOnRelease;
+}
+
+int CContext::addRef()
+{
+	Lock();
+	m_nRef++;
+	Unlock();
+
+	return m_nRef;
+}
+
+int CContext::release()
+{
+	Lock();
+	if (m_nRef > 0) {
+		m_nRef--;
+		BOOL bRefCount0 = m_nRef == 0;
+		Unlock();
+
+		if (bRefCount0 && m_onReleaseCallback != nullptr) {
+			m_onReleaseCallback(this);
+		}
+	}
+	else {
+		Unlock();
+	}
+
+	return m_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;
+}
\ No newline at end of file
diff --git a/SourceCode/Bond/EAPSimulator/Context.h b/SourceCode/Bond/EAPSimulator/Context.h
new file mode 100644
index 0000000..9e556ac
--- /dev/null
+++ b/SourceCode/Bond/EAPSimulator/Context.h
@@ -0,0 +1,48 @@
+#pragma once
+#include "Common.h"
+#include <functional>
+
+
+typedef std::function<void(void*)> ONRELEASECALLBACK;
+class CContext : public IRxObject
+{
+public:
+	CContext();
+	virtual ~CContext();
+
+public:
+	void setOnRelease(ONRELEASECALLBACK fOnRelease);
+	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);
+
+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:
+	ONRELEASECALLBACK m_onReleaseCallback;
+	int m_nRef;
+	CRITICAL_SECTION m_criticalSection;
+
+protected:
+	int m_nRetCode;
+	std::string m_strRetMsg;
+	HANDLE m_hEvent;
+};
+
diff --git a/SourceCode/Bond/EAPSimulator/EAPSimulator.cpp b/SourceCode/Bond/EAPSimulator/EAPSimulator.cpp
new file mode 100644
index 0000000..52d469b
--- /dev/null
+++ b/SourceCode/Bond/EAPSimulator/EAPSimulator.cpp
@@ -0,0 +1,133 @@
+锘�
+// EAPSimulator.cpp: 瀹氫箟搴旂敤绋嬪簭鐨勭被琛屼负銆�
+//
+
+#include "pch.h"
+#include "framework.h"
+#include "EAPSimulator.h"
+#include "EAPSimulatorDlg.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#endif
+
+
+// CEAPSimulatorApp
+
+BEGIN_MESSAGE_MAP(CEAPSimulatorApp, CWinApp)
+	ON_COMMAND(ID_HELP, &CWinApp::OnHelp)
+END_MESSAGE_MAP()
+
+
+// CEAPSimulatorApp 鏋勯��
+
+CEAPSimulatorApp::CEAPSimulatorApp()
+{
+	// 鏀寔閲嶆柊鍚姩绠$悊鍣�
+	m_dwRestartManagerSupportFlags = AFX_RESTART_MANAGER_SUPPORT_RESTART;
+
+	// TODO: 鍦ㄦ澶勬坊鍔犳瀯閫犱唬鐮侊紝
+	// 灏嗘墍鏈夐噸瑕佺殑鍒濆鍖栨斁缃湪 InitInstance 涓�
+}
+
+
+// 鍞竴鐨� CEAPSimulatorApp 瀵硅薄
+
+CEAPSimulatorApp theApp;
+
+
+// CEAPSimulatorApp 鍒濆鍖�
+
+BOOL CEAPSimulatorApp::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;
+
+	// 婵�娲烩�淲indows Native鈥濊瑙夌鐞嗗櫒锛屼互渚垮湪 MFC 鎺т欢涓惎鐢ㄤ富棰�
+	CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerWindows));
+
+	// 鏍囧噯鍒濆鍖�
+	// 濡傛灉鏈娇鐢ㄨ繖浜涘姛鑳藉苟甯屾湜鍑忓皬
+	// 鏈�缁堝彲鎵ц鏂囦欢鐨勫ぇ灏忥紝鍒欏簲绉婚櫎涓嬪垪
+	// 涓嶉渶瑕佺殑鐗瑰畾鍒濆鍖栦緥绋�
+	// 鏇存敼鐢ㄤ簬瀛樺偍璁剧疆鐨勬敞鍐岃〃椤�
+	// TODO: 搴旈�傚綋淇敼璇ュ瓧绗︿覆锛�
+	// 渚嬪淇敼涓哄叕鍙告垨缁勭粐鍚�
+	SetRegistryKey(_T("搴旂敤绋嬪簭鍚戝鐢熸垚鐨勬湰鍦板簲鐢ㄧ▼搴�"));
+
+
+	// 鏈▼搴忔枃浠剁洰褰�
+	TCHAR sDrive[_MAX_DRIVE];
+	TCHAR sDir[_MAX_DIR];
+	TCHAR sFilename[_MAX_FNAME], sAppFilename[_MAX_FNAME];
+	TCHAR sExt[_MAX_EXT];
+	GetModuleFileName(AfxGetInstanceHandle(), sAppFilename, _MAX_FNAME);
+	_tsplitpath_s(sAppFilename, sDrive, sDir, sFilename, sExt);
+	m_strAppDir = CString(sDrive) + CString(sDir);
+	m_strAppFile = CString(sFilename);
+
+
+	// 鍒濆鍖朢x搴�
+	RX_Init();
+	HSMS_Initialize();
+
+
+
+	CEAPSimulatorDlg dlg;
+	m_pMainWnd = &dlg;
+	INT_PTR nResponse = dlg.DoModal();
+	if (nResponse == IDOK)
+	{
+		// TODO: 鍦ㄦ鏀剧疆澶勭悊浣曟椂鐢�
+		//  鈥滅‘瀹氣�濇潵鍏抽棴瀵硅瘽妗嗙殑浠g爜
+	}
+	else if (nResponse == IDCANCEL)
+	{
+		// TODO: 鍦ㄦ鏀剧疆澶勭悊浣曟椂鐢�
+		//  鈥滃彇娑堚�濇潵鍏抽棴瀵硅瘽妗嗙殑浠g爜
+	}
+	else if (nResponse == -1)
+	{
+		TRACE(traceAppMsg, 0, "璀﹀憡: 瀵硅瘽妗嗗垱寤哄け璐ワ紝搴旂敤绋嬪簭灏嗘剰澶栫粓姝€�俓n");
+		TRACE(traceAppMsg, 0, "璀﹀憡: 濡傛灉鎮ㄥ湪瀵硅瘽妗嗕笂浣跨敤 MFC 鎺т欢锛屽垯鏃犳硶 #define _AFX_NO_MFC_CONTROLS_IN_DIALOGS銆俓n");
+	}
+
+	// 鍒犻櫎涓婇潰鍒涘缓鐨� shell 绠$悊鍣ㄣ��
+	if (pShellManager != nullptr)
+	{
+		delete pShellManager;
+	}
+
+#if !defined(_AFXDLL) && !defined(_AFX_NO_MFC_CONTROLS_IN_DIALOGS)
+	ControlBarCleanUp();
+#endif
+
+	// 鐢变簬瀵硅瘽妗嗗凡鍏抽棴锛屾墍浠ュ皢杩斿洖 FALSE 浠ヤ究閫�鍑哄簲鐢ㄧ▼搴忥紝
+	//  鑰屼笉鏄惎鍔ㄥ簲鐢ㄧ▼搴忕殑娑堟伅娉点��
+	return FALSE;
+}
+
+
+int CEAPSimulatorApp::ExitInstance()
+{
+	HSMS_Term();
+	RX_Term();
+
+	return CWinApp::ExitInstance();
+}
diff --git a/SourceCode/Bond/EAPSimulator/EAPSimulator.h b/SourceCode/Bond/EAPSimulator/EAPSimulator.h
new file mode 100644
index 0000000..0734c5a
--- /dev/null
+++ b/SourceCode/Bond/EAPSimulator/EAPSimulator.h
@@ -0,0 +1,40 @@
+锘�
+// EAPSimulator.h: PROJECT_NAME 搴旂敤绋嬪簭鐨勪富澶存枃浠�
+//
+
+#pragma once
+
+#ifndef __AFXWIN_H__
+	#error "鍦ㄥ寘鍚鏂囦欢涔嬪墠鍖呭惈 'pch.h' 浠ョ敓鎴� PCH"
+#endif
+
+#include "resource.h"		// 涓荤鍙�
+#include "CModel.h"
+
+
+// CEAPSimulatorApp:
+// 鏈夊叧姝ょ被鐨勫疄鐜帮紝璇峰弬闃� EAPSimulator.cpp
+//
+
+class CEAPSimulatorApp : public CWinApp
+{
+public:
+	CEAPSimulatorApp();
+
+
+public:
+	CModel m_model;
+	CString m_strAppDir;
+	CString m_strAppFile;
+
+// 閲嶅啓
+public:
+	virtual BOOL InitInstance();
+
+// 瀹炵幇
+
+	DECLARE_MESSAGE_MAP()
+	virtual int ExitInstance();
+};
+
+extern CEAPSimulatorApp theApp;
diff --git a/SourceCode/Bond/EAPSimulator/EAPSimulator.rc b/SourceCode/Bond/EAPSimulator/EAPSimulator.rc
new file mode 100644
index 0000000..e90e25a
--- /dev/null
+++ b/SourceCode/Bond/EAPSimulator/EAPSimulator.rc
Binary files differ
diff --git a/SourceCode/Bond/EAPSimulator/EAPSimulator.vcxproj b/SourceCode/Bond/EAPSimulator/EAPSimulator.vcxproj
new file mode 100644
index 0000000..a614abf
--- /dev/null
+++ b/SourceCode/Bond/EAPSimulator/EAPSimulator.vcxproj
@@ -0,0 +1,247 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" 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">
+    <VCProjectVersion>16.0</VCProjectVersion>
+    <ProjectGuid>{9EA43050-B71C-47A7-AC90-F0D7A88C5F50}</ProjectGuid>
+    <Keyword>MFCProj</Keyword>
+    <RootNamespace>EAPSimulator</RootNamespace>
+    <WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>v142</PlatformToolset>
+    <CharacterSet>Unicode</CharacterSet>
+    <UseOfMfc>Dynamic</UseOfMfc>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>v142</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>v142</PlatformToolset>
+    <CharacterSet>MultiByte</CharacterSet>
+    <UseOfMfc>Dynamic</UseOfMfc>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>v142</PlatformToolset>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</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|x64'">
+    <LinkIncremental>true</LinkIncremental>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <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|x64'">
+    <ClCompile>
+      <PrecompiledHeader>Use</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <SDLCheck>true</SDLCheck>
+      <PreprocessorDefinitions>_WINDOWS;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
+    </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|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>Use</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <SDLCheck>true</SDLCheck>
+      <PreprocessorDefinitions>WIN32;_WINDOWS;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
+    </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>
+      <PrecompiledHeader>Use</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <PreprocessorDefinitions>WIN32;_WINDOWS;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
+    </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>
+      <PrecompiledHeader>Use</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <PreprocessorDefinitions>_WINDOWS;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
+    </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>
+    <ClInclude Include="CAddIDSDlg.h" />
+    <ClInclude Include="CCollectionEvent.h" />
+    <ClInclude Include="CDefineReportsDlg.h" />
+    <ClInclude Include="CEDEventReportDlg.h" />
+    <ClInclude Include="CHsmsActive.h" />
+    <ClInclude Include="CLinkReportDetailDlg.h" />
+    <ClInclude Include="CLinkReportDlg.h" />
+    <ClInclude Include="CModel.h" />
+    <ClInclude Include="Common.h" />
+    <ClInclude Include="Context.h" />
+    <ClInclude Include="CReport.h" />
+    <ClInclude Include="CTerminalDisplayDlg.h" />
+    <ClInclude Include="CVariable.h" />
+    <ClInclude Include="EAPSimulator.h" />
+    <ClInclude Include="EAPSimulatorDlg.h" />
+    <ClInclude Include="framework.h" />
+    <ClInclude Include="Log.h" />
+    <ClInclude Include="LogEdit.h" />
+    <ClInclude Include="pch.h" />
+    <ClInclude Include="Resource.h" />
+    <ClInclude Include="targetver.h" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="CAddIDSDlg.cpp" />
+    <ClCompile Include="CCollectionEvent.cpp" />
+    <ClCompile Include="CDefineReportsDlg.cpp" />
+    <ClCompile Include="CEDEventReportDlg.cpp" />
+    <ClCompile Include="CHsmsActive.cpp" />
+    <ClCompile Include="CLinkReportDetailDlg.cpp" />
+    <ClCompile Include="CLinkReportDlg.cpp" />
+    <ClCompile Include="CModel.cpp" />
+    <ClCompile Include="Context.cpp" />
+    <ClCompile Include="CReport.cpp" />
+    <ClCompile Include="CTerminalDisplayDlg.cpp" />
+    <ClCompile Include="CVariable.cpp" />
+    <ClCompile Include="EAPSimulator.cpp" />
+    <ClCompile Include="EAPSimulatorDlg.cpp" />
+    <ClCompile Include="Log.cpp" />
+    <ClCompile Include="LogEdit.cpp" />
+    <ClCompile Include="pch.cpp">
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ResourceCompile Include="EAPSimulator.rc" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="res\EAPSimulator.rc2" />
+  </ItemGroup>
+  <ItemGroup>
+    <Image Include="res\EAPSimulator.ico" />
+  </ItemGroup>
+  <ItemGroup>
+    <Manifest Include="res\application.exe.manifest" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>
\ No newline at end of file
diff --git a/SourceCode/Bond/EAPSimulator/EAPSimulator.vcxproj.filters b/SourceCode/Bond/EAPSimulator/EAPSimulator.vcxproj.filters
new file mode 100644
index 0000000..dab50ba
--- /dev/null
+++ b/SourceCode/Bond/EAPSimulator/EAPSimulator.vcxproj.filters
@@ -0,0 +1,153 @@
+锘�<?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;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+    </Filter>
+    <Filter Include="澶存枃浠�">
+      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+      <Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;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>
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="EAPSimulator.h">
+      <Filter>澶存枃浠�</Filter>
+    </ClInclude>
+    <ClInclude Include="EAPSimulatorDlg.h">
+      <Filter>澶存枃浠�</Filter>
+    </ClInclude>
+    <ClInclude Include="framework.h">
+      <Filter>澶存枃浠�</Filter>
+    </ClInclude>
+    <ClInclude Include="targetver.h">
+      <Filter>澶存枃浠�</Filter>
+    </ClInclude>
+    <ClInclude Include="Resource.h">
+      <Filter>澶存枃浠�</Filter>
+    </ClInclude>
+    <ClInclude Include="pch.h">
+      <Filter>澶存枃浠�</Filter>
+    </ClInclude>
+    <ClInclude Include="Log.h">
+      <Filter>澶存枃浠�</Filter>
+    </ClInclude>
+    <ClInclude Include="LogEdit.h">
+      <Filter>澶存枃浠�</Filter>
+    </ClInclude>
+    <ClInclude Include="CModel.h">
+      <Filter>澶存枃浠�</Filter>
+    </ClInclude>
+    <ClInclude Include="Context.h">
+      <Filter>澶存枃浠�</Filter>
+    </ClInclude>
+    <ClInclude Include="CHsmsActive.h">
+      <Filter>澶存枃浠�</Filter>
+    </ClInclude>
+    <ClInclude Include="Common.h">
+      <Filter>澶存枃浠�</Filter>
+    </ClInclude>
+    <ClInclude Include="CTerminalDisplayDlg.h">
+      <Filter>澶存枃浠�</Filter>
+    </ClInclude>
+    <ClInclude Include="CEDEventReportDlg.h">
+      <Filter>澶存枃浠�</Filter>
+    </ClInclude>
+    <ClInclude Include="CDefineReportsDlg.h">
+      <Filter>澶存枃浠�</Filter>
+    </ClInclude>
+    <ClInclude Include="CAddIDSDlg.h">
+      <Filter>澶存枃浠�</Filter>
+    </ClInclude>
+    <ClInclude Include="CLinkReportDlg.h">
+      <Filter>澶存枃浠�</Filter>
+    </ClInclude>
+    <ClInclude Include="CCollectionEvent.h">
+      <Filter>澶存枃浠�</Filter>
+    </ClInclude>
+    <ClInclude Include="CReport.h">
+      <Filter>澶存枃浠�</Filter>
+    </ClInclude>
+    <ClInclude Include="CVariable.h">
+      <Filter>澶存枃浠�</Filter>
+    </ClInclude>
+    <ClInclude Include="CLinkReportDetailDlg.h">
+      <Filter>澶存枃浠�</Filter>
+    </ClInclude>
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="EAPSimulator.cpp">
+      <Filter>婧愭枃浠�</Filter>
+    </ClCompile>
+    <ClCompile Include="EAPSimulatorDlg.cpp">
+      <Filter>婧愭枃浠�</Filter>
+    </ClCompile>
+    <ClCompile Include="pch.cpp">
+      <Filter>婧愭枃浠�</Filter>
+    </ClCompile>
+    <ClCompile Include="Log.cpp">
+      <Filter>婧愭枃浠�</Filter>
+    </ClCompile>
+    <ClCompile Include="LogEdit.cpp">
+      <Filter>婧愭枃浠�</Filter>
+    </ClCompile>
+    <ClCompile Include="CModel.cpp">
+      <Filter>婧愭枃浠�</Filter>
+    </ClCompile>
+    <ClCompile Include="Context.cpp">
+      <Filter>婧愭枃浠�</Filter>
+    </ClCompile>
+    <ClCompile Include="CHsmsActive.cpp">
+      <Filter>婧愭枃浠�</Filter>
+    </ClCompile>
+    <ClCompile Include="CTerminalDisplayDlg.cpp">
+      <Filter>婧愭枃浠�</Filter>
+    </ClCompile>
+    <ClCompile Include="CEDEventReportDlg.cpp">
+      <Filter>婧愭枃浠�</Filter>
+    </ClCompile>
+    <ClCompile Include="CDefineReportsDlg.cpp">
+      <Filter>婧愭枃浠�</Filter>
+    </ClCompile>
+    <ClCompile Include="CAddIDSDlg.cpp">
+      <Filter>婧愭枃浠�</Filter>
+    </ClCompile>
+    <ClCompile Include="CLinkReportDlg.cpp">
+      <Filter>婧愭枃浠�</Filter>
+    </ClCompile>
+    <ClCompile Include="CCollectionEvent.cpp">
+      <Filter>婧愭枃浠�</Filter>
+    </ClCompile>
+    <ClCompile Include="CReport.cpp">
+      <Filter>婧愭枃浠�</Filter>
+    </ClCompile>
+    <ClCompile Include="CVariable.cpp">
+      <Filter>婧愭枃浠�</Filter>
+    </ClCompile>
+    <ClCompile Include="CLinkReportDetailDlg.cpp">
+      <Filter>婧愭枃浠�</Filter>
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ResourceCompile Include="EAPSimulator.rc">
+      <Filter>璧勬簮鏂囦欢</Filter>
+    </ResourceCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="res\EAPSimulator.rc2">
+      <Filter>璧勬簮鏂囦欢</Filter>
+    </None>
+  </ItemGroup>
+  <ItemGroup>
+    <Image Include="res\EAPSimulator.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/EAPSimulator/EAPSimulator.vcxproj.user b/SourceCode/Bond/EAPSimulator/EAPSimulator.vcxproj.user
new file mode 100644
index 0000000..ff5ccd7
--- /dev/null
+++ b/SourceCode/Bond/EAPSimulator/EAPSimulator.vcxproj.user
@@ -0,0 +1,6 @@
+锘�<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <RESOURCE_FILE>EAPSimulator.rc</RESOURCE_FILE>
+  </PropertyGroup>
+</Project>
\ No newline at end of file
diff --git a/SourceCode/Bond/EAPSimulator/EAPSimulatorDlg.cpp b/SourceCode/Bond/EAPSimulator/EAPSimulatorDlg.cpp
new file mode 100644
index 0000000..430a1ae
--- /dev/null
+++ b/SourceCode/Bond/EAPSimulator/EAPSimulatorDlg.cpp
@@ -0,0 +1,357 @@
+锘�
+// EAPSimulatorDlg.cpp: 瀹炵幇鏂囦欢
+//
+
+#include "pch.h"
+#include "framework.h"
+#include "EAPSimulator.h"
+#include "EAPSimulatorDlg.h"
+#include "afxdialogex.h"
+#include "Common.h"
+#include <regex>
+#include "CTerminalDisplayDlg.h"
+#include "CEDEventReportDlg.h"
+#include "CDefineReportsDlg.h"
+#include "CLinkReportDlg.h"
+
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#endif
+
+
+// 鐢ㄤ簬搴旂敤绋嬪簭鈥滃叧浜庘�濊彍鍗曢」鐨� 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()
+
+
+// CEAPSimulatorDlg 瀵硅瘽妗�
+
+
+
+CEAPSimulatorDlg::CEAPSimulatorDlg(CWnd* pParent /*=nullptr*/)
+	: CDialogEx(IDD_EAPSIMULATOR_DIALOG, pParent)
+{
+	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
+	m_pObserver = nullptr;
+}
+
+void CEAPSimulatorDlg::DoDataExchange(CDataExchange* pDX)
+{
+	CDialogEx::DoDataExchange(pDX);
+	DDX_Control(pDX, IDC_EDIT_LOG, m_logEdit);
+}
+
+BEGIN_MESSAGE_MAP(CEAPSimulatorDlg, CDialogEx)
+	ON_WM_SYSCOMMAND()
+	ON_WM_PAINT()
+	ON_WM_QUERYDRAGICON()
+	ON_WM_DESTROY()
+	ON_BN_CLICKED(IDC_BUTTON_CONNECT, &CEAPSimulatorDlg::OnBnClickedButtonConnect)
+	ON_BN_CLICKED(IDC_BUTTON_DISCONNECT, &CEAPSimulatorDlg::OnBnClickedButtonDisconnect)
+	ON_BN_CLICKED(IDC_BUTTON_ARE_YOU_THERE, &CEAPSimulatorDlg::OnBnClickedButtonAreYouThere)
+	ON_BN_CLICKED(IDC_BUTTON_DATETIME_SYNC, &CEAPSimulatorDlg::OnBnClickedButtonDatetimeSync)
+	ON_BN_CLICKED(IDC_BUTTON_TERMINAL_DISPLAY, &CEAPSimulatorDlg::OnBnClickedButtonTerminalDisplay)
+	ON_BN_CLICKED(IDC_BUTTON_ED_EVENT_REPORT, &CEAPSimulatorDlg::OnBnClickedButtonEdEventReport)
+	ON_BN_CLICKED(IDC_BUTTON_ED_ALARM_REPORT, &CEAPSimulatorDlg::OnBnClickedButtonEdAlarmReport)
+	ON_BN_CLICKED(IDC_BUTTON_DEFINE_REPORT, &CEAPSimulatorDlg::OnBnClickedButtonDefineReport)
+	ON_BN_CLICKED(IDC_BUTTON_LINE_REPORT, &CEAPSimulatorDlg::OnBnClickedButtonLineReport)
+	ON_BN_CLICKED(IDC_BUTTON_CONFIGURE_SPOOLING, &CEAPSimulatorDlg::OnBnClickedButtonConfigureSpooling)
+END_MESSAGE_MAP()
+
+
+// CEAPSimulatorDlg 娑堟伅澶勭悊绋嬪簭
+
+void CEAPSimulatorDlg::InitRxWindow()
+{
+	/* code */
+	// 璁㈤槄鏁版嵁
+	IRxWindows* pRxWindows = RX_GetRxWindows();
+	pRxWindows->enableLog(5);
+	if (m_pObserver == NULL) {
+		m_pObserver = pRxWindows->allocObserver([&](IAny* pAny) -> void {
+			// onNext
+			pAny->addRef();
+			int code = pAny->getCode();
+			if (RX_CODE_LOG == code && ::IsWindow(m_hWnd)) {
+				const char* pszLogMsg;
+				int level;
+				if (pAny->getStringValue("text", pszLogMsg)
+					&& pAny->getIntValue("exCode", level)) {
+					CString strText = pszLogMsg;
+					strText.Replace("\n", "\r\n");
+					AppendLog(level, (LPTSTR)(LPCTSTR)strText);
+				}
+			}
+			else if (RX_CODE_ACTIVE_STATUS_CHANGED == code) {
+				int state;
+				if (pAny->getIntValue("exCode", state)) {
+					if ((ACTIVESTATE)state == ACTIVESTATE::SELECTED) {
+						SetGroup2Enabled(TRUE);
+					}
+					if ((ACTIVESTATE)state == ACTIVESTATE::NOT_CONNECTED) {
+						SetGroup2Enabled(FALSE);
+						SetGroup1Enabled(TRUE);
+					}
+				}
+			}
+
+			pAny->release();
+			}, [&]() -> void {
+				// onComplete
+			}, [&](IThrowable* pThrowable) -> void {
+				// onErrorm
+				pThrowable->printf();
+			});
+
+		theApp.m_model.getObservable()->observeOn(pRxWindows->mainThread())
+			->subscribe(m_pObserver);
+	}
+
+	theApp.m_model.init();
+}
+
+BOOL CEAPSimulatorDlg::OnInitDialog()
+{
+	CDialogEx::OnInitDialog();
+
+	// 灏嗏�滃叧浜�...鈥濊彍鍗曢」娣诲姞鍒扮郴缁熻彍鍗曚腑銆�
+
+	// IDM_ABOUTBOX 蹇呴』鍦ㄧ郴缁熷懡浠よ寖鍥村唴銆�
+	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
+	ASSERT(IDM_ABOUTBOX < 0xF000);
+
+	CMenu* pSysMenu = GetSystemMenu(FALSE);
+	if (pSysMenu != nullptr)
+	{
+		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);		// 璁剧疆灏忓浘鏍�
+
+	SetDlgItemText(IDC_EDIT_IP, _T("127.0.0.1"));
+	SetDlgItemInt(IDC_EDIT_PORT, 7000);
+	SetGroup2Enabled(FALSE);
+	SetGroup1Enabled(TRUE);
+	::SetProp(GetDlgItem(IDC_BUTTON_ED_ALARM_REPORT)->m_hWnd, _T("Enable"), (void*)1);
+
+
+	// log edit
+	m_logEdit.SetMaxLineCount(8000);
+	m_logEdit.SetLimitText(-1);
+	InitRxWindow();
+
+	return TRUE;  // 闄ら潪灏嗙劍鐐硅缃埌鎺т欢锛屽惁鍒欒繑鍥� TRUE
+}
+
+void CEAPSimulatorDlg::OnSysCommand(UINT nID, LPARAM lParam)
+{
+	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
+	{
+		CAboutDlg dlgAbout;
+		dlgAbout.DoModal();
+	}
+	else
+	{
+		CDialogEx::OnSysCommand(nID, lParam);
+	}
+}
+
+// 濡傛灉鍚戝璇濇娣诲姞鏈�灏忓寲鎸夐挳锛屽垯闇�瑕佷笅闈㈢殑浠g爜
+//  鏉ョ粯鍒惰鍥炬爣銆�  瀵逛簬浣跨敤鏂囨。/瑙嗗浘妯″瀷鐨� MFC 搴旂敤绋嬪簭锛�
+//  杩欏皢鐢辨鏋惰嚜鍔ㄥ畬鎴愩��
+
+void CEAPSimulatorDlg::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 CEAPSimulatorDlg::OnQueryDragIcon()
+{
+	return static_cast<HCURSOR>(m_hIcon);
+}
+
+void CEAPSimulatorDlg::AppendLog(int level, const char* pszText)
+{
+	if (!::IsWindow(m_logEdit.m_hWnd)) {
+		return;
+	}
+	m_logEdit.AppendText(pszText);
+}
+
+
+
+void CEAPSimulatorDlg::OnDestroy()
+{
+	CDialogEx::OnDestroy();
+
+	ASSERT(m_pObserver != NULL);
+	m_pObserver->unsubscribe();
+	m_pObserver = NULL;
+}
+
+void CEAPSimulatorDlg::SetGroup1Enabled(bool enabled)
+{
+	GetDlgItem(IDC_EDIT_IP)->EnableWindow(enabled);
+	GetDlgItem(IDC_EDIT_PORT)->EnableWindow(enabled);
+	GetDlgItem(IDC_BUTTON_CONNECT)->EnableWindow(enabled);
+}
+
+void CEAPSimulatorDlg::SetGroup2Enabled(bool enabled)
+{
+	GetDlgItem(IDC_BUTTON_DISCONNECT)->EnableWindow(enabled);
+	GetDlgItem(IDC_BUTTON_ARE_YOU_THERE)->EnableWindow(enabled);
+	GetDlgItem(IDC_BUTTON_DATETIME_SYNC)->EnableWindow(enabled);
+	GetDlgItem(IDC_BUTTON_TERMINAL_DISPLAY)->EnableWindow(enabled);	
+	GetDlgItem(IDC_BUTTON_ED_EVENT_REPORT)->EnableWindow(enabled);
+	GetDlgItem(IDC_BUTTON_ED_ALARM_REPORT)->EnableWindow(enabled);	
+	GetDlgItem(IDC_BUTTON_DEFINE_REPORT)->EnableWindow(enabled);
+	GetDlgItem(IDC_BUTTON_LINE_REPORT)->EnableWindow(enabled);	
+	GetDlgItem(IDC_BUTTON_CONFIGURE_SPOOLING)->EnableWindow(enabled);	
+}
+
+void CEAPSimulatorDlg::OnBnClickedButtonConnect()
+{
+	CString strIp;
+	UINT port;
+	GetDlgItemText(IDC_EDIT_IP, strIp);
+	port = GetDlgItemInt(IDC_EDIT_PORT);
+	theApp.m_model.connectEq((LPTSTR)(LPCTSTR)strIp, port);
+	SetGroup1Enabled(FALSE);
+}
+
+void CEAPSimulatorDlg::OnBnClickedButtonDisconnect()
+{
+	theApp.m_model.disconnect();
+}
+
+void CEAPSimulatorDlg::OnBnClickedButtonAreYouThere()
+{
+	theApp.m_model.m_pHsmsActive->hsmsAreYouThere();
+}
+
+void CEAPSimulatorDlg::OnBnClickedButtonDatetimeSync()
+{
+	theApp.m_model.m_pHsmsActive->hsmsDatetimeSync();
+}
+
+void CEAPSimulatorDlg::OnBnClickedButtonTerminalDisplay()
+{
+	CTerminalDisplayDlg dlg;
+	dlg.DoModal();
+}
+
+void CEAPSimulatorDlg::OnBnClickedButtonEdEventReport()
+{
+	CEDEventReportDlg dlg;
+	dlg.DoModal();
+}
+
+void CEAPSimulatorDlg::OnBnClickedButtonEdAlarmReport()
+{
+	int enable = (int)::GetProp(GetDlgItem(IDC_BUTTON_ED_ALARM_REPORT)->m_hWnd, _T("Enable"));
+	enable = enable == 0 ? 1 : 0;
+	theApp.m_model.m_pHsmsActive->hsmsEDAlarmReport(enable == 1, 0);
+
+	SetDlgItemText(IDC_BUTTON_ED_ALARM_REPORT, 
+		enable == 1 ? _T("Disable Alarm Report") : _T("Enable Alarm Report"));
+	::SetProp(GetDlgItem(IDC_BUTTON_ED_ALARM_REPORT)->m_hWnd, _T("Enable"), (void*)enable);
+}
+
+void CEAPSimulatorDlg::OnBnClickedButtonDefineReport()
+{
+	CDefineReportsDlg dlg;
+	dlg.DoModal();
+}
+
+void CEAPSimulatorDlg::OnBnClickedButtonLineReport()
+{
+	CLinkReportDlg dlg;
+	dlg.DoModal();
+}
+
+void CEAPSimulatorDlg::OnBnClickedButtonConfigureSpooling()
+{
+	std::map<unsigned int, std::set<unsigned int>> spoolingConfig;
+
+	// test clear all
+	// theApp.m_model.m_pHsmsActive->hsmsConfigureSpooling(spoolingConfig);
+
+
+	// test add s2[1,3,5];
+	// spoolingConfig[2].insert(1);
+	// spoolingConfig[2].insert(3);
+	// spoolingConfig[2].insert(5);
+	// spoolingConfig[3].insert(2);
+	// spoolingConfig[3].insert(4);
+	// spoolingConfig[3].insert(6);
+	// theApp.m_model.m_pHsmsActive->hsmsConfigureSpooling(spoolingConfig);
+
+	// test clear S2
+	// spoolingConfig[2].clear();
+	// theApp.m_model.m_pHsmsActive->hsmsConfigureSpooling(spoolingConfig);
+
+	spoolingConfig[5].insert(66);
+	theApp.m_model.m_pHsmsActive->hsmsConfigureSpooling(spoolingConfig);
+}
diff --git a/SourceCode/Bond/EAPSimulator/EAPSimulatorDlg.h b/SourceCode/Bond/EAPSimulator/EAPSimulatorDlg.h
new file mode 100644
index 0000000..dd2de49
--- /dev/null
+++ b/SourceCode/Bond/EAPSimulator/EAPSimulatorDlg.h
@@ -0,0 +1,57 @@
+锘�
+// EAPSimulatorDlg.h: 澶存枃浠�
+//
+
+#pragma once
+#include "LogEdit.h"
+
+
+// CEAPSimulatorDlg 瀵硅瘽妗�
+class CEAPSimulatorDlg : public CDialogEx
+{
+// 鏋勯��
+public:
+	CEAPSimulatorDlg(CWnd* pParent = nullptr);	// 鏍囧噯鏋勯�犲嚱鏁�
+
+
+private:
+	void AppendLog(int level, const char* pszText);
+	void InitRxWindow();
+	void SetGroup1Enabled(bool enabled);
+	void SetGroup2Enabled(bool enabled);
+
+
+// 瀵硅瘽妗嗘暟鎹�
+#ifdef AFX_DESIGN_TIME
+	enum { IDD = IDD_EAPSIMULATOR_DIALOG };
+#endif
+
+	protected:
+	virtual void DoDataExchange(CDataExchange* pDX);	// DDX/DDV 鏀寔
+
+
+// 瀹炵幇
+protected:
+	HICON m_hIcon;
+	CLogEdit m_logEdit;
+	IObserver* m_pObserver;
+
+	// 鐢熸垚鐨勬秷鎭槧灏勫嚱鏁�
+	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 OnDestroy();
+	afx_msg void OnBnClickedButtonConnect();
+	afx_msg void OnBnClickedButtonDisconnect();
+	afx_msg void OnBnClickedButtonAreYouThere();
+	afx_msg void OnBnClickedButtonDatetimeSync();
+	afx_msg void OnBnClickedButtonTerminalDisplay();
+	afx_msg void OnBnClickedButtonEdEventReport();
+	afx_msg void OnBnClickedButtonEdAlarmReport();
+	afx_msg void OnBnClickedButtonDefineReport();
+	afx_msg void OnBnClickedButtonLineReport();
+	afx_msg void OnBnClickedButtonConfigureSpooling();
+};
diff --git a/SourceCode/Bond/EAPSimulator/Log.cpp b/SourceCode/Bond/EAPSimulator/Log.cpp
new file mode 100644
index 0000000..ed48f5e
--- /dev/null
+++ b/SourceCode/Bond/EAPSimulator/Log.cpp
@@ -0,0 +1,214 @@
+#include "pch.h"
+#include "Log.h"
+
+
+static const char* pszLevel[] = {" [Debug] ", " [Info] ", " [Warn] ", " [Error] "};
+
+CLog::CLog()
+{
+	m_nLevel = 0;
+	m_nOutputTarget = OT_TRACE;
+	m_bAutoAppendTime = TRUE;
+	m_strEquipmentId = _T("Unknown");
+	m_nDay = 0;
+	m_funOnLog = nullptr;
+	InitializeCriticalSection(&m_criticalSection);
+}
+
+
+CLog::~CLog()
+{
+	DeleteCriticalSection(&m_criticalSection);
+}
+
+CLog *CLog::GetLog(void)
+{
+	static CLog* pLog = NULL;
+	if (pLog == NULL) {
+		static CLog log;
+		pLog = &log;
+	}
+
+	return pLog;
+}
+
+void CLog::SetOnLogCallback(ONLOG funOnLog)
+{
+	m_funOnLog = funOnLog;
+}
+
+void CLog::SetOutputTarget(int flag)
+{
+	m_nOutputTarget = flag;
+}
+
+void CLog::SetEquipmentId(const char* pszEquipmentId)
+{
+	m_strEquipmentId = pszEquipmentId;
+}
+
+void CLog::SetAutoAppendTimeString(BOOL bAutoAppendTime)
+{
+	m_bAutoAppendTime = bAutoAppendTime;
+}
+
+void CLog::Batch()
+{
+	if (m_file.m_hFile != CFile::hFileNull) {
+		m_file.Close();
+	}
+}
+
+BOOL CLog::BatchAndNew(int& nDay)
+{
+	Batch();
+	if ( (m_nOutputTarget & OT_FILE) && m_file.m_hFile == CFile::hFileNull) {
+		CString strFilepath;
+		BOOL bRet = m_file.Open(MakeFilepathD(strFilepath, nDay), CFile::modeCreate | CFile::modeNoTruncate | CFile::modeWrite | CFile::shareDenyWrite);
+		if (bRet) {
+			m_file.SeekToEnd();
+		}
+		return bRet;
+	}
+
+	return FALSE;
+}
+
+#define BUFFERSIZE		1024*10
+void CLog::LogFormat(int nLevel, const char* pszTag, char* szMessage, ...)
+{
+	// 检查日期是否有变化,有变化则结批
+	Lock();
+	_SYSTEMTIME sysTime;
+	GetLocalTime(&sysTime);
+	if(m_nDay != sysTime.wDay) {
+		int nDay = 0;
+		if (BatchAndNew(nDay)) {
+			m_nDay = nDay;
+		}
+	}
+	Unlock();
+
+	if (nLevel < m_nLevel) {
+		return;
+	}
+
+	char szFullMessage[BUFFERSIZE];
+	char szFormatMessage[BUFFERSIZE];
+
+	// format message
+	va_list ap;
+	va_start(ap, szMessage);
+	_vsnprintf_s(szFormatMessage, BUFFERSIZE, szMessage, ap);
+	va_end(ap);
+
+	if (m_bAutoAppendTime) {
+		CString strTime;
+		strcpy_s(szFullMessage, BUFFERSIZE, (LPTSTR)(LPCTSTR)GetCurTime(strTime));
+	}
+	strcat_s(szFullMessage, BUFFERSIZE, pszLevel[nLevel]);
+	strcat_s(szFullMessage, szFormatMessage);
+	strcat_s(szFullMessage, BUFFERSIZE, "\n");
+
+	if (m_nOutputTarget & OT_FILE) {
+		Lock();
+		if (m_file.m_hFile != CFile::hFileNull) {
+			m_file.WriteString(szFullMessage);
+		}
+		Unlock();
+	}
+	if (m_nOutputTarget & OT_ODSTRING) {
+		OutputDebugStringA(szFullMessage);
+	}
+	else if(m_nOutputTarget & OT_TRACE) {
+		TRACE(szFormatMessage);
+	}
+
+	if (m_funOnLog != nullptr) {
+		m_funOnLog(nLevel, szFullMessage);
+	}
+}
+
+void CLog::Log(int nLevel, const char* pszTag, const char* szMessage)
+{
+	// 检查日期是否有变化,有变化则结批
+	Lock();
+	_SYSTEMTIME sysTime;
+	GetLocalTime(&sysTime);
+	if (m_nDay != sysTime.wDay) {
+		int nDay = 0;
+		if (BatchAndNew(nDay)) {
+			m_nDay = nDay;
+		}
+	}
+	Unlock();
+
+	if (nLevel < m_nLevel) {
+		return;
+	}
+
+	CString strMsg;
+	if (m_bAutoAppendTime) {
+		CString strTime;
+		GetCurTime(strTime);
+		strMsg.Append(strTime);
+	}
+	strMsg.Append(pszTag);
+	strMsg.Append(szMessage);
+	strMsg.Append("\n");
+
+	if (m_nOutputTarget & OT_FILE) {
+		Lock();
+		if (m_file.m_hFile != CFile::hFileNull) {
+			m_file.WriteString(strMsg);
+		}
+		Unlock();
+	}
+	if (m_nOutputTarget & OT_ODSTRING) {
+		OutputDebugStringA(strMsg);
+	}
+	else if (m_nOutputTarget & OT_TRACE) {
+		TRACE(strMsg);
+	}
+
+	if (m_funOnLog != nullptr) {
+		m_funOnLog(nLevel, strMsg);
+	}
+}
+
+CString& CLog::GetCurTime(CString& strTime)
+{
+	_SYSTEMTIME sysTime;
+	GetLocalTime(&sysTime);
+	strTime.Format(_T("%d/%02d/%02d %02d:%02d:%02d.%03d"), sysTime.wYear, sysTime.wMonth, sysTime.wDay,
+		sysTime.wHour, sysTime.wMinute, sysTime.wSecond, sysTime.wMilliseconds);
+	return strTime;
+}
+
+CString& CLog::MakeFilepath(CString& strFilepath)
+{
+	_SYSTEMTIME sysTime;
+	GetLocalTime(&sysTime);
+	strFilepath.Format(_T("%s\\Log(%s)_%d_%02d_%02d.log"), (LPTSTR)(LPCTSTR)m_strLogsDir,
+		(LPTSTR)(LPCTSTR)m_strEquipmentId,
+		sysTime.wYear, sysTime.wMonth, sysTime.wDay);
+
+	return strFilepath;
+}
+
+CString& CLog::MakeFilepathD(CString& strFilepath, int& day)
+{
+	_SYSTEMTIME sysTime;
+	GetLocalTime(&sysTime);
+	strFilepath.Format(_T("%s\\Log(%s)_%d_%02d_%02d.log"), (LPTSTR)(LPCTSTR)m_strLogsDir,
+		(LPTSTR)(LPCTSTR)m_strEquipmentId,
+		sysTime.wYear, sysTime.wMonth, sysTime.wDay);
+	day = sysTime.wDay;
+
+	return strFilepath;
+}
+
+void CLog::SetLogsDir(CString strDir)
+{
+	m_strLogsDir = strDir;
+}
diff --git a/SourceCode/Bond/EAPSimulator/Log.h b/SourceCode/Bond/EAPSimulator/Log.h
new file mode 100644
index 0000000..ee28e15
--- /dev/null
+++ b/SourceCode/Bond/EAPSimulator/Log.h
@@ -0,0 +1,61 @@
+#pragma once
+#include <functional>
+
+
+#define LEVEL_DEBUG		0
+#define LEVEL_INFO		1
+#define LEVEL_WARN		2
+#define LEVEL_ERROR		3
+
+
+#define LOGD(msg, ...)		CLog::GetLog()->LogFormat(LEVEL_DEBUG, "", msg, __VA_ARGS__)
+#define LOGI(msg, ...)		CLog::GetLog()->LogFormat(LEVEL_INFO, "", msg, __VA_ARGS__)
+#define LOGW(msg, ...)		CLog::GetLog()->LogFormat(LEVEL_WARN, "", msg, __VA_ARGS__)
+#define LOGE(msg, ...)		CLog::GetLog()->LogFormat(LEVEL_ERROR, "", msg, __VA_ARGS__)
+
+
+#define OT_FILE			0x01
+#define OT_ODSTRING		0x02
+#define OT_TRACE		0x04
+#define LOGBATHCH()				CLog::GetLog()->Batch()
+#define LOGNEW()				CLog::GetLog()->BatchAndNew()
+
+typedef std::function<void(int level, const char* pszMessage)> ONLOG;
+
+class CLog
+{
+public:
+	CLog();
+	~CLog();
+
+public:
+	void SetOnLogCallback(ONLOG funOnLog);
+	static CLog *GetLog(void);
+	void SetOutputTarget(int flag);
+	void SetEquipmentId(const char* pszEquipmentId);
+	static CString& GetCurTime(CString& strTime);
+	CString& MakeFilepath(CString& strFilepath);
+	CString& MakeFilepathD(CString& strFilepath, int& day);
+	void LogFormat(int nLevel, const char* pszTag, char* szMessage, ...);
+	void Log(int nLevel, const char* pszTag, const char* szMessage);
+	void SetAutoAppendTimeString(BOOL bAutoAppendTime);
+	void SetLogsDir(CString strDir);
+	void Batch();
+	BOOL BatchAndNew(int& nDay);
+
+private:
+	inline void Lock() { EnterCriticalSection(&m_criticalSection); }
+	inline void Unlock() { LeaveCriticalSection(&m_criticalSection); }
+
+private:
+	ONLOG m_funOnLog;
+	int m_nOutputTarget;
+	int m_nLevel;
+	BOOL m_bAutoAppendTime;
+	CString m_strLogsDir;
+	CString m_strEquipmentId;
+	CStdioFile m_file;
+	int m_nDay;						// 按日保存一条记录,比较此数字,以决定是否结批并创建新文件
+	CRITICAL_SECTION m_criticalSection;
+};
+
diff --git a/SourceCode/Bond/EAPSimulator/LogEdit.cpp b/SourceCode/Bond/EAPSimulator/LogEdit.cpp
new file mode 100644
index 0000000..d6e75ad
--- /dev/null
+++ b/SourceCode/Bond/EAPSimulator/LogEdit.cpp
@@ -0,0 +1,117 @@
+#include "pch.h"
+#include "LogEdit.h"
+
+
+#define MENU_ITEM_SEL_ALL		0x666
+#define MENU_ITEM_COPY			0x667
+#define MENU_ITEM_CLEAR			0x668
+
+CLogEdit::CLogEdit()
+{
+	m_nMaxLines = 0xffff;
+	m_nTrimLines = 100;
+	m_bAutoScroll = TRUE;
+}
+
+
+CLogEdit::~CLogEdit()
+{
+}
+
+BEGIN_MESSAGE_MAP(CLogEdit, CEdit)
+	ON_WM_CONTEXTMENU()
+	ON_WM_VSCROLL()
+    ON_WM_MOUSEWHEEL()
+END_MESSAGE_MAP()
+
+void CLogEdit::SetMaxLineCount(int line)
+{
+	m_nMaxLines = line;
+	m_nTrimLines = min(m_nMaxLines, 4000);
+}
+
+void CLogEdit::OnContextMenu(CWnd* pWnd, CPoint point)
+{
+	HMENU hMenu = CreatePopupMenu();
+	InsertMenu(hMenu, 0, MF_BYPOSITION, MENU_ITEM_SEL_ALL, "全选");
+	InsertMenu(hMenu, 1, MF_BYPOSITION, MENU_ITEM_COPY, "复制");
+	InsertMenu(hMenu, 2, MF_BYPOSITION | MF_SEPARATOR, NULL, NULL);	
+	InsertMenu(hMenu, 3, MF_BYPOSITION, MENU_ITEM_CLEAR, "全部清除");
+	int cmd = ::TrackPopupMenu(hMenu,
+		TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD,
+		point.x, point.y + 2, 0, m_hWnd, NULL);
+	DestroyMenu(hMenu);
+
+	if (cmd == MENU_ITEM_SEL_ALL) {
+		SetFocus();
+		this->SetSel(0, -1);
+	}
+	else if (cmd == MENU_ITEM_COPY) {
+		this->Copy();
+	}
+	else if (cmd == MENU_ITEM_CLEAR) {
+		SetWindowText(_T(""));
+	}
+}
+
+void CLogEdit::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
+{
+	// 每次滚动时检查是否还在底部
+	m_bAutoScroll = IsScrollBarAtBottom();
+	CEdit::OnVScroll(nSBCode, nPos, pScrollBar);
+}
+
+BOOL CLogEdit::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
+{
+    // 每次滚动时检查是否还在底部
+    m_bAutoScroll = IsScrollBarAtBottom();
+    return CEdit::OnMouseWheel(nFlags, zDelta, pt);
+}
+
+BOOL CLogEdit::IsScrollBarAtBottom()
+{
+	SCROLLINFO si = { sizeof(si), SIF_ALL };
+	GetScrollInfo(SB_VERT, &si);
+	return (si.nPos + (int)si.nPage >= si.nMax);
+}
+
+void CLogEdit::AppendText(const char* pszText)
+{
+    SetRedraw(FALSE);
+
+    // 剪切过多行
+    int totalLines = GetLineCount();
+    if (totalLines > m_nMaxLines) {
+        int startChar = LineIndex(0);
+        int endChar = LineIndex(m_nTrimLines);
+        if (startChar >= 0 && endChar > startChar) {
+            SetSel(startChar, endChar);
+            ReplaceSel(_T(""));
+        }
+    }
+
+    // 保存当前选择
+    int start, end;
+    GetSel(start, end);
+    bool hasSelection = (start != end);
+
+    int endPos = GetWindowTextLength();
+    SetSel(endPos, endPos);
+    ReplaceSel(pszText);
+
+    if (m_bAutoScroll && !hasSelection) {
+        LineScroll(GetLineCount());
+    }
+
+    // 恢复选择
+    if (hasSelection) {
+        SetSel(start, end);
+    }
+
+    SetRedraw(TRUE);
+
+    if (m_bAutoScroll && !hasSelection) {
+        Invalidate();
+        UpdateWindow();
+    }
+}
diff --git a/SourceCode/Bond/EAPSimulator/LogEdit.h b/SourceCode/Bond/EAPSimulator/LogEdit.h
new file mode 100644
index 0000000..617b444
--- /dev/null
+++ b/SourceCode/Bond/EAPSimulator/LogEdit.h
@@ -0,0 +1,26 @@
+#pragma once
+#include "afxwin.h"
+class CLogEdit :
+	public CEdit
+{
+public:
+	CLogEdit();
+	~CLogEdit();
+
+public:
+	void SetMaxLineCount(int line);
+	void AppendText(const char* pszText);
+	BOOL IsScrollBarAtBottom();
+
+private:
+	int m_nMaxLines;
+	int m_nTrimLines;
+	BOOL m_bAutoScroll;		// 是否自动滚动
+
+	DECLARE_MESSAGE_MAP()
+	afx_msg void OnContextMenu(CWnd* pWnd, CPoint point);
+	afx_msg void OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
+public:
+	afx_msg BOOL OnMouseWheel(UINT nFlags, short zDelta, CPoint pt);
+};
+
diff --git a/SourceCode/Bond/EAPSimulator/Resource.h b/SourceCode/Bond/EAPSimulator/Resource.h
new file mode 100644
index 0000000..fda0a5c
--- /dev/null
+++ b/SourceCode/Bond/EAPSimulator/Resource.h
@@ -0,0 +1,58 @@
+锘�//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ 鐢熸垚鐨勫寘鍚枃浠躲��
+// 渚� EAPSimulator.rc 浣跨敤
+//
+#define IDM_ABOUTBOX                    0x0010
+#define IDD_ABOUTBOX                    100
+#define IDS_ABOUTBOX                    101
+#define IDD_EAPSIMULATOR_DIALOG         102
+#define IDR_MAINFRAME                   128
+#define IDD_DIALOG_TERMINAL_DISPLAY     129
+#define IDD_DIALOG_ED_EVENT_REPORT      131
+#define IDD_DIALOG_DEFINE_REPORTS       133
+#define IDD_DIALOG_ADD_IDS              135
+#define IDD_DIALOG_LINK_REPORT          137
+#define IDD_DIALOG_LINK_REPORT_DETAIL   139
+#define IDC_EDIT_LOG                    1000
+#define IDC_EDIT_IP                     1001
+#define IDC_EDIT_PORT                   1002
+#define IDC_BUTTON_CONNECT              1003
+#define IDC_BUTTON_DISCONNECT           1004
+#define IDC_BUTTON_ARE_YOU_THERE        1005
+#define IDC_BUTTON_DATETIME_SYNC        1006
+#define IDC_BUTTON_TERMINAL_DISPLAY     1007
+#define IDC_COMBO_TID                   1008
+#define IDC_BUTTON_ED_EVENT_REPORT      1008
+#define IDC_EDIT_TEXT                   1009
+#define IDC_BUTTON_ED_ALARM_REPORT      1009
+#define IDC_BUTTON_SEND                 1010
+#define IDC_BUTTON_DEFINE_REPORT        1010
+#define IDC_BUTTON_LINE_REPORT          1011
+#define IDC_RADIO_ENABLE                1012
+#define IDC_BUTTON_LINE_REPORT2         1012
+#define IDC_BUTTON_CONFIGURE_SPOOLING   1012
+#define IDC_RADIO_DISABLE               1013
+#define IDC_EDIT_CEID                   1014
+#define IDC_LIST1                       1015
+#define IDC_EDIT_CE_NAME                1015
+#define IDC_LIST2                       1016
+#define IDC_EDIT_CE_DESCRIPTIONS        1016
+#define IDC_BUTTON_ADD_RPTID            1017
+#define IDC_EDIT_CE_RPTID               1017
+#define IDC_BUTTON_DEL_REPORT           1018
+#define IDC_BUTTON_ADD_VID              1019
+#define IDC_BUTTON_DEL_VID              1020
+#define IDC_GROUP_IDS                   1021
+#define IDC_EDIT_ID                     1022
+#define IDC_BUTTON1                     1023
+
+// Next default values for new objects
+// 
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE        141
+#define _APS_NEXT_COMMAND_VALUE         32771
+#define _APS_NEXT_CONTROL_VALUE         1025
+#define _APS_NEXT_SYMED_VALUE           101
+#endif
+#endif
diff --git a/SourceCode/Bond/EAPSimulator/framework.h b/SourceCode/Bond/EAPSimulator/framework.h
new file mode 100644
index 0000000..5672fb5
--- /dev/null
+++ b/SourceCode/Bond/EAPSimulator/framework.h
@@ -0,0 +1,49 @@
+锘�#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/EAPSimulator/pch.cpp b/SourceCode/Bond/EAPSimulator/pch.cpp
new file mode 100644
index 0000000..b6fb8f4
--- /dev/null
+++ b/SourceCode/Bond/EAPSimulator/pch.cpp
@@ -0,0 +1,5 @@
+锘�// pch.cpp: 涓庨缂栬瘧鏍囧ご瀵瑰簲鐨勬簮鏂囦欢
+
+#include "pch.h"
+
+// 褰撲娇鐢ㄩ缂栬瘧鐨勫ご鏃讹紝闇�瑕佷娇鐢ㄦ婧愭枃浠讹紝缂栬瘧鎵嶈兘鎴愬姛銆�
diff --git a/SourceCode/Bond/EAPSimulator/pch.h b/SourceCode/Bond/EAPSimulator/pch.h
new file mode 100644
index 0000000..776d342
--- /dev/null
+++ b/SourceCode/Bond/EAPSimulator/pch.h
@@ -0,0 +1,17 @@
+锘�// pch.h: 杩欐槸棰勭紪璇戞爣澶存枃浠躲��
+// 涓嬫柟鍒楀嚭鐨勬枃浠朵粎缂栬瘧涓�娆★紝鎻愰珮浜嗗皢鏉ョ敓鎴愮殑鐢熸垚鎬ц兘銆�
+// 杩欒繕灏嗗奖鍝� IntelliSense 鎬ц兘锛屽寘鎷唬鐮佸畬鎴愬拰璁稿浠g爜娴忚鍔熻兘銆�
+// 浣嗘槸锛屽鏋滄澶勫垪鍑虹殑鏂囦欢涓殑浠讳綍涓�涓湪鐢熸垚涔嬮棿鏈夋洿鏂帮紝瀹冧滑鍏ㄩ儴閮藉皢琚噸鏂扮紪璇戙��
+// 璇峰嬁鍦ㄦ澶勬坊鍔犺棰戠箒鏇存柊鐨勬枃浠讹紝杩欏皢浣垮緱鎬ц兘浼樺娍鏃犳晥銆�
+
+#ifndef PCH_H
+#define PCH_H
+
+// 娣诲姞瑕佸湪姝ゅ棰勭紪璇戠殑鏍囧ご
+#include "framework.h"
+
+#include "..\RxWindows1.0\include\RxWindowsLib.h"
+#include "..\HSMSSDK\Include\HSMSSDK.h"
+
+
+#endif //PCH_H
diff --git a/SourceCode/Bond/EAPSimulator/res/EAPSimulator.ico b/SourceCode/Bond/EAPSimulator/res/EAPSimulator.ico
new file mode 100644
index 0000000..1b0c1f2
--- /dev/null
+++ b/SourceCode/Bond/EAPSimulator/res/EAPSimulator.ico
Binary files differ
diff --git a/SourceCode/Bond/EAPSimulator/res/EAPSimulator.rc2 b/SourceCode/Bond/EAPSimulator/res/EAPSimulator.rc2
new file mode 100644
index 0000000..8144dfe
--- /dev/null
+++ b/SourceCode/Bond/EAPSimulator/res/EAPSimulator.rc2
Binary files differ
diff --git a/SourceCode/Bond/EAPSimulator/res/application.exe.manifest b/SourceCode/Bond/EAPSimulator/res/application.exe.manifest
new file mode 100644
index 0000000..b96c40d
--- /dev/null
+++ b/SourceCode/Bond/EAPSimulator/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/EAPSimulator/targetver.h b/SourceCode/Bond/EAPSimulator/targetver.h
new file mode 100644
index 0000000..79934a3
--- /dev/null
+++ b/SourceCode/Bond/EAPSimulator/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/GangBond2860.sln b/SourceCode/Bond/GangBond2860.sln
index 4b90a5f..e73e6fb 100644
--- a/SourceCode/Bond/GangBond2860.sln
+++ b/SourceCode/Bond/GangBond2860.sln
@@ -1,7 +1,7 @@
 锘�
 Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 14
-VisualStudioVersion = 14.0.23107.0
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.31729.503
 MinimumVisualStudioVersion = 10.0.40219.1
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BEQLibrary", "BEQLibrary\BEQLibrary.vcxproj", "{8421CE64-06F9-48F4-A3F3-ACFB683C94D4}"
 EndProject
@@ -14,6 +14,8 @@
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Servo", "Servo\Servo.vcxproj", "{66ADACE5-3166-4D1F-B30B-DE5E01FB01A2}"
 EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BoounionPLC", "BoounionPLC\BoounionPLC.vcxproj", "{6DC0600E-5588-4033-A281-3626A4F74B67}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "EAPSimulator", "EAPSimulator\EAPSimulator.vcxproj", "{9EA43050-B71C-47A7-AC90-F0D7A88C5F50}"
 EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -71,6 +73,14 @@
 		{6DC0600E-5588-4033-A281-3626A4F74B67}.Release|x64.Build.0 = Release|x64
 		{6DC0600E-5588-4033-A281-3626A4F74B67}.Release|x86.ActiveCfg = Release|Win32
 		{6DC0600E-5588-4033-A281-3626A4F74B67}.Release|x86.Build.0 = Release|Win32
+		{9EA43050-B71C-47A7-AC90-F0D7A88C5F50}.Debug|x64.ActiveCfg = Debug|x64
+		{9EA43050-B71C-47A7-AC90-F0D7A88C5F50}.Debug|x64.Build.0 = Debug|x64
+		{9EA43050-B71C-47A7-AC90-F0D7A88C5F50}.Debug|x86.ActiveCfg = Debug|Win32
+		{9EA43050-B71C-47A7-AC90-F0D7A88C5F50}.Debug|x86.Build.0 = Debug|Win32
+		{9EA43050-B71C-47A7-AC90-F0D7A88C5F50}.Release|x64.ActiveCfg = Release|x64
+		{9EA43050-B71C-47A7-AC90-F0D7A88C5F50}.Release|x64.Build.0 = Release|x64
+		{9EA43050-B71C-47A7-AC90-F0D7A88C5F50}.Release|x86.ActiveCfg = Release|Win32
+		{9EA43050-B71C-47A7-AC90-F0D7A88C5F50}.Release|x86.Build.0 = Release|Win32
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE
diff --git a/SourceCode/Bond/HSMSSDK/Include/HSMSSDK.h b/SourceCode/Bond/HSMSSDK/Include/HSMSSDK.h
index 4231f09..db54862 100644
--- a/SourceCode/Bond/HSMSSDK/Include/HSMSSDK.h
+++ b/SourceCode/Bond/HSMSSDK/Include/HSMSSDK.h
@@ -1,6 +1,7 @@
 #pragma once
 #include <functional>
 #include "IPassive.h"
+#include "IActive.h"
 #include "IMessage.h"
 
 
@@ -62,7 +63,10 @@
 	int				EXPORTED	HSMS_Term();
 	int				EXPORTED	HSMS_CreatePassive(OUT IPassive*& pPassive, const char* pName, const unsigned int nPort);
 	int				EXPORTED	HSMS_DestroyPassive(IPassive* pPassive);
+	int				EXPORTED	HSMS_CreateActive(OUT IActive*& pAcitve, const char* pName, const char* pszIp, const unsigned int nPort);
+	int				EXPORTED	HSMS_DestroyActive(IActive* pAcitve);
 	int				EXPORTED	HSMS_Create1Message(OUT IMessage*& pMessage, unsigned short sessionId, BYTE stream, BYTE function, unsigned int nSystemBytes);
+	int				EXPORTED	HSMS_CreateMessageWithSType(OUT IMessage*& pMessage, BYTE sType, unsigned int nSystemBytes);
 	int				EXPORTED	HSMS_Destroy1Message(IMessage* pMessage);
 
 #ifdef __cplusplus
diff --git a/SourceCode/Bond/HSMSSDK/Include/IActive.h b/SourceCode/Bond/HSMSSDK/Include/IActive.h
new file mode 100644
index 0000000..ce2f9e7
--- /dev/null
+++ b/SourceCode/Bond/HSMSSDK/Include/IActive.h
@@ -0,0 +1,41 @@
+#pragma once
+#include <functional>
+#include "IMessage.h"
+
+
+enum class ACTIVESTATE
+{
+	NOT_CONNECTED = 0,
+	NOT_SELECTED = 1,
+	SELECTED = 2
+};
+
+typedef std::function<void(void* pFrom, ACTIVESTATE state)> ONACTIVESTATECHANGED;
+typedef std::function<void(void* pFrom, const char* pszData, int size)> ONRECVRAWDATA;
+typedef std::function<void(void* pFrom, IMessage* pMessage)> ONRECVDATAMSG;
+typedef std::function<void(void* pFrom, IMessage* pMessage)> ONRECVSYSMSG;
+typedef std::function<void(void* pFrom, int error)> ONDATAERROR;
+typedef struct _ActiveListener
+{
+	ONACTIVESTATECHANGED	funStateChanged;
+	ONRECVRAWDATA			funRecvRawData;
+	ONRECVDATAMSG			funRecvDataMessage;
+	ONRECVSYSMSG			funRecvSysMessage;
+	ONDATAERROR				funError;
+} ActiveListener;
+
+
+class IActive
+{
+public:
+	virtual void setListener(ActiveListener listener) = 0;
+	virtual void setTimeout3(int timeout) = 0;
+	virtual void setTimeout5(int timeout) = 0;
+	virtual void setTimeout6(int timeout) = 0;
+	virtual void setTimeout7(int timeout) = 0;
+	virtual void setTimeout8(int timeout) = 0;
+	virtual int sendMessage(IMessage* pMessage) = 0;
+	virtual ACTIVESTATE getState() = 0;
+	virtual int connect() = 0;
+	virtual int disconnect() = 0;
+};
diff --git a/SourceCode/Bond/HSMSSDK/Include/ISECS2Item.h b/SourceCode/Bond/HSMSSDK/Include/ISECS2Item.h
index 0d4a38e..ba3f21d 100644
--- a/SourceCode/Bond/HSMSSDK/Include/ISECS2Item.h
+++ b/SourceCode/Bond/HSMSSDK/Include/ISECS2Item.h
@@ -55,7 +55,7 @@
 	virtual bool getSubItemU1(int index, unsigned char& value) = 0;
 	virtual void reset() = 0;
 	virtual ISECS2Item* addItem(const char* pszText, const char* pszNote) = 0;
-	virtual ISECS2Item* addBinaryItem(BYTE bin, const char* pszNote) = 0;
+	virtual ISECS2Item* addBinaryItem(const char* pszData, unsigned int len, const char* pszNote) = 0;
 	virtual ISECS2Item* addBoolItem(bool boolValue, const char* pszNote) = 0;
 	virtual ISECS2Item* addI8Item(long long value, const char* pszNote) = 0;
 	virtual ISECS2Item* addI4Item(int value, const char* pszNote) = 0;
@@ -68,5 +68,6 @@
 	virtual ISECS2Item* addU2Item(unsigned short value, const char* pszNote) = 0;
 	virtual ISECS2Item* addU1Item(unsigned char value, const char* pszNote) = 0;
 	virtual void setBinary(const char* pszData, unsigned int len, const char* pszNote) = 0;
+	virtual void setString(const char* pszText, const char* pszNote) = 0;
 	virtual ISECS2Item* addItem() = 0;
 };
diff --git a/SourceCode/Bond/Servo/CBonder.cpp b/SourceCode/Bond/Servo/CBonder.cpp
index c4cb52f..c4eb76c 100644
--- a/SourceCode/Bond/Servo/CBonder.cpp
+++ b/SourceCode/Bond/Servo/CBonder.cpp
@@ -419,14 +419,17 @@
 	{
 		CEquipment::onTimer(nTimerid);
 
-		// test
+		// test	 
 		/*
 		static int i[2] = { 0, 0 };
 		i[m_nIndex]++;
-
-		if (i[m_nIndex] == 15) {
-			char szBuffer[26];
-			decodeJobProcessStartReport(getStep(STEP_ID_JOB_PROCESS_START_REPORT), szBuffer, 26);
+		if (m_nIndex == 0 && i[m_nIndex] % 20 == 0) {
+			if (m_listener.onAlarm != nullptr) {
+				m_listener.onAlarm(this, 1,
+					i[m_nIndex],
+					getID(),
+					1);
+			}
 		}
 		*/
 	}
diff --git a/SourceCode/Bond/Servo/CCollectionEvent.cpp b/SourceCode/Bond/Servo/CCollectionEvent.cpp
new file mode 100644
index 0000000..a0b7773
--- /dev/null
+++ b/SourceCode/Bond/Servo/CCollectionEvent.cpp
@@ -0,0 +1,113 @@
+#include "stdafx.h"
+#include "CCollectionEvent.h"
+
+
+namespace SERVO {
+	CCollectionEvent::CCollectionEvent()
+	{
+		m_nCEID = 0;
+	}
+
+	CCollectionEvent::CCollectionEvent(unsigned int id, const char* pszName, const char* pszDescription, std::vector<unsigned int>& prtids)
+	{
+		m_nCEID = id;
+		m_strName = pszName;
+		m_strDescription = pszDescription;
+		for (auto item : prtids) {
+			m_rptids.push_back(item);
+		}
+	}
+
+	CCollectionEvent::~CCollectionEvent()
+	{
+
+	}
+
+	unsigned int CCollectionEvent::getEventId()
+	{
+		return m_nCEID;
+	}
+
+	std::string& CCollectionEvent::getName()
+	{
+		return m_strName;
+	}
+
+	std::string& CCollectionEvent::getDescription()
+	{
+		return m_strDescription;
+	}
+
+	BOOL CCollectionEvent::addReport(CReport* pReport)
+	{
+		ASSERT(pReport);
+		if (getReport(pReport->getReportId()) != nullptr) {
+			return FALSE;
+		}
+
+		m_reports.push_back(pReport);
+		return TRUE;
+	}
+
+	void CCollectionEvent::setReport(CReport* pReport)
+	{
+		m_rptids.clear();
+		m_reports.clear();
+		if (pReport != nullptr) {
+			m_rptids.push_back(pReport->getReportId());
+			m_reports.push_back(pReport);
+		}
+	}
+
+	unsigned int CCollectionEvent::getPortID()
+	{
+		if (m_reports.empty()) return -1;
+		return m_reports.front()->getReportId();
+	}
+
+	BOOL CCollectionEvent::deleteReport(unsigned int nReportId)
+	{
+		BOOL bDelete = FALSE;
+		for (auto iter = m_reports.begin(); iter != m_reports.end(); ++iter) {
+			if (nReportId == (*iter)->getReportId()) {
+				m_reports.erase(iter);
+				bDelete = TRUE;
+				break;
+			}
+		}
+
+		return bDelete;
+	}
+
+	CReport* CCollectionEvent::getReport(unsigned int nReportId)
+	{
+		for (auto item : m_reports) {
+			if (nReportId == item->getReportId()) {
+				return item;
+			}
+		}
+
+		return nullptr;
+	}
+
+	std::vector<CReport*>& CCollectionEvent::getReports()
+	{
+		return m_reports;
+	}
+
+	std::string CCollectionEvent::getReportIdsText()
+	{
+		std::string strResult, strName;
+		for (int i = 0; i < m_rptids.size(); i++) {
+			strResult += std::to_string(m_rptids[i]);// (getReport(m_rptids[i]) ?
+			if (nullptr == getReport(m_rptids[i])) {
+				strResult += "?";
+			}
+			if (i != m_rptids.size() - 1) {
+				strResult += ",";
+			}
+		}
+
+		return strResult;
+	}
+}
diff --git a/SourceCode/Bond/Servo/CCollectionEvent.h b/SourceCode/Bond/Servo/CCollectionEvent.h
new file mode 100644
index 0000000..bfad5fb
--- /dev/null
+++ b/SourceCode/Bond/Servo/CCollectionEvent.h
@@ -0,0 +1,34 @@
+#pragma once
+#include "CReport.h"
+#include <vector>
+
+
+namespace SERVO {
+	class CCollectionEvent
+	{
+	public:
+		CCollectionEvent();
+		CCollectionEvent(unsigned int id, const char* pszName, const char* pszDescription, std::vector<unsigned int>& prtids);
+		virtual ~CCollectionEvent();
+
+	public:
+		unsigned int getEventId();
+		std::string& getName();
+		std::string& getDescription();
+		std::vector<CReport*>& getReports();
+		std::string getReportIdsText();
+		BOOL addReport(CReport* pReport);
+		BOOL deleteReport(unsigned int nReportId);
+		CReport* getReport(unsigned int nReportId);
+
+		/* 如果一个CEID只有一个Report的场景,调用此函数设置或取消 */
+		void setReport(CReport* pReport);
+		unsigned int getPortID();
+	private:
+		unsigned int m_nCEID;
+		std::string m_strName;
+		std::string m_strDescription;
+		std::vector<unsigned int> m_rptids;
+		std::vector<CReport*> m_reports;
+	};
+}
diff --git a/SourceCode/Bond/Servo/CMaster.cpp b/SourceCode/Bond/Servo/CMaster.cpp
index 9b78a9a..f1b3b26 100644
--- a/SourceCode/Bond/Servo/CMaster.cpp
+++ b/SourceCode/Bond/Servo/CMaster.cpp
@@ -52,6 +52,8 @@
 		m_pActiveRobotTask = nullptr;
 		m_nLastError = 0;
 		m_isCompareMapsBeforeProceeding = FALSE;
+		m_bEnableEventReport = true;
+		m_bEnableAlarmReport = true;
 		InitializeCriticalSection(&m_criticalSection);
 	}
 
@@ -1503,4 +1505,27 @@
 	{
 		m_isCompareMapsBeforeProceeding = bCompare;
 	}
+
+	void CMaster::datetimeSync(SYSTEMTIME& time)
+	{
+		for (auto item : m_listEquipment) {
+			item->setDateTime(time.wYear, time.wMonth, time.wDay,
+				time.wHour, time.wMinute, time.wSecond);
+		}
+	}
+
+	void CMaster::enableEventReport(bool bEnable)
+	{
+		m_bEnableEventReport = bEnable;
+	}
+
+	void CMaster::enableAlarmReport(bool bEnable)
+	{
+		m_bEnableAlarmReport = bEnable;
+	}
+
+	bool CMaster::isAlarmReportEnable()
+	{
+		return m_bEnableAlarmReport;
+	}
 }
diff --git a/SourceCode/Bond/Servo/CMaster.h b/SourceCode/Bond/Servo/CMaster.h
index 57756d0..fb040fc 100644
--- a/SourceCode/Bond/Servo/CMaster.h
+++ b/SourceCode/Bond/Servo/CMaster.h
@@ -74,6 +74,10 @@
             int cassetteType, int transferMode, BOOL autoChangeEnable);
         void setPortCassetteType(unsigned int index, SERVO::CassetteType type);
         void setCompareMapsBeforeProceeding(BOOL bCompare);
+        void datetimeSync(SYSTEMTIME& time);
+        void enableEventReport(bool bEnable);
+        void enableAlarmReport(bool bEnable);
+        bool isAlarmReportEnable();
 
     private:
         inline void lock() { EnterCriticalSection(&m_criticalSection); }
@@ -102,7 +106,7 @@
         CRobotTask* createTransferTask_bake_to_cooling(CEquipment* pSrcEq);
         CRobotTask* createTransferTask_bakecooling_to_measurement(CEquipment* pSrcEq, CEquipment* pTarEq);
         CRobotTask* createTransferTask_restore(CEquipment* pEqSrc, CLoadPort** pPorts);
- 
+
     private:
         CRITICAL_SECTION m_criticalSection;
         MasterListener m_listener;
@@ -138,6 +142,9 @@
 
         // 在开始工艺前是否先需要先比较map
         BOOL m_isCompareMapsBeforeProceeding;
+    private:
+        bool m_bEnableEventReport;
+        bool m_bEnableAlarmReport;
     };
 }
 
diff --git a/SourceCode/Bond/Servo/CMyStatusbar.cpp b/SourceCode/Bond/Servo/CMyStatusbar.cpp
index d0ab4fe..589a8cc 100644
--- a/SourceCode/Bond/Servo/CMyStatusbar.cpp
+++ b/SourceCode/Bond/Servo/CMyStatusbar.cpp
@@ -75,6 +75,11 @@
 	SetDlgItemText(IDC_BUTTON_ROBOTTASK, pszText);
 }
 
+void CMyStatusbar::setCimBtnText(const char* pszText)
+{
+	SetDlgItemText(IDC_BUTTON_CIM, pszText);
+}
+
 BOOL CMyStatusbar::OnInitDialog()
 {
 	CDialogEx::OnInitDialog();
@@ -87,6 +92,11 @@
 	m_btnCurTask.SetFrameColor(BS_HOVER, RGB(218, 218, 218));
 	m_btnCurTask.SetFrameColor(BS_PRESS, RGB(168, 168, 168));
 
+	m_btnCim.SubclassDlgItem(IDC_BUTTON_CIM, this);
+	m_btnCim.SetFaceColor(m_crBkgnd);
+	m_btnCim.SetFrameColor(m_crBkgnd);
+	m_btnCim.SetFrameColor(BS_HOVER, RGB(218, 218, 218));
+	m_btnCim.SetFrameColor(BS_PRESS, RGB(168, 168, 168));
 
 	return TRUE;  // return TRUE unless you set the focus to a control
 				  // 寮傚父: OCX 灞炴�ч〉搴旇繑鍥� FALSE
@@ -129,6 +139,11 @@
 		pItem->GetWindowRect(rcItem);
 		GetParent()->SendMessage(ID_MSG_STATUSBAR_BTN_CLICKED, rcItem.left, LOWORD(wParam));
 		break;
+	case IDC_BUTTON_CIM:
+		pItem = GetDlgItem(IDC_BUTTON_CIM);
+		pItem->GetWindowRect(rcItem);
+		GetParent()->SendMessage(ID_MSG_STATUSBAR_BTN_CLICKED, rcItem.left, LOWORD(wParam));
+		break;
 	}
 
 	return CDialogEx::OnCommand(wParam, lParam);
@@ -165,4 +180,16 @@
 	pItem->GetClientRect(rcItem);
 	pItem->MoveWindow(x, (rcClient.Height() - rcItem.Height()) / 2, rcItem.Width(), rcItem.Height());
 	x += rcItem.Width();
+
+	x += 8;
+	pItem = GetDlgItem(IDC_LABEL_CIM);
+	pItem->GetClientRect(rcItem);
+	pItem->MoveWindow(x, (rcClient.Height() - rcItem.Height()) / 2, rcItem.Width(), rcItem.Height());
+	x += rcItem.Width();
+
+	x += 8;
+	pItem = GetDlgItem(IDC_BUTTON_CIM);
+	pItem->GetClientRect(rcItem);
+	pItem->MoveWindow(x, (rcClient.Height() - rcItem.Height()) / 2, rcItem.Width(), rcItem.Height());
+	x += rcItem.Width();
 }
\ No newline at end of file
diff --git a/SourceCode/Bond/Servo/CMyStatusbar.h b/SourceCode/Bond/Servo/CMyStatusbar.h
index 08c6c1f..4afaaa4 100644
--- a/SourceCode/Bond/Servo/CMyStatusbar.h
+++ b/SourceCode/Bond/Servo/CMyStatusbar.h
@@ -21,6 +21,7 @@
 	void setForegroundColor(COLORREF cr);
 	void setRunTimeText(const char* pszText);
 	void setCurTaskBtnText(const char* pszText);
+	void setCimBtnText(const char* pszText);
 
 private:
 	void Resize();
@@ -30,6 +31,7 @@
 	COLORREF m_crBkgnd;
 	CBrush m_brBkgnd;
 	CBlButton m_btnCurTask;
+	CBlButton m_btnCim;
 
 // 瀵硅瘽妗嗘暟鎹�
 #ifdef AFX_DESIGN_TIME
diff --git a/SourceCode/Bond/Servo/CPageCollectionEvent.cpp b/SourceCode/Bond/Servo/CPageCollectionEvent.cpp
new file mode 100644
index 0000000..a7108fb
--- /dev/null
+++ b/SourceCode/Bond/Servo/CPageCollectionEvent.cpp
@@ -0,0 +1,126 @@
+锘�// CPageCollectionEvent.cpp: 瀹炵幇鏂囦欢
+//
+
+#include "stdafx.h"
+#include "Servo.h"
+#include "CPageCollectionEvent.h"
+#include "afxdialogex.h"
+
+
+// CPageCollectionEvent 瀵硅瘽妗�
+
+IMPLEMENT_DYNAMIC(CPageCollectionEvent, CHMPropertyPage)
+
+CPageCollectionEvent::CPageCollectionEvent(CWnd* pParent /*=nullptr*/)
+	: CHMPropertyPage(IDD_PAGE_COLLECTION_EVENT, pParent)
+{
+
+}
+
+CPageCollectionEvent::~CPageCollectionEvent()
+{
+}
+
+void CPageCollectionEvent::DoDataExchange(CDataExchange* pDX)
+{
+	CDialogEx::DoDataExchange(pDX);
+	DDX_Control(pDX, IDC_LIST1, m_listCtrl);
+}
+
+
+BEGIN_MESSAGE_MAP(CPageCollectionEvent, CHMPropertyPage)
+	ON_WM_CTLCOLOR()
+	ON_WM_DESTROY()
+	ON_WM_SIZE()
+END_MESSAGE_MAP()
+
+
+// CPageCollectionEvent 娑堟伅澶勭悊绋嬪簭
+
+
+BOOL CPageCollectionEvent::OnInitDialog()
+{
+	CHMPropertyPage::OnInitDialog();
+
+	// 璇诲嚭鍒楀
+	CString strIniFile, strItem;
+	strIniFile.Format(_T("%s\\configuration.ini"), (LPTSTR)(LPCTSTR)theApp.m_strAppDir);
+	int width[8] = { 0, 218, 180, 180, 180, 180, 180, 180 };
+	for (int i = 0; i < 8; i++) {
+		strItem.Format(_T("Col_%d_Width"), i);
+		width[i] = GetPrivateProfileInt("PageCollectionListCtrl", strItem, width[i], strIniFile);
+	}
+
+
+	// 鎶ヨ〃鎺т欢
+	DWORD dwStyle = m_listCtrl.GetExtendedStyle();
+	dwStyle |= LVS_EX_FULLROWSELECT;
+	dwStyle |= LVS_EX_GRIDLINES;
+	m_listCtrl.SetExtendedStyle(dwStyle);
+
+	HIMAGELIST imageList = ImageList_Create(24, 24, ILC_COLOR24, 1, 1);
+	ListView_SetImageList(m_listCtrl.GetSafeHwnd(), imageList, LVSIL_SMALL);
+	m_listCtrl.InsertColumn(0, _T(""), LVCFMT_RIGHT, width[0]);
+	m_listCtrl.InsertColumn(1, _T("CEID"), LVCFMT_LEFT, width[1]);
+	m_listCtrl.InsertColumn(2, _T("CE Name"), LVCFMT_LEFT, width[2]);
+	m_listCtrl.InsertColumn(3, _T("Descriptions"), LVCFMT_LEFT, width[3]);
+	m_listCtrl.InsertColumn(4, _T("Attached RPTID"), LVCFMT_LEFT, width[4]);
+	loadCollectionEvents();
+
+	return TRUE;  // return TRUE unless you set the focus to a control
+				  // 寮傚父: OCX 灞炴�ч〉搴旇繑鍥� FALSE
+}
+
+
+HBRUSH CPageCollectionEvent::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
+{
+	HBRUSH hbr = CHMPropertyPage::OnCtlColor(pDC, pWnd, nCtlColor);
+
+	// TODO:  鍦ㄦ鏇存敼 DC 鐨勪换浣曠壒鎬�
+
+	// TODO:  濡傛灉榛樿鐨勪笉鏄墍闇�鐢荤瑪锛屽垯杩斿洖鍙︿竴涓敾绗�
+	return hbr;
+}
+
+
+void CPageCollectionEvent::OnDestroy()
+{
+	CHMPropertyPage::OnDestroy();
+
+	// 淇濆瓨鍒楀
+	CString strIniFile, strItem, strTemp;
+	strIniFile.Format(_T("%s\\configuration.ini"), (LPTSTR)(LPCTSTR)theApp.m_strAppDir);
+	CHeaderCtrl* pHeader = m_listCtrl.GetHeaderCtrl();
+	for (int i = 0; i < pHeader->GetItemCount(); i++) {
+		RECT rect;
+		pHeader->GetItemRect(i, &rect);
+		strItem.Format(_T("Col_%d_Width"), i);
+		strTemp.Format(_T("%d"), rect.right - rect.left);
+		WritePrivateProfileString("PageCollectionListCtrl", strItem, strTemp, strIniFile);
+	}
+}
+
+
+void CPageCollectionEvent::OnSize(UINT nType, int cx, int cy)
+{
+	CHMPropertyPage::OnSize(nType, cx, cy);
+	if (GetDlgItem(IDC_LIST1) == nullptr) return;
+
+	CWnd* pItem;
+	CRect rcClient, rcItem;
+	GetClientRect(&rcClient);
+	m_listCtrl.MoveWindow(12, 12, rcClient.Width() - 24, rcClient.Height() - 24);
+}
+
+void CPageCollectionEvent::loadCollectionEvents()
+{
+	auto& collectionEvent = theApp.m_model.m_hsmsPassive.getCollectionEvents();
+	for (auto item : collectionEvent) {
+		int index = m_listCtrl.InsertItem(m_listCtrl.GetItemCount(), _T(""));
+		m_listCtrl.SetItemData(index, (DWORD_PTR)item);
+		m_listCtrl.SetItemText(index, 1, std::to_string(item->getEventId()).c_str());
+		m_listCtrl.SetItemText(index, 2, item->getName().c_str());
+		m_listCtrl.SetItemText(index, 3, item->getDescription().c_str());
+		m_listCtrl.SetItemText(index, 4, item->getReportIdsText().c_str());
+	}
+}
diff --git a/SourceCode/Bond/Servo/CPageCollectionEvent.h b/SourceCode/Bond/Servo/CPageCollectionEvent.h
new file mode 100644
index 0000000..7332a09
--- /dev/null
+++ b/SourceCode/Bond/Servo/CPageCollectionEvent.h
@@ -0,0 +1,34 @@
+锘�#pragma once
+#include "CHMPropertyPage.h"
+#include "ListCtrlEx.h"
+
+
+// CPageCollectionEvent 瀵硅瘽妗�
+
+class CPageCollectionEvent : public CHMPropertyPage
+{
+	DECLARE_DYNAMIC(CPageCollectionEvent)
+
+public:
+	CPageCollectionEvent(CWnd* pParent = nullptr);   // 鏍囧噯鏋勯�犲嚱鏁�
+	virtual ~CPageCollectionEvent();
+	void loadCollectionEvents();
+
+private:
+	CListCtrlEx m_listCtrl;
+
+// 瀵硅瘽妗嗘暟鎹�
+#ifdef AFX_DESIGN_TIME
+	enum { IDD = IDD_PAGE_COLLECTION_EVENT };
+#endif
+
+protected:
+	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 鏀寔
+
+	DECLARE_MESSAGE_MAP()
+public:
+	virtual BOOL OnInitDialog();
+	afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor);
+	afx_msg void OnDestroy();
+	afx_msg void OnSize(UINT nType, int cx, int cy);
+};
diff --git a/SourceCode/Bond/Servo/CPageReport.cpp b/SourceCode/Bond/Servo/CPageReport.cpp
new file mode 100644
index 0000000..94f55b8
--- /dev/null
+++ b/SourceCode/Bond/Servo/CPageReport.cpp
@@ -0,0 +1,126 @@
+锘�// CPageReport.cpp: 瀹炵幇鏂囦欢
+//
+
+#include "stdafx.h"
+#include "Servo.h"
+#include "CPageReport.h"
+#include "afxdialogex.h"
+
+
+// CPageReport 瀵硅瘽妗�
+
+IMPLEMENT_DYNAMIC(CPageReport, CHMPropertyPage)
+
+CPageReport::CPageReport(CWnd* pParent /*=nullptr*/)
+	: CHMPropertyPage(IDD_PAGE_REPORT, pParent)
+{
+
+}
+
+CPageReport::~CPageReport()
+{
+}
+
+void CPageReport::DoDataExchange(CDataExchange* pDX)
+{
+	CHMPropertyPage::DoDataExchange(pDX);
+	DDX_Control(pDX, IDC_LIST1, m_listCtrl);
+}
+
+
+BEGIN_MESSAGE_MAP(CPageReport, CHMPropertyPage)
+	ON_WM_CTLCOLOR()
+	ON_WM_DESTROY()
+	ON_WM_SIZE()
+END_MESSAGE_MAP()
+
+
+// CPageReport 娑堟伅澶勭悊绋嬪簭
+
+
+BOOL CPageReport::OnInitDialog()
+{
+	CHMPropertyPage::OnInitDialog();
+
+
+	// 璇诲嚭鍒楀
+	CString strIniFile, strItem;
+	strIniFile.Format(_T("%s\\configuration.ini"), (LPTSTR)(LPCTSTR)theApp.m_strAppDir);
+	int width[8] = { 0, 218, 180, 180, 180, 180, 180, 180 };
+	for (int i = 0; i < 8; i++) {
+		strItem.Format(_T("Col_%d_Width"), i);
+		width[i] = GetPrivateProfileInt("PageReportListCtrl", strItem, width[i], strIniFile);
+	}
+
+
+	// 鎶ヨ〃鎺т欢
+	DWORD dwStyle = m_listCtrl.GetExtendedStyle();
+	dwStyle |= LVS_EX_FULLROWSELECT;
+	dwStyle |= LVS_EX_GRIDLINES;
+	m_listCtrl.SetExtendedStyle(dwStyle);
+
+	HIMAGELIST imageList = ImageList_Create(24, 24, ILC_COLOR24, 1, 1);
+	ListView_SetImageList(m_listCtrl.GetSafeHwnd(), imageList, LVSIL_SMALL);
+	m_listCtrl.InsertColumn(0, _T(""), LVCFMT_RIGHT, width[0]);
+	m_listCtrl.InsertColumn(1, _T("RPT ID"), LVCFMT_LEFT, width[1]);
+	m_listCtrl.InsertColumn(2, _T("VID"), LVCFMT_LEFT, width[2]);
+	loadReports();
+
+	return TRUE;  // return TRUE unless you set the focus to a control
+				  // 寮傚父: OCX 灞炴�ч〉搴旇繑鍥� FALSE
+
+	return TRUE;  // return TRUE unless you set the focus to a control
+				  // 寮傚父: OCX 灞炴�ч〉搴旇繑鍥� FALSE
+}
+
+
+HBRUSH CPageReport::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
+{
+	HBRUSH hbr = CHMPropertyPage::OnCtlColor(pDC, pWnd, nCtlColor);
+
+	// TODO:  鍦ㄦ鏇存敼 DC 鐨勪换浣曠壒鎬�
+
+	// TODO:  濡傛灉榛樿鐨勪笉鏄墍闇�鐢荤瑪锛屽垯杩斿洖鍙︿竴涓敾绗�
+	return hbr;
+}
+
+
+void CPageReport::OnDestroy()
+{
+	CHMPropertyPage::OnDestroy();
+
+	// 淇濆瓨鍒楀
+	CString strIniFile, strItem, strTemp;
+	strIniFile.Format(_T("%s\\configuration.ini"), (LPTSTR)(LPCTSTR)theApp.m_strAppDir);
+	CHeaderCtrl* pHeader = m_listCtrl.GetHeaderCtrl();
+	for (int i = 0; i < pHeader->GetItemCount(); i++) {
+		RECT rect;
+		pHeader->GetItemRect(i, &rect);
+		strItem.Format(_T("Col_%d_Width"), i);
+		strTemp.Format(_T("%d"), rect.right - rect.left);
+		WritePrivateProfileString("PageReportListCtrl", strItem, strTemp, strIniFile);
+	}
+}
+
+
+void CPageReport::OnSize(UINT nType, int cx, int cy)
+{
+	CHMPropertyPage::OnSize(nType, cx, cy);
+	if (GetDlgItem(IDC_LIST1) == nullptr) return;
+
+	CWnd* pItem;
+	CRect rcClient, rcItem;
+	GetClientRect(&rcClient);
+	m_listCtrl.MoveWindow(12, 12, rcClient.Width() - 24, rcClient.Height() - 24);
+}
+
+void CPageReport::loadReports()
+{
+	auto& reports = theApp.m_model.m_hsmsPassive.getReports();
+	for (auto item : reports) {
+		int index = m_listCtrl.InsertItem(m_listCtrl.GetItemCount(), _T(""));
+		m_listCtrl.SetItemData(index, (DWORD_PTR)item);
+		m_listCtrl.SetItemText(index, 1, std::to_string(item->getReportId()).c_str());
+		m_listCtrl.SetItemText(index, 2, item->getVariablesIdsText().c_str());
+	}
+}
diff --git a/SourceCode/Bond/Servo/CPageReport.h b/SourceCode/Bond/Servo/CPageReport.h
new file mode 100644
index 0000000..716ac0b
--- /dev/null
+++ b/SourceCode/Bond/Servo/CPageReport.h
@@ -0,0 +1,34 @@
+锘�#pragma once
+#include "CHMPropertyPage.h"
+#include "ListCtrlEx.h"
+
+
+// CPageReport 瀵硅瘽妗�
+
+class CPageReport : public CHMPropertyPage
+{
+	DECLARE_DYNAMIC(CPageReport)
+
+public:
+	CPageReport(CWnd* pParent = nullptr);   // 鏍囧噯鏋勯�犲嚱鏁�
+	virtual ~CPageReport();
+	void loadReports();
+
+private:
+	CListCtrlEx m_listCtrl;
+
+// 瀵硅瘽妗嗘暟鎹�
+#ifdef AFX_DESIGN_TIME
+	enum { IDD = IDD_PAGE_REPORT };
+#endif
+
+protected:
+	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 鏀寔
+
+	DECLARE_MESSAGE_MAP()
+public:
+	virtual BOOL OnInitDialog();
+	afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor);
+	afx_msg void OnDestroy();
+	afx_msg void OnSize(UINT nType, int cx, int cy);
+};
diff --git a/SourceCode/Bond/Servo/CPageVarialbles.cpp b/SourceCode/Bond/Servo/CPageVarialbles.cpp
new file mode 100644
index 0000000..415a5dc
--- /dev/null
+++ b/SourceCode/Bond/Servo/CPageVarialbles.cpp
@@ -0,0 +1,133 @@
+锘�// CPageVarialbles.cpp: 瀹炵幇鏂囦欢
+//
+
+#include "stdafx.h"
+#include "Servo.h"
+#include "CPageVarialbles.h"
+#include "afxdialogex.h"
+
+
+// CPageVarialbles 瀵硅瘽妗�
+
+IMPLEMENT_DYNAMIC(CPageVarialbles, CHMPropertyPage)
+
+CPageVarialbles::CPageVarialbles(CWnd* pParent /*=nullptr*/)
+	: CHMPropertyPage(IDD_PAGE_VARIABLE, pParent)
+{
+
+}
+
+CPageVarialbles::~CPageVarialbles()
+{
+}
+
+void CPageVarialbles::DoDataExchange(CDataExchange* pDX)
+{
+	CHMPropertyPage::DoDataExchange(pDX);
+	DDX_Control(pDX, IDC_LIST1, m_listCtrl);
+}
+
+
+BEGIN_MESSAGE_MAP(CPageVarialbles, CHMPropertyPage)
+	ON_WM_CTLCOLOR()
+	ON_WM_DESTROY()
+	ON_WM_SIZE()
+END_MESSAGE_MAP()
+
+
+// CPageVarialbles 娑堟伅澶勭悊绋嬪簭
+
+
+BOOL CPageVarialbles::OnInitDialog()
+{
+	CHMPropertyPage::OnInitDialog();
+
+
+	// 璇诲嚭鍒楀
+	CString strIniFile, strItem;
+	strIniFile.Format(_T("%s\\configuration.ini"), (LPTSTR)(LPCTSTR)theApp.m_strAppDir);
+	int width[8] = { 0, 218, 180, 180, 180, 180, 180, 180 };
+	for (int i = 0; i < 8; i++) {
+		strItem.Format(_T("Col_%d_Width"), i);
+		width[i] = GetPrivateProfileInt("PageVariableListCtrl", strItem, width[i], strIniFile);
+	}
+
+
+	// 鎶ヨ〃鎺т欢
+	DWORD dwStyle = m_listCtrl.GetExtendedStyle();
+	dwStyle |= LVS_EX_FULLROWSELECT;
+	dwStyle |= LVS_EX_GRIDLINES;
+	m_listCtrl.SetExtendedStyle(dwStyle);
+
+	HIMAGELIST imageList = ImageList_Create(24, 24, ILC_COLOR24, 1, 1);
+	ListView_SetImageList(m_listCtrl.GetSafeHwnd(), imageList, LVSIL_SMALL);
+	m_listCtrl.InsertColumn(0, _T(""), LVCFMT_RIGHT, width[0]);
+	m_listCtrl.InsertColumn(1, _T("SV ID"), LVCFMT_LEFT, width[1]);
+	m_listCtrl.InsertColumn(2, _T("SV Name"), LVCFMT_LEFT, width[2]);
+	m_listCtrl.InsertColumn(3, _T("SV Format"), LVCFMT_LEFT, width[3]);
+	m_listCtrl.InsertColumn(4, _T("SV Remark"), LVCFMT_LEFT, width[4]);
+	loadVariables();
+
+	return TRUE;  // return TRUE unless you set the focus to a control
+				  // 寮傚父: OCX 灞炴�ч〉搴旇繑鍥� FALSE
+}
+
+
+HBRUSH CPageVarialbles::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
+{
+	HBRUSH hbr = CHMPropertyPage::OnCtlColor(pDC, pWnd, nCtlColor);
+
+	// TODO:  鍦ㄦ鏇存敼 DC 鐨勪换浣曠壒鎬�
+
+	// TODO:  濡傛灉榛樿鐨勪笉鏄墍闇�鐢荤瑪锛屽垯杩斿洖鍙︿竴涓敾绗�
+	return hbr;
+}
+
+
+void CPageVarialbles::OnDestroy()
+{
+	CHMPropertyPage::OnDestroy();
+
+	// 淇濆瓨鍒楀
+	CString strIniFile, strItem, strTemp;
+	strIniFile.Format(_T("%s\\configuration.ini"), (LPTSTR)(LPCTSTR)theApp.m_strAppDir);
+	CHeaderCtrl* pHeader = m_listCtrl.GetHeaderCtrl();
+	for (int i = 0; i < pHeader->GetItemCount(); i++) {
+		RECT rect;
+		pHeader->GetItemRect(i, &rect);
+		strItem.Format(_T("Col_%d_Width"), i);
+		strTemp.Format(_T("%d"), rect.right - rect.left);
+		WritePrivateProfileString("PageVariableListCtrl", strItem, strTemp, strIniFile);
+	}
+}
+
+
+void CPageVarialbles::OnSize(UINT nType, int cx, int cy)
+{
+	CHMPropertyPage::OnSize(nType, cx, cy);
+
+	if (GetDlgItem(IDC_LIST1) == nullptr) return;
+
+	CWnd* pItem;
+	CRect rcClient, rcItem;
+	GetClientRect(&rcClient);
+	m_listCtrl.MoveWindow(12, 12, rcClient.Width() - 24, rcClient.Height() - 24);
+}
+
+void CPageVarialbles::OnApply()
+{
+	__super::OnApply();
+}
+
+void CPageVarialbles::loadVariables()
+{
+	auto& variables = theApp.m_model.m_hsmsPassive.getVariables();
+	for (auto item : variables) {
+		int index = m_listCtrl.InsertItem(m_listCtrl.GetItemCount(), _T(""));
+		m_listCtrl.SetItemData(index, (DWORD_PTR)item);
+		m_listCtrl.SetItemText(index, 1, std::to_string(item->getVarialbleId()).c_str());
+		m_listCtrl.SetItemText(index, 2, item->getName().c_str());
+		m_listCtrl.SetItemText(index, 3, SERVO::CVariable::formatToString(item->getFormat()).c_str());
+		m_listCtrl.SetItemText(index, 4, item->getRemark().c_str());
+	}
+}
diff --git a/SourceCode/Bond/Servo/CPageVarialbles.h b/SourceCode/Bond/Servo/CPageVarialbles.h
new file mode 100644
index 0000000..3ccbdc0
--- /dev/null
+++ b/SourceCode/Bond/Servo/CPageVarialbles.h
@@ -0,0 +1,36 @@
+锘�#pragma once
+#include "CHMPropertyPage.h"
+#include "ListCtrlEx.h"
+
+
+// CPageVarialbles 瀵硅瘽妗�
+
+class CPageVarialbles : public CHMPropertyPage
+{
+	DECLARE_DYNAMIC(CPageVarialbles)
+
+public:
+	CPageVarialbles(CWnd* pParent = nullptr);   // 鏍囧噯鏋勯�犲嚱鏁�
+	virtual ~CPageVarialbles();
+	virtual void OnApply();
+	void loadVariables();
+
+private:
+	CListCtrlEx m_listCtrl;
+
+
+// 瀵硅瘽妗嗘暟鎹�
+#ifdef AFX_DESIGN_TIME
+	enum { IDD = IDD_PAGE_VARIABLE };
+#endif
+
+protected:
+	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 鏀寔
+
+	DECLARE_MESSAGE_MAP()
+public:
+	virtual BOOL OnInitDialog();
+	afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor);
+	afx_msg void OnDestroy();
+	afx_msg void OnSize(UINT nType, int cx, int cy);
+};
diff --git a/SourceCode/Bond/Servo/CReport.cpp b/SourceCode/Bond/Servo/CReport.cpp
new file mode 100644
index 0000000..1ab15fa
--- /dev/null
+++ b/SourceCode/Bond/Servo/CReport.cpp
@@ -0,0 +1,98 @@
+#include "stdafx.h"
+#include "CReport.h"
+
+
+namespace SERVO {
+	CReport::CReport()
+	{
+		m_nReportId = 0;
+	}
+
+	CReport::CReport(unsigned int reportId, std::vector<unsigned int>& vids)
+	{
+		m_nReportId = reportId;
+		for (auto vid : vids) {
+			m_vids.push_back(vid);
+		}
+	}
+
+	CReport::~CReport()
+	{
+
+	}
+
+	unsigned int CReport::getReportId()
+	{
+		return m_nReportId;
+	}
+
+	BOOL CReport::addVariable(CVariable* pVariable)
+	{
+		ASSERT(pVariable);
+		if (getVariable(pVariable->getVarialbleId()) != nullptr) {
+			return FALSE;
+		}
+
+		m_variabels.push_back(pVariable);
+		return TRUE;
+	}
+
+	BOOL CReport::deleteVarialble(unsigned int nVarialbleId)
+	{
+		BOOL bDelete = FALSE;
+		for (auto iter = m_variabels.begin(); iter != m_variabels.end(); ++iter) {
+			if (nVarialbleId == (*iter)->getVarialbleId()) {
+				m_variabels.erase(iter);
+				bDelete = TRUE;
+				break;
+			}
+		}
+
+		return bDelete;
+	}
+
+	CVariable* CReport::getVariable(unsigned int nVarialbleId)
+	{
+		for (auto item : m_variabels) {
+			if (nVarialbleId == item->getVarialbleId()) {
+				return item;
+			}
+		}
+
+		return nullptr;
+	}
+
+	std::vector<CVariable*>& CReport::getVariables()
+	{
+		return m_variabels;
+	}
+
+	std::string CReport::getVariablesIdsText()
+	{
+		std::string strResult, strName;
+		for (int i = 0; i < m_vids.size(); i++) {
+			strResult += std::to_string(m_vids[i]);
+			strResult += "(";
+			strResult += (getVariableName(m_vids[i], strName) ?
+				strName : _T("null"));
+			strResult += ")";
+			if (i != m_vids.size() - 1) {
+				strResult += ",";
+			}
+		}
+
+		return strResult;
+	}
+
+	bool CReport::getVariableName(unsigned int vid, std::string& strName)
+	{
+		for (auto item : m_variabels) {
+			if (item->getVarialbleId() == vid) {
+				strName = item->getName();
+				return true;
+			}
+		}
+
+		return false;
+	}
+}
diff --git a/SourceCode/Bond/Servo/CReport.h b/SourceCode/Bond/Servo/CReport.h
new file mode 100644
index 0000000..191d539
--- /dev/null
+++ b/SourceCode/Bond/Servo/CReport.h
@@ -0,0 +1,28 @@
+#pragma once
+#include "CVariable.h"
+#include <vector>
+
+namespace SERVO {
+	class CReport
+	{
+	public:
+		CReport();
+		CReport(unsigned int reportId, std::vector<unsigned int>& vids);
+		virtual ~CReport();
+
+	public:
+		unsigned int getReportId();
+		BOOL addVariable(CVariable* pVariable);
+		BOOL deleteVarialble(unsigned int nVarialbleId);
+		CVariable* getVariable(unsigned int nVarialbleId);
+		std::vector<CVariable*>& getVariables();
+		std::string getVariablesIdsText();
+		bool getVariableName(unsigned int vid, std::string& strName);
+
+	private:
+		unsigned int m_nReportId;
+		std::vector<unsigned int> m_vids;
+		std::vector<CVariable*> m_variabels;
+	};
+}
+
diff --git a/SourceCode/Bond/Servo/CVariable.cpp b/SourceCode/Bond/Servo/CVariable.cpp
new file mode 100644
index 0000000..21ddb44
--- /dev/null
+++ b/SourceCode/Bond/Servo/CVariable.cpp
@@ -0,0 +1,90 @@
+#include "stdafx.h"
+#include "CVariable.h"
+
+
+namespace SERVO {
+	CVariable::CVariable()
+	{
+		m_nVarialbeId = 0;
+		m_format = SVFromat::U1;
+	}
+
+	CVariable::CVariable(const char* pszId, const char* pszName, const char* pszFormat, const char* pszRemark)
+	{
+		m_nVarialbeId = atoi(pszId);
+		m_strName = pszName;
+		m_format = toFormat(pszFormat);
+		m_strRemark = pszRemark;
+		TRACE("CVariable .....%d,%s,%d,%s\n", m_nVarialbeId, m_strName.c_str(),
+			m_format, m_strRemark.c_str());
+
+	}
+
+	CVariable::~CVariable()
+	{
+
+	}
+
+	SVFromat CVariable::toFormat(const char* pszFormat)
+	{
+		if (_strcmpi("U1", pszFormat) == 0) {
+			return SVFromat::U1;
+		}
+		if (_strcmpi("U2", pszFormat) == 0) {
+			return SVFromat::U2;
+		}
+		if (_strcmpi("I2", pszFormat) == 0) {
+			return SVFromat::I2;
+		}
+		if (_strcmpi("A50", pszFormat) == 0) {
+			return SVFromat::A50;
+		}
+		if (_strcmpi("A20", pszFormat) == 0) {
+			return SVFromat::A20;
+		}
+
+		return SVFromat::U1;
+	}
+
+
+	std::string CVariable::formatToString(SVFromat format)
+	{
+		if (SVFromat::U1 == format) {
+			return "U1";
+		}
+		if (SVFromat::U2 == format) {
+			return "U1";
+		}
+		if (SVFromat::I2 == format) {
+			return "I2";
+		}
+		if (SVFromat::A50 == format) {
+			return "A50";
+		}
+		if (SVFromat::A20 == format) {
+			return "A20";
+		}
+
+		return "U1";
+	}
+
+	unsigned int CVariable::getVarialbleId()
+	{
+		return m_nVarialbeId;
+	}
+
+	std::string& CVariable::getName()
+	{
+		return m_strName;
+	}
+
+	SVFromat CVariable::getFormat()
+	{
+		return m_format;
+	}
+
+	std::string& CVariable::getRemark()
+	{
+		return m_strRemark;
+	}
+}
\ No newline at end of file
diff --git a/SourceCode/Bond/Servo/CVariable.h b/SourceCode/Bond/Servo/CVariable.h
new file mode 100644
index 0000000..7bac823
--- /dev/null
+++ b/SourceCode/Bond/Servo/CVariable.h
@@ -0,0 +1,37 @@
+#pragma once
+#include <string>
+
+
+namespace SERVO {
+	// 变量格式
+	enum class SVFromat {
+		U1 = 0,
+		U2,
+		I2,
+		A20,
+		A50
+	};
+
+	class CVariable
+	{
+	public:
+		CVariable();
+		CVariable(const char* pszId, const char* pszName, const char* pszFormat, const char* pszRemark);
+		~CVariable();
+
+	public:
+		static SVFromat toFormat(const char* pszFormat);
+		static std::string formatToString(SVFromat format);
+		unsigned int getVarialbleId();
+		std::string& getName();
+		SVFromat getFormat();
+		std::string& getRemark();
+
+	private:
+		unsigned int m_nVarialbeId;
+		std::string m_strName;
+		SVFromat m_format;
+		std::string m_strRemark;
+	};
+}
+
diff --git a/SourceCode/Bond/Servo/HsmsPassive.cpp b/SourceCode/Bond/Servo/HsmsPassive.cpp
index 094f4fd..22840c2 100644
--- a/SourceCode/Bond/Servo/HsmsPassive.cpp
+++ b/SourceCode/Bond/Servo/HsmsPassive.cpp
@@ -1,4 +1,4 @@
-#include "stdafx.h"
+锘�#include "stdafx.h"
 #include "HsmsPassive.h"
 #include "Log.h"
 #include "Model.h"
@@ -8,7 +8,12 @@
 #include <time.h>  
 #include <stdlib.h>  
 #include <string.h>  
+#include <regex>
 
+
+const char ACK[2] = {0, 1};
+const char* ACK0 = &ACK[0];
+const char* ACK1 = &ACK[1];
 
 unsigned __stdcall CimWorkThreadFunction(LPVOID lpParam)
 {
@@ -68,11 +73,7 @@
 
 void CHsmsPassive::setListener(SECSListener listener)
 {
-	m_listener.onEQOffLine = listener.onEQOffLine;
-	m_listener.onEQOnLine = listener.onEQOnLine;
-	m_listener.onCommand = listener.onCommand;
-	m_listener.onEQConstantRequest = listener.onEQConstantRequest;
-	m_listener.onEQConstantSend = listener.onEQConstantSend;
+	m_listener = listener;
 }
 
 void CHsmsPassive::setActionTimeout(int nSecond)
@@ -97,70 +98,45 @@
 
 }
 
-void CHsmsPassive::addReport(unsigned int id, const char* pszName)
+void CHsmsPassive::linkEventReport(unsigned int CEID, unsigned int RPTID)
 {
-	Lock();
-	REPORT report;
-	report.id = id;
-	strcpy_s(report.szName, REPORT_NAME_MAX, pszName);
-	m_mapReport[id] = report;
-	Unlock();
-}
-
-void CHsmsPassive::linkEventReport(unsigned int RPTID, unsigned int CEID)
-{
-	m_mapReportIdToCEID[RPTID] = CEID;
+	SERVO::CCollectionEvent* pEvent = getEvent(CEID);
+	SERVO::CReport* pReport = getReport(RPTID);
+	if (pEvent != nullptr) {
+		pEvent->setReport(pReport);
+	}
 }
 
 void CHsmsPassive::unlinkEventReport(unsigned int CEID)
 {
-	for (auto it = m_mapReportIdToCEID.begin(); it != m_mapReportIdToCEID.end(); ) {
-		if (it->second == CEID) {
-			m_mapReportIdToCEID.erase(it++);  // 更新迭代器
-		}
-		else {
-			++it;
-		}
-	}
-
-}
-
-unsigned int CHsmsPassive::getCEID(int RPTID)
-{
-	auto iter = m_mapReportIdToCEID.find(RPTID);
-	if (iter != m_mapReportIdToCEID.end()) return iter->second;
-	return 0;
-}
-
-void CHsmsPassive::deleteReport(unsigned int RPTID)
-{
-	for (auto it = m_mapValueIdToPRTID.begin(); it != m_mapValueIdToPRTID.end(); ) {
-		if (it->second == RPTID) {
-			m_mapValueIdToPRTID.erase(it++);  // 更新迭代器
-		}
-		else {
-			++it;
-		}
+	SERVO::CCollectionEvent* pEvent = getEvent(CEID);
+	if (pEvent != nullptr) {
+		pEvent->setReport(nullptr);
 	}
 }
 
-void CHsmsPassive::deleteAllReport()
+SERVO::CReport* CHsmsPassive::defineReport(unsigned int RPTID, std::vector<unsigned int>& vids)
 {
-	m_mapValueIdToPRTID.clear();
-}
+	// 娣诲姞瀹氫箟report
+	SERVO::CReport* pReport = new SERVO::CReport(RPTID, vids);
+	for (auto vid : vids) {
+		SERVO::CVariable* pVariable = getVariable(vid);
+		if (pVariable != nullptr) {
+			pReport->addVariable(pVariable);
+		}
+	}
+	m_reports.push_back(pReport);
 
-void CHsmsPassive::defineReport(unsigned int VID, unsigned int RPTID)
-{
-	m_mapValueIdToPRTID[VID] = RPTID;
+	return pReport;
 }
 
 void CHsmsPassive::OnTimer(UINT nTimerid)
 {
-	// 所有已发送的Action自加1
+	// 鎵�鏈夊凡鍙戦�佺殑Action鑷姞1
 	Lock();
 	for (auto iter = m_listActionSent.begin(); iter != m_listActionSent.end();) {
 		if ((*iter)->incrementAndCheckTimeout()) {
-			TRACE("CHsmsPassive::超时\n");
+			TRACE("CHsmsPassive::瓒呮椂\n");
 			delete (*iter);
 			m_listActionSent.erase(iter++);
 		}
@@ -178,7 +154,7 @@
 	CHsmsAction* pAction = nullptr;
 	for (auto iter = m_listActionSent.begin(); iter != m_listActionSent.end(); iter++) {
 		if ((*iter)->getSendMessage()->getHeader()->systemBytes == pMessage->getHeader()->systemBytes) {
-			LOGI("CHsmsPassive::找到");
+			LOGI("CHsmsPassive::鎵惧埌");
 			pAction = (*iter);
 			m_listActionSent.erase(iter);
 			break;
@@ -187,12 +163,277 @@
 	Unlock();
 
 	if (pAction != nullptr) {
-		LOGI("onRecvMsg::相应处理");
+		LOGI("onRecvMsg::鐩稿簲澶勭悊");
 		delete pAction;
 	}
 
 
 	return 0;
+}
+
+int CHsmsPassive::loadVarialbles(const char* pszFilepath)
+{
+	CStdioFile file;
+	if (!file.Open(pszFilepath, CFile::modeRead)) {
+		return -1;
+	}
+
+	std::regex pattern("^\\d+,.*");  // 鍖归厤浠ユ暟瀛�+閫楀彿寮�澶寸殑瀛楃涓�
+	std::vector<SERVO::CVariable*> variables;
+	int index, last;
+	CString strLine;
+	CString strId, strName, strFormat, strRemark;
+	while (file.ReadString(strLine)) {
+		if (!std::regex_match((LPTSTR)(LPCTSTR)strLine, pattern)) {
+			continue;
+		}
+
+		last = 0;
+		index = strLine.Find(",", last);
+		if (index < 0) continue;
+		strId = strLine.Left(index);
+		last = index + 1;
+
+		index = strLine.Find(",", last);
+		if (index < 0) continue;
+		strName = strLine.Mid(last, index - last);
+		last = index + 1;
+
+		index = strLine.Find(",", last);
+		if (index < 0) continue;
+		strFormat = strLine.Mid(last, index - last);
+		strRemark = strLine.Right(strLine.GetLength() - index - 1);
+		strRemark.Replace(_T("\\r\\n"), _T("\r\n"));
+
+		SERVO::CVariable* pVarialble = new SERVO::CVariable(
+			(LPTSTR)(LPCTSTR)strId, (LPTSTR)(LPCTSTR)strName, (LPTSTR)(LPCTSTR)strFormat, (LPTSTR)(LPCTSTR)strRemark);
+		variables.push_back(pVarialble);
+	}
+
+	if (!variables.empty()) {
+		clearAllVariabel();
+		for (auto item : variables) {
+			m_variabels.push_back(item);
+		}
+	}
+
+
+	file.Close();
+	return 0;
+}
+
+std::vector<SERVO::CVariable*>& CHsmsPassive::getVariables()
+{
+	return m_variabels;
+}
+
+SERVO::CVariable* CHsmsPassive::getVariable(int variableId)
+{
+	for (auto item : m_variabels) {
+		if (item->getVarialbleId() == variableId) {
+			return item;
+		}
+	}
+
+	return nullptr;
+}
+
+void CHsmsPassive::clearAllVariabel()
+{
+	for (auto item : m_variabels) {
+		delete item;
+	}
+	m_variabels.clear();
+}
+
+int CHsmsPassive::loadReports(const char* pszFilepath)
+{
+	CStdioFile file;
+	if (!file.Open(pszFilepath, CFile::modeRead)) {
+		return -1;
+	}
+
+	std::regex pattern("^\\d+,\\(\\d+(,\\d+)*\\).*");  // 鍖归厤浠ユ暟瀛�+閫楀彿寮�澶寸殑瀛楃涓�
+	std::vector<SERVO::CReport*> reports;
+	int index;
+	CString strLine, strVariable;
+	CString strId;
+	while (file.ReadString(strLine)) {
+		if (!std::regex_match((LPTSTR)(LPCTSTR)strLine, pattern)) {
+			continue;
+		}
+
+		index = strLine.Find(",", 0);
+		if (index < 0) continue;
+		strId = strLine.Left(index);
+		strVariable = strLine.Right(strLine.GetLength() - index - 1);
+		strVariable.Delete(0);
+		strVariable.Delete(strVariable.GetLength() - 1);
+		auto vids = parseVidList(strVariable);
+
+		SERVO::CReport* pReport = new SERVO::CReport(atoi((LPTSTR)(LPCTSTR)strId), vids);
+		for (auto vid : vids) {
+			SERVO::CVariable* pVariable = getVariable(vid);
+			if (pVariable != nullptr) {
+				pReport->addVariable(pVariable);
+			}
+		}
+
+		reports.push_back(pReport);
+	}
+	
+	if (!reports.empty()) {
+		clearAllReport();
+		for (auto item : reports) {
+			m_reports.push_back(item);
+		}
+	}
+	
+
+	file.Close();
+	return 0;
+}
+
+std::vector<SERVO::CReport*>& CHsmsPassive::getReports()
+{
+	return m_reports;
+}
+
+SERVO::CReport* CHsmsPassive::getReport(int rptid)
+{
+	for (auto item : m_reports) {
+		if (item->getReportId() == rptid) {
+			return item;
+		}
+	}
+
+	return nullptr;
+}
+
+bool CHsmsPassive::removeReport(int rptid)
+{
+	for (auto iter = m_reports.begin(); iter != m_reports.end(); ++iter) {
+		if ((*iter)->getReportId() == rptid) {
+			delete (*iter);
+			m_reports.erase(iter);
+			return true;
+		}
+	}
+
+	return false;
+}
+
+void CHsmsPassive::clearAllReport()
+{
+	for (auto item : m_reports) {
+		delete item;
+	}
+	m_reports.clear();
+}
+
+int CHsmsPassive::loadCollectionEvents(const char* pszFilepath)
+{
+	CStdioFile file;
+	if (!file.Open(pszFilepath, CFile::modeRead)) {
+		return -1;
+	}
+
+	std::regex pattern("^\\d+,[^,]*,[^,]*,\\(\\d+(,\\d+)*\\).*");  // 鍖归厤浠ユ暟瀛�+閫楀彿寮�澶寸殑瀛楃涓�
+	std::vector<SERVO::CCollectionEvent*> events;
+	int index, last;
+	CString strLine, strRPTIDs;
+	CString strId, strName, strDescription;
+	while (file.ReadString(strLine)) {
+		if (!std::regex_match((LPTSTR)(LPCTSTR)strLine, pattern)) {
+			continue;
+		}
+
+		last = 0;
+		index = strLine.Find(",", last);
+		if (index < 0) continue;
+		strId = strLine.Left(index);
+		last = index + 1;
+
+		index = strLine.Find(",", last);
+		if (index < 0) continue;
+		strName = strLine.Mid(last, index - last);
+		last = index + 1;
+
+		index = strLine.Find(",", last);
+		if (index < 0) continue;
+		strDescription = strLine.Mid(last, index - last);
+		strRPTIDs = strLine.Right(strLine.GetLength() - index - 1);
+		strRPTIDs.Delete(0);
+		strRPTIDs.Delete(strRPTIDs.GetLength() - 1);
+		auto prtids = parseVidList(strRPTIDs);
+
+		SERVO::CCollectionEvent* pEvent = new SERVO::CCollectionEvent(
+			atoi(strId), (LPTSTR)(LPCTSTR)strName, (LPTSTR)(LPCTSTR)strDescription, prtids);
+		for (auto rptid : prtids) {
+			SERVO::CReport* pReport = getReport(rptid);
+			if (pReport != nullptr) {
+				pEvent->addReport(pReport);
+			}
+		}
+		events.push_back(pEvent);
+	}
+
+	if (!events.empty()) {
+		clearAllCollectionEvent();
+		for (auto item : events) {
+			m_collectionEvents.push_back(item);
+		}
+	}
+
+
+	file.Close();
+	return 0;
+}
+
+std::vector<SERVO::CCollectionEvent*>& CHsmsPassive::getCollectionEvents()
+{
+	return m_collectionEvents;
+}
+
+void CHsmsPassive::clearAllCollectionEvent()
+{
+	for (auto item : m_collectionEvents) {
+		delete item;
+	}
+	m_collectionEvents.clear();
+}
+
+SERVO::CCollectionEvent* CHsmsPassive::getEvent(unsigned short CEID)
+{
+	for (auto item : m_collectionEvents) {
+		if (item->getEventId() == CEID) {
+			return item;
+		}
+	}
+
+	return nullptr;
+}
+
+std::vector<unsigned int> CHsmsPassive::parseVidList(CString& strNums)
+{
+	// 1. 鍏堝幓鎺夊彲鑳藉嚭鐜扮殑绌虹櫧绗︼紙绌烘牸銆佸埗琛ㄧ绛夛級
+	strNums.Trim();
+
+	// 2锔�.
+	std::vector<unsigned int> result;
+	int i = 0;
+	CString strVid;
+	while (1) {
+		if (!AfxExtractSubString(strVid, (LPCTSTR)strNums, i, ',')) {
+			break;
+		}
+		if (!strVid.IsEmpty())                 // 闃插尽鎬ф鏌�
+			result.push_back(std::stoi((LPTSTR)(LPCTSTR)strVid));
+		i++;
+
+	}
+
+	return result;
 }
 
 int CHsmsPassive::init(CModel* pModel, const char* pszName, unsigned int port)
@@ -205,8 +446,8 @@
 	auto onStatusChanged = [&](void* pFrom, STATE state) -> void {
 		m_pModel->notifyInt(RX_CODE_PASSIVE_STATUS_CHANGED, (int)state);
 
-		// 连上之后发S1F1
-		// 修改为不主动发送,而是响应
+		// 杩炰笂涔嬪悗鍙慡1F1
+		// 淇敼涓轰笉涓诲姩鍙戦�侊紝鑰屾槸鍝嶅簲
 		/*
 		if (STATE::SELECTED == state) {
 			m_bAreYouThereRequest = FALSE;
@@ -245,7 +486,7 @@
 		HEADER* pHeader = pMessage->getHeader();
 		int nStream = (pHeader->stream & 0x7F);
 
-		LOGI("<HSMS>收到消息 S%dF%d", nStream, pHeader->function);
+		LOGI("<HSMS>鏀跺埌娑堟伅 S%dF%d", nStream, pHeader->function);
 		if (nStream == 1 && pHeader->function == 1) {
 			// S1F1
 			replyAreYouThere(pMessage);
@@ -280,6 +521,9 @@
 		else if (nStream == 2 && pHeader->function == 41) {
 			replyCommand(pMessage);
 		}
+		else if (nStream == 2 && pHeader->function == 43) {
+			replyConfigureSpooling(pMessage);
+		}
 		else if (nStream == 5 && pHeader->function == 3) {
 			replyEanbleDisableAlarmReport(pMessage);
 		}
@@ -299,7 +543,7 @@
 	listener.funError = onError;
 	m_pPassive->setListener(listener);
 
-	// 启动工作线程
+	// 鍚姩宸ヤ綔绾跨▼
 	m_bCimWorking = TRUE;
 	m_hCimWorkThreadHandle = (HANDLE)_beginthreadex(NULL, 0, ::CimWorkThreadFunction, this,
 		0, &m_nCimWorkThrdaddr);
@@ -312,7 +556,7 @@
 
 int CHsmsPassive::term()
 {
-	// 结束线程
+	// 缁撴潫绾跨▼
 	m_bCimWorking = FALSE;
 	SetEvent(m_hCimWorkEvent);
 	if (m_hCimWorkThreadHandle != NULL) {
@@ -326,6 +570,10 @@
 		m_pPassive = NULL;
 	}
 
+	clearAllVariabel();
+	clearAllReport();
+	clearAllCollectionEvent();
+
 	return 0;
 }
 
@@ -333,12 +581,12 @@
 {
 	while (m_bCimWorking) {
 
-		// 待退出信号或时间到
+		// 寰呴��鍑轰俊鍙锋垨鏃堕棿鍒�
 		int nRet = WaitForSingleObject(m_hCimWorkEvent, INFINITE);
 		ResetEvent(m_hCimWorkEvent);
 		if (!m_bCimWorking) break;
 
-		// 取出请求列表并进行处理
+		// 鍙栧嚭璇锋眰鍒楄〃骞惰繘琛屽鐞�
 		std::list<CHsmsAction*> list;
 		Lock();
 		list.splice(list.end(), m_listAction);
@@ -357,14 +605,14 @@
 			LOGI("<HSMS> [SEND] SysByte=%u sessionId:%d", pMessage->getHeader()->systemBytes, pMessage->getHeader()->sessionId);
 
 			if (pAction->isNeedWaitReply()) {
-				// 如果需要等待回复
+				// 濡傛灉闇�瑕佺瓑寰呭洖澶�
 				int nRet = WaitForSingleObject(pAction->getEvent(), pAction->getTimeout() * 1000);
 				if (nRet == WAIT_TIMEOUT) {
 					TRACE("Timeout...\n");
 					CContext* pContext = pAction->getContext();
 					if (pContext != NULL) {
 						//pContext->setRetCode(CRC_TIMEOUT);
-						//pContext->setRetMsg("超时");
+						//pContext->setRetMsg("瓒呮椂");
 						//pContext->setEvent();
 					}
 				}
@@ -390,7 +638,7 @@
 	return 0;
 }
 
-// 通用的reply ack函数
+// 閫氱敤鐨剅eply ack鍑芥暟
 void CHsmsPassive::replyAck(int s, int f, unsigned int systemBytes, BYTE ack, const char* pszAckName)
 {
 	IMessage* pMessage = NULL;
@@ -453,13 +701,13 @@
 	}
 
 
-	// 交由上层应用来获取机器常量值
+	// 浜ょ敱涓婂眰搴旂敤鏉ヨ幏鍙栨満鍣ㄥ父閲忓��
 	if (m_listener.onEQOffLine != nullptr) {
 		m_listener.onEQOffLine(this);
 	}
 
 
-	// 回复
+	// 鍥炲
 	replyAck(1, 16, pRecv->getHeader()->systemBytes, BYTE(0), "OFLACK");
 	return 0;
 }
@@ -472,13 +720,13 @@
 	}
 
 
-	// 交由上层应用来获取机器常量值
+	// 浜ょ敱涓婂眰搴旂敤鏉ヨ幏鍙栨満鍣ㄥ父閲忓��
 	if (m_listener.onEQOnLine != nullptr) {
 		m_listener.onEQOnLine(this);
 	}
 
 
-	// 回复
+	// 鍥炲
 	replyAck(1, 18, pRecv->getHeader()->systemBytes, BYTE(0), "ONLACK");
 	return 0;
 }
@@ -494,12 +742,12 @@
 	ASSERT(pMessage);
 
 	ISECS2Item* pItem = pMessage->getBody();
-	pItem->addBinaryItem(BYTE(0), "COMMACK");
+	pItem->addBinaryItem(ACK0, 1, "COMMACK");
 	ISECS2Item* pList = pItem->addItem();
 	pList->addItem(m_strEquipmentModelType.c_str(), "MDLN");
 	pList->addItem(m_strSoftRev.c_str(), "SOFTREV");
 	m_pPassive->sendMessage(pMessage);
-	LOGI("<HSMS>[SECS Msg SEND]S1F14 (SysByte=%u)", pMessage->getHeader()->systemBytes);
+	LOGI("<HSMS>[SECS Msg SEND]%s", pMessage->toString());
 	HSMS_Destroy1Message(pMessage);
 
 	return 0;
@@ -513,7 +761,7 @@
 	}
 
 
-	// 要获取的常量表表
+	// 瑕佽幏鍙栫殑甯搁噺琛ㄨ〃
 	BOOL bCheckData = FALSE;
 	std::vector<EQConstant> eqcs;
 	{
@@ -530,13 +778,13 @@
 	}
 
 
-	// 交由上层应用来获取机器常量值
+	// 浜ょ敱涓婂眰搴旂敤鏉ヨ幏鍙栨満鍣ㄥ父閲忓��
 	if (m_listener.onEQConstantRequest != nullptr) {
 		m_listener.onEQConstantRequest(this, eqcs);
 	}
 
 
-	// 回复
+	// 鍥炲
 	IMessage* pMessage = NULL;
 	HSMS_Create1Message(pMessage, m_nSessionId, 1, 14, pRecv->getHeader()->systemBytes);
 	ASSERT(pMessage);
@@ -560,7 +808,7 @@
 	}
 
 
-	// 要设置的常量表表
+	// 瑕佽缃殑甯搁噺琛ㄨ〃
 	BOOL bCheckData = FALSE;
 	std::vector<EQConstant> eqcs;
 	{
@@ -583,14 +831,14 @@
 	}
 
 
-	// 交由上层应用来保存和设置机器常量值
+	// 浜ょ敱涓婂眰搴旂敤鏉ヤ繚瀛樺拰璁剧疆鏈哄櫒甯搁噺鍊�
 	std::vector<unsigned int> ecvs;
 	if (m_listener.onEQConstantSend != nullptr) {
 		m_listener.onEQConstantSend(this, eqcs);
 	}
 
 
-	// 回复
+	// 鍥炲
 	replyAck(2, 16, pRecv->getHeader()->systemBytes, BYTE(0), "EACK");
 	return 0;
 }
@@ -605,7 +853,7 @@
 	if (pBody == nullptr || pBody->getType() != SITYPE::A) ER_PARAM_ERROR;
 	const char* pszMessage;
 	if (pBody->getString(pszMessage)) {
-		// 更新时间
+		// 鏇存柊鏃堕棿
 		SYSTEMTIME time;
 		char szBuffer[20];
 		memcpy(szBuffer, pszMessage, 16);
@@ -623,6 +871,9 @@
 		time.wYear = atoi(&szBuffer[0]);
 		time.wMilliseconds = 0;
 		SetLocalTime(&time);
+		if (m_listener.onDatetimeSync != nullptr) {
+			m_listener.onDatetimeSync(this, time);
+		}
 	}
 
 	replyAck(2, 32, pRecv->getHeader()->systemBytes, BYTE(0), "TIACK");
@@ -640,40 +891,47 @@
 	ISECS2Item* pBody = pRecv->getBody();
 	ISECS2Item* defineItem, *rptListItem, * vidListItem;
 	unsigned int dataId, rptid, vid;
+
 	if (!pBody->getSubItemU4(0, dataId)) goto MYREPLY;
 	rptListItem = pBody->getSubItem(1);
 	if (rptListItem == nullptr) goto MYREPLY;
 	if (rptListItem->getSubItemSize() == 0) {
-		deleteAllReport();
+		clearAllReport();
 		goto MYREPLY;
 	}
+
 	for (int i = 0; i < rptListItem->getSubItemSize(); i++) {
 		defineItem = rptListItem->getSubItem(i);
 		if (defineItem == nullptr) continue;
+
+		std::vector<unsigned int> vids;
+		SERVO::CReport* pReport = nullptr;
 		vidListItem = defineItem->getSubItem(1);
 		if (defineItem->getSubItemU4(0, rptid)
 			&& vidListItem != nullptr) {
-			int vidCount = vidListItem->getSubItemSize();
-			if (vidCount == 0) {
-				deleteReport(rptid);
-			}
-			else {
-				for (int k = 0; k < vidCount; k++) {
-					if (vidListItem->getSubItemU4(k, vid)) {
-						defineReport(vid, rptid);
-					}
+			for (int k = 0; k < vidListItem->getSubItemSize(); k++) {
+				if (vidListItem->getSubItemU4(k, vid)) {
+					vids.push_back(vid);
 				}
+			}
+		}
+
+		removeReport(rptid);
+		if (!vids.empty()) {
+			pReport = defineReport(rptid, vids);
+		}
+
+		// 妫�楠岀粨鏋滄槸鍚︽纭�
+		if (pReport != nullptr) {
+			auto variables = pReport->getVariables();
+			for (auto item : variables) {
+				LOGE("=== prtid:%d, vid:%d", rptid, item->getVarialbleId());
 			}
 		}
 	}
 
 
 MYREPLY:
-	// 检验结果是否正确
-	for (auto item : m_mapValueIdToPRTID) {
-		LOGE("=== vid:%d, prtid:%d", item.first, item.second);
-	}
-
 	replyAck(2, 34, pRecv->getHeader()->systemBytes, BYTE(0), "DRACK");
 	return 0;
 }
@@ -705,7 +963,7 @@
 			else {
 				for (int k = 0; k < prtCount; k++) {
 					if (rptListItem->getSubItemU4(k, rptid)) {
-						linkEventReport(rptid, ceid);
+						linkEventReport(ceid, rptid);
 					}
 				}
 			}
@@ -713,11 +971,11 @@
 	}
 
 
-	// 检验结果是否正确
-	for (auto item : m_mapReportIdToCEID) {
-		LOGE("=== prtid:%d, ceid:%d", item.first, item.second);
+	// 妫�楠岀粨鏋滄槸鍚︽纭�
+	for (auto item : m_collectionEvents) {
+		LOGE("=== ceid:%d, prtid:%d", item->getEventId(), item->getPortID());
 	}
-
+	
 MYREPLY:
 	replyAck(2, 36, pRecv->getHeader()->systemBytes, BYTE(0), "LRACK");
 	return 0;
@@ -751,15 +1009,15 @@
 			}
 		}
 		bCheckData = TRUE;
-		LOGI("EanbleDisableAlarm bEnable:%s", bEnable ? _T("YES") : _T("NO"));
-		for (auto item : ids) {
-			LOGI("ID:%u", item);
+		if (m_listener.onEnableDisableEventReport != nullptr) {
+			m_listener.onEnableDisableEventReport(this, bEnable, ids);
 		}
 	}
 
 
 MYREPLY:
-	replyAck(2, 38, pRecv->getHeader()->systemBytes, BYTE(0), "ERACK");
+	replyAck(2, 38, pRecv->getHeader()->systemBytes, 
+		bCheckData ? BYTE(0) : BYTE(1), "ERACK");
 	return 0;
 }
 
@@ -800,13 +1058,58 @@
 	}
 
 
-	// 回调到应用层
+	// 鍥炶皟鍒板簲鐢ㄥ眰
 	if (bCheckData) {
 		if (m_listener.onCommand != nullptr) {
 			m_listener.onCommand(this, pszCmdName, params);
 		}
 	}
 
+MYREPLY:
+	replyAck(2, 42, pRecv->getHeader()->systemBytes, BYTE(0), "ERACK");
+	return 0;
+}
+
+// S2F43
+int CHsmsPassive::replyConfigureSpooling(IMessage* pRecv)
+{
+	if (m_pPassive == NULL || STATE::SELECTED != m_pPassive->getState()) {
+		return ER_NOTSELECT;
+	}
+	ISECS2Item* pBody = pRecv->getBody();
+	if (pBody == nullptr || pBody->getType() != SITYPE::L) ER_PARAM_ERROR;
+
+	// 娓呯┖鎵�鏈�
+	if (pBody->getSubItemSize() == 0) {
+		m_spoolingConfig.clear();
+		goto MYREPLY;
+	}
+
+	// 渚濇閰嶇疆Stream
+	for (int i = 0; i < pBody->getSubItemSize(); i++) {
+		ISECS2Item* pStreamItem = pBody->getSubItem(i);
+		ASSERT(pStreamItem);
+		unsigned char STRID, FCNID;
+		pStreamItem->getSubItemU1(0, STRID);
+		ISECS2Item* pFcnItemList = pStreamItem->getSubItem(1);
+		if (pFcnItemList->getSubItemSize() == 0) {
+			m_spoolingConfig[STRID].clear();
+		}
+		else {
+			for (int j = 0; j < pFcnItemList->getSubItemSize(); j++) {
+				pFcnItemList->getSubItemU1(j, FCNID);
+				m_spoolingConfig[STRID].insert(FCNID);
+			}
+		}
+	}
+
+	// 鎵撳嵃楠岃瘉缁撴灉
+	for (auto s : m_spoolingConfig) {
+		LOGI("====> stream:%d", s.first);
+		for (auto f : s.second) {
+			LOGI("function:%d", f);
+		}
+	}
 MYREPLY:
 	replyAck(2, 42, pRecv->getHeader()->systemBytes, BYTE(0), "ERACK");
 	return 0;
@@ -834,36 +1137,9 @@
 		if (!pItem->getSubItemU4(1, ALID)) goto MYREPLY;
 		bCheckData = TRUE;
 		LOGI("EanbleDisableAlarmReport ALED:0x%02x, ALID:%d", ALED[0], ALID);
-
-		double d;
-		float f;
-		pItem->getSubItemF4(2, f);
-		pItem->getSubItemF8(3, d);
-		LOGI("EanbleDisableAlarmReport d:%lf, f:%f",
-			d, f);
-		/*
-		unsigned long long n1;
-		unsigned int n2;
-		unsigned short n3;
-		unsigned char n4;
-		long long sn1;
-		int sn2;
-		short sn3;
-		char sn4;
-		pItem->getSubItemU8(2, n1);
-		pItem->getSubItemU4(3, n2);
-		pItem->getSubItemU2(4, n3);
-		pItem->getSubItemU1(5, n4);
-		pItem->getSubItemI8(6, sn1);
-		pItem->getSubItemI4(7, sn2);
-		pItem->getSubItemI2(8, sn3);
-		pItem->getSubItemI1(9, sn4);
-
-		LOGI("EanbleDisableAlarmReport n1:%llu, n2:%u, n3:%hu, n4:%hhu", 
-			n1, n2, n3, n4);
-		LOGI("EanbleDisableAlarmReport sn1:%lld, sn2:%d, sn3:%hd, sn4:%hhd",
-			sn1, sn2, sn3, sn4);
-			*/
+		if (m_listener.onEnableDisableAlarmReport != nullptr) {
+			m_listener.onEnableDisableAlarmReport(this, ALED[0] != 0, ALID);
+		}
 	}
 
 
@@ -936,6 +1212,9 @@
 		return ER_NOTSELECT;
 	}
 
+	char szALCD[1];
+	szALCD[0] = ALCD & 0xff;
+
 	Lock();
 	CHsmsAction* pAction = new CHsmsAction(ACTION_ALARM_REPORT, TRUE, m_nActionTimeout);
 	m_listAction.push_back(pAction);
@@ -943,7 +1222,7 @@
 	HSMS_Create1Message(pMessage, m_nSessionId, 5 | REPLY, 1, ++m_nSystemByte);
 	ASSERT(pMessage);
 	ISECS2Item* pItem = pMessage->getBody();
-	pItem->addBinaryItem(BYTE(ALCD & 0xff), "ALCD");
+	pItem->addBinaryItem(szALCD, 1, "ALCD");
 	pItem->addU4Item(ALID, "ALID");
 	pItem->addItem(ALTX, "ALTX");
 	pAction->setSendMessage(pMessage);
@@ -955,10 +1234,18 @@
 }
 
 // S6F11
-int CHsmsPassive::requestEventReportSend(unsigned int DATAID, unsigned int RPTID, const std::vector<std::string>& values)
+int CHsmsPassive::requestEventReportSend(unsigned int DATAID, unsigned int CEID, const std::vector<std::string>& values)
 {
 	if (m_pPassive == NULL || STATE::SELECTED != m_pPassive->getState()) {
 		return ER_NOTSELECT;
+	}
+
+	SERVO::CCollectionEvent* pEvent = getEvent(CEID);
+	if (pEvent == nullptr) {
+		return ER_NO_EVENT;
+	}
+	if (pEvent == nullptr) {
+		return ER_UNLINK_EVENT_REPORT;
 	}
 
 	Lock();
@@ -969,10 +1256,10 @@
 	ASSERT(pMessage);
 	ISECS2Item* pItem = pMessage->getBody();
 	pItem->addU4Item(DATAID, "DATAID");
-	pItem->addU4Item(getCEID(RPTID), "CEID");
+	pItem->addU4Item(CEID, "CEID");
 	ISECS2Item* pItemList1 = pItem->addItem();
 	ISECS2Item* pItemList2 = pItemList1->addItem();
-	pItemList2->addU4Item(RPTID, "RPTID");
+	pItemList2->addU4Item(pEvent->getPortID(), "RPTID");
 	ISECS2Item* pItemList3 = pItemList2->addItem();
 	for (auto item : values) {
 		pItemList3->addItem(item.c_str(), "V");
diff --git a/SourceCode/Bond/Servo/HsmsPassive.h b/SourceCode/Bond/Servo/HsmsPassive.h
index 44ce52c..84644a5 100644
--- a/SourceCode/Bond/Servo/HsmsPassive.h
+++ b/SourceCode/Bond/Servo/HsmsPassive.h
@@ -5,6 +5,8 @@
 #include <functional>
 #include <vector>
 #include <map>
+#include <set>
+#include "CCollectionEvent.h"
 
 
 #define EQCONSTANT_VALUE_MAX	64
@@ -14,10 +16,12 @@
 #define VALUE_NAME_MAX			64
 
 
-#define ER_NOERROR			0
-#define ER_NOTSELECT		-1
-#define ER_BUSY				-2
-#define ER_PARAM_ERROR		-3
+#define ER_NOERROR				0
+#define ER_NOTSELECT			-1
+#define ER_BUSY					-2
+#define ER_PARAM_ERROR			-3
+#define ER_NO_EVENT				-4
+#define ER_UNLINK_EVENT_REPORT	-5
 
 
 /*
@@ -60,6 +64,9 @@
 typedef std::function<void(void* pFrom)> SECSEQOFFLINE;
 typedef std::function<void(void* pFrom, std::vector<EQConstant>&)> SECSEQCONSTANTREQUEST;
 typedef std::function<void(void* pFrom, const char*, std::vector<CommandParameter>&)> SECSCommand;
+typedef std::function<void(void* pFrom, SYSTEMTIME& time)> DATETIMESYNC;
+typedef std::function<void(void* pFrom, bool bEnable, std::vector<unsigned int>& ids)> EDEVENTREPORT;
+typedef std::function<void(void* pFrom, bool bEnable, unsigned int id)> EDALARMREPORT;
 typedef struct _SECSListener
 {
 	SECSEQOFFLINE				onEQOffLine;
@@ -67,6 +74,9 @@
 	SECSEQCONSTANTREQUEST		onEQConstantRequest;
 	SECSEQCONSTANTREQUEST		onEQConstantSend;
 	SECSCommand					onCommand;
+	DATETIMESYNC				onDatetimeSync;
+	EDEVENTREPORT				onEnableDisableEventReport;
+	EDALARMREPORT				onEnableDisableAlarmReport;
 } SECSListener;
 
 
@@ -84,25 +94,48 @@
 	/* 设置软件版本号 最大长度 20 bytes */
 	void setSoftRev(const char* pszRev);
 
-	/* 添加Report */
-	void addReport(unsigned int id, const char* pszName);
-
 	// 连接Report
-	void linkEventReport(unsigned int RPTID, unsigned int CEID);
+	void linkEventReport(unsigned int CEID, unsigned int RPTID);
 
 	// 取消连接report
 	void unlinkEventReport(unsigned int CEID);
 
-	unsigned int getCEID(int RPTID);
-
 	// define Report
-	void defineReport(unsigned int VID, unsigned int RPTID);
+	SERVO::CReport* defineReport(unsigned int RPTID, std::vector<unsigned int>& vids);
 
 	// 取消 define report
-	void deleteReport(unsigned int RPTID);
+	bool removeReport(int rptid);
+	void clearAllReport();
 
-	// 取消/删除所有 define report
-	void deleteAllReport();
+	// 从文件中加载CVariable列表
+	int loadVarialbles(const char* pszFilepath);
+
+	// 取得CVariable列表
+	std::vector<SERVO::CVariable*>& getVariables();
+
+	// 取得指定Variable
+	SERVO::CVariable* getVariable(int variableId);
+
+	// 从文件中加载CReport列表
+	int loadReports(const char* pszFilepath);
+
+	// 取得Report列表
+	std::vector<SERVO::CReport*>& getReports();
+
+	// 从文件中加载CCollectionEvent列表
+	int loadCollectionEvents(const char* pszFilepath);
+
+	// 取得CCollectionEvent列表
+	std::vector<SERVO::CCollectionEvent*>& getCollectionEvents();
+
+	// 取消/删除所有CollectionEvent
+	void clearAllCollectionEvent();
+
+	// 取得CCollectionEvent
+	SERVO::CCollectionEvent* getEvent(unsigned short CEID);
+
+	// 取得Report
+	SERVO::CReport* getReport(int rptid);
 
 	void setListener(SECSListener listener);
 	unsigned OnCimWork();
@@ -115,7 +148,7 @@
 	/* request开头的函数为主动发送数据的函数 */
 	int requestAreYouThere();
 	int requestAlarmReport(int ALCD, int ALID, const char* ALTX);
-	int requestEventReportSend(unsigned int DATAID, unsigned int RPTID, const std::vector<std::string>& values);
+	int requestEventReportSend(unsigned int DATAID, unsigned int CEID, const std::vector<std::string>& values);
 
 private:
 	void replyAck(int s, int f, unsigned int systemBytes, BYTE ack, const char* pszAckName);
@@ -132,6 +165,7 @@
 	int replyLinkEventReport(IMessage* pRecv);
 	int replyEanbleDisableEventReport(IMessage* pRecv);
 	int replyCommand(IMessage* pRecv);
+	int replyConfigureSpooling(IMessage* pRecv);
 	int replyEanbleDisableAlarmReport(IMessage* pRecv);
 	int replyQueryPPIDList(IMessage* pRecv);
 	int replyTerminalDisplay(IMessage* pRecv);
@@ -140,6 +174,8 @@
 	inline void Lock() { EnterCriticalSection(&m_criticalSection); }
 	inline void Unlock() { LeaveCriticalSection(&m_criticalSection); }
 	int onRecvMsg(IMessage* pMessage);
+	void clearAllVariabel();
+	std::vector<unsigned int> parseVidList(CString& strNums);
 
 private:
 	CModel* m_pModel;
@@ -162,16 +198,16 @@
 	unsigned m_nCimWorkThrdaddr;
 
 private:
-	// RPTID to CEID
-	std::map<unsigned int, unsigned int> m_mapReportIdToCEID;
-	
-	// RPTID to Report
-	std::map<unsigned int, REPORT> m_mapReport;
+	// CVariable vector
+	std::vector<SERVO::CVariable*> m_variabels;
 
-	// VID to RPTID
-	std::map<unsigned int, unsigned int> m_mapValueIdToPRTID;
+	// CReport vector
+	std::vector<SERVO::CReport*> m_reports;
 
-	// VID to Report
-	std::map<unsigned int, VALUE> m_mapValue;
+	// CollectionEvent vector
+	std::vector<SERVO::CCollectionEvent*> m_collectionEvents;
+
+	// Spooling Config
+	std::map<uint16_t, std::set<uint16_t>> m_spoolingConfig;
 };
 
diff --git a/SourceCode/Bond/Servo/Model.cpp b/SourceCode/Bond/Servo/Model.cpp
index 7f3ed76..1a63ddd 100644
--- a/SourceCode/Bond/Servo/Model.cpp
+++ b/SourceCode/Bond/Servo/Model.cpp
@@ -114,11 +114,34 @@
 			LOGI("onEQConstantRequest: %d, %s", item.id, item.szValue);
 		}
 	};
-
+	listener.onDatetimeSync = [&](void* pFrom, SYSTEMTIME& time) -> void {
+		LOGI("onDatetimeSync: %d%02d%02d%02d%02d%02d", time.wYear,
+			time.wMonth, time.wDay, time.wHour, time.wMinute, time.wSecond);
+		m_master.datetimeSync(time);
+	};
+	listener.onEnableDisableEventReport = [&](void* pFrom, bool bEnable, std::vector<unsigned int> ids) -> void {
+		LOGI("EanbleDisableEventReport bEnable:%s", bEnable ? _T("YES") : _T("NO"));
+		if (ids.empty()) {
+			m_master.enableEventReport(bEnable);
+		}
+	};
+	listener.onEnableDisableAlarmReport = [&](void* pFrom, bool bEnable, unsigned int id) -> void {
+		LOGI("onEnableDisableAlarmReport bEnable:%s, id:%d", bEnable ? _T("YES") : _T("NO"), id);
+		if (id == 0) {
+			m_master.enableAlarmReport(bEnable);
+		}
+	};
 	m_hsmsPassive.setListener(listener);
 	m_hsmsPassive.setEquipmentModelType((LPTSTR)(LPCTSTR)strModeType);
 	m_hsmsPassive.setSoftRev((LPTSTR)(LPCTSTR)strSoftRev);
+	CString strVarialbleFile;
+	strVarialbleFile.Format(_T("%s\\VariableList.txt"), (LPTSTR)(LPCTSTR)m_strWorkDir);
+	m_hsmsPassive.loadVarialbles((LPTSTR)(LPCTSTR)strVarialbleFile);
 	m_hsmsPassive.init(this, "APP", 7000);
+	strVarialbleFile.Format(_T("%s\\ReportList.txt"), (LPTSTR)(LPCTSTR)m_strWorkDir);
+	m_hsmsPassive.loadReports((LPTSTR)(LPCTSTR)strVarialbleFile);
+	strVarialbleFile.Format(_T("%s\\CollectionEventList.txt"), (LPTSTR)(LPCTSTR)m_strWorkDir);
+	m_hsmsPassive.loadCollectionEvents((LPTSTR)(LPCTSTR)strVarialbleFile);
 
 
 	SERVO::MasterListener masterListener;
@@ -178,9 +201,11 @@
 			notify(RX_CODE_ALARM_CLEAR);
 		}
 
-		m_hsmsPassive.requestAlarmReport(state,
-			pEquipment->getBaseAlarmId() + alarmId,
-			strAlarmText.c_str());
+		if (m_master.isAlarmReportEnable()) {
+			m_hsmsPassive.requestAlarmReport(state,
+				pEquipment->getBaseAlarmId() + alarmId,
+				strAlarmText.c_str());
+		}
 	};
 	masterListener.onEqVcrEventReport = [&](void* pMaster, SERVO::CEquipment* pEquipment, SERVO::CVcrEventReport* pReport) {
 		LOGE("<CModel>onEqVcrEventReport.");
diff --git a/SourceCode/Bond/Servo/Servo.rc b/SourceCode/Bond/Servo/Servo.rc
index e5d1d9c..003d2f9 100644
--- a/SourceCode/Bond/Servo/Servo.rc
+++ b/SourceCode/Bond/Servo/Servo.rc
Binary files differ
diff --git a/SourceCode/Bond/Servo/Servo.vcxproj b/SourceCode/Bond/Servo/Servo.vcxproj
index d3bbe72..008f416 100644
--- a/SourceCode/Bond/Servo/Servo.vcxproj
+++ b/SourceCode/Bond/Servo/Servo.vcxproj
@@ -201,16 +201,22 @@
   <ItemGroup>
     <ClInclude Include="CBaseDlg.h" />
     <ClInclude Include="CCustomCheckBox.h" />
+    <ClInclude Include="CCollectionEvent.h" />
     <ClInclude Include="CEquipmentPage3.h" />
     <ClInclude Include="CGlassPool.h" />
     <ClInclude Include="ChangePasswordDlg.h" />
     <ClInclude Include="CMyStatusbar.h" />
+    <ClInclude Include="CPageCollectionEvent.h" />
     <ClInclude Include="CPageLinkSignal.h" />
+    <ClInclude Include="CPageReport.h" />
+    <ClInclude Include="CPageVarialbles.h" />
+    <ClInclude Include="CReport.h" />
     <ClInclude Include="CRobotCmdContainerDlg.h" />
     <ClInclude Include="CRobotCmdTestDlg.h" />
     <ClInclude Include="CPagePortStatus.h" />
     <ClInclude Include="CPortStatusReport.h" />
     <ClInclude Include="CRobotTaskDlg.h" />
+    <ClInclude Include="CVariable.h" />
     <ClInclude Include="GridControl\CellRange.h" />
     <ClInclude Include="GridControl\GridCell.h" />
     <ClInclude Include="GridControl\GridCellBase.h" />
@@ -344,16 +350,22 @@
   <ItemGroup>
     <ClCompile Include="CBaseDlg.cpp" />
     <ClCompile Include="CCustomCheckBox.cpp" />
+    <ClCompile Include="CCollectionEvent.cpp" />
     <ClCompile Include="CEquipmentPage3.cpp" />
     <ClCompile Include="CGlassPool.cpp" />
     <ClCompile Include="ChangePasswordDlg.cpp" />
     <ClCompile Include="CMyStatusbar.cpp" />
+    <ClCompile Include="CPageCollectionEvent.cpp" />
     <ClCompile Include="CPageLinkSignal.cpp" />
+    <ClCompile Include="CPageReport.cpp" />
+    <ClCompile Include="CPageVarialbles.cpp" />
+    <ClCompile Include="CReport.cpp" />
     <ClCompile Include="CRobotCmdContainerDlg.cpp" />
     <ClCompile Include="CRobotCmdTestDlg.cpp" />
     <ClCompile Include="CPagePortStatus.cpp" />
     <ClCompile Include="CPortStatusReport.cpp" />
     <ClCompile Include="CRobotTaskDlg.cpp" />
+    <ClCompile Include="CVariable.cpp" />
     <ClCompile Include="GridControl\GridCell.cpp" />
     <ClCompile Include="GridControl\GridCellBase.cpp" />
     <ClCompile Include="GridControl\GridCellButton.cpp" />
diff --git a/SourceCode/Bond/Servo/Servo.vcxproj.filters b/SourceCode/Bond/Servo/Servo.vcxproj.filters
index 8b805ea..c82ddab 100644
--- a/SourceCode/Bond/Servo/Servo.vcxproj.filters
+++ b/SourceCode/Bond/Servo/Servo.vcxproj.filters
@@ -170,6 +170,12 @@
     <ClCompile Include="RecipeManager.cpp" />
     <ClCompile Include="RecipeDeviceBindDlg.cpp" />
     <ClCompile Include="CCustomCheckBox.cpp" />
+    <ClCompile Include="CCollectionEvent.cpp" />
+    <ClCompile Include="CReport.cpp" />
+    <ClCompile Include="CVariable.cpp" />
+    <ClCompile Include="CPageVarialbles.cpp" />
+    <ClCompile Include="CPageReport.cpp" />
+    <ClCompile Include="CPageCollectionEvent.cpp" />
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="AlarmManager.h" />
@@ -345,6 +351,12 @@
     <ClInclude Include="RecipeManager.h" />
     <ClInclude Include="RecipeDeviceBindDlg.h" />
     <ClInclude Include="CCustomCheckBox.h" />
+    <ClInclude Include="CCollectionEvent.h" />
+    <ClInclude Include="CReport.h" />
+    <ClInclude Include="CVariable.h" />
+    <ClInclude Include="CPageVarialbles.h" />
+    <ClInclude Include="CPageReport.h" />
+    <ClInclude Include="CPageCollectionEvent.h" />
   </ItemGroup>
   <ItemGroup>
     <ResourceCompile Include="Servo.rc" />
diff --git a/SourceCode/Bond/Servo/Servo.vcxproj.user b/SourceCode/Bond/Servo/Servo.vcxproj.user
index 82c7903..0c03257 100644
--- a/SourceCode/Bond/Servo/Servo.vcxproj.user
+++ b/SourceCode/Bond/Servo/Servo.vcxproj.user
@@ -7,6 +7,6 @@
     <RemoteDebuggerCommand>\\DESKTOP-IODBVIQ\Servo\Debug\Servo.exe</RemoteDebuggerCommand>
     <RemoteDebuggerWorkingDirectory>\\DESKTOP-IODBVIQ\Servo\Debug\</RemoteDebuggerWorkingDirectory>
     <RemoteDebuggerServerName>DESKTOP-IODBVIQ</RemoteDebuggerServerName>
-    <DebuggerFlavor>WindowsRemoteDebugger</DebuggerFlavor>
+    <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
   </PropertyGroup>
 </Project>
\ No newline at end of file
diff --git a/SourceCode/Bond/Servo/ServoDlg.cpp b/SourceCode/Bond/Servo/ServoDlg.cpp
index cec70de..d6b4057 100644
--- a/SourceCode/Bond/Servo/ServoDlg.cpp
+++ b/SourceCode/Bond/Servo/ServoDlg.cpp
@@ -22,6 +22,10 @@
 #include "UserManager.h"
 #include "SystemLogManager.h"
 #include "PortConfigurationDlg.h"
+#include "CHMPropertyDlg.h"
+#include "CPageVarialbles.h"
+#include "CPageReport.h"
+#include "CPageCollectionEvent.h"
 
 
 #ifdef _DEBUG
@@ -118,6 +122,8 @@
 	ON_UPDATE_COMMAND_UI(ID_MENU_FILE_SETTINGS, &CServoDlg::OnUpdateMenuFileSettings)
 	ON_COMMAND(ID_MENU_FILE_SECSTEST, &CServoDlg::OnMenuFileSecsTest)
 	ON_UPDATE_COMMAND_UI(ID_MENU_FILE_SECSTEST, &CServoDlg::OnUpdateMenuFileSecsTest)
+	ON_COMMAND(ID_MENU_PROJECT_VARIABLE_LIST, &CServoDlg::OnMenuProjectVarialbleList)
+	ON_UPDATE_COMMAND_UI(ID_MENU_PROJECT_VARIABLE_LIST, &CServoDlg::OnUpdateMenuProjectVarialbleList)
 	ON_COMMAND(ID_MENU_TEST_MESSAGE_SET, &CServoDlg::OnMenuTestMessageSet)
 	ON_UPDATE_COMMAND_UI(ID_MENU_TEST_MESSAGE_SET, &CServoDlg::OnUpdateMenuTestMessageSet)
 	ON_COMMAND(ID_MENU_TEST_MESSAGE_CLEAR, &CServoDlg::OnMenuTestMessageClear)
@@ -250,6 +256,26 @@
 				}
 			}
 
+			if (RX_CODE_PASSIVE_STATUS_CHANGED == code) {
+				int state = 0;
+				pAny->getIntValue("exCode", state);
+
+				if (STATE::NOT_CONNECTED == state) {
+					m_pMyStatusbar->setCimBtnText("Disconnected");
+					//m_labelPassiveState.setBackground(DISCONNECTED_BACKGROUND);
+					//m_labelPassiveState.setForeground(DISCONNECTED_FOREGROUND, TRUE);
+				}
+				else if (STATE::NOT_SELECTED == state) {
+					m_pMyStatusbar->setCimBtnText("Not Selected");
+					//m_labelPassiveState.setBackground(NOT_SELECTED_BACKGROUND);
+					//m_labelPassiveState.setForeground(NOT_SELECTED_FOREGROUND, TRUE);
+				}
+				else if (STATE::SELECTED == state) {
+					m_pMyStatusbar->setCimBtnText("Selected");
+					//m_labelPassiveState.setBackground(SELECTED_BACKGROUND);
+					//m_labelPassiveState.setForeground(SELECTED_FOREGROUND, TRUE);
+				}
+			}
 			pAny->release();
 		}, [&]() -> void {
 			// onComplete
@@ -537,6 +563,30 @@
 }
 
 void CServoDlg::OnUpdateMenuFileExit(CCmdUI* pCmdUI)
+{
+	pCmdUI->Enable(TRUE);
+}
+
+void CServoDlg::OnMenuProjectVarialbleList()
+{
+	CHMPropertyDlg dlg(_T("Variable | Rreport | Collection Event"), 658, 788);
+
+	CPageCollectionEvent* pPage1 = new CPageCollectionEvent();
+	pPage1->Create(IDD_PAGE_COLLECTION_EVENT);
+	dlg.addPage(pPage1, "Event");
+
+	CPageReport* pPage2 = new CPageReport();
+	pPage2->Create(IDD_PAGE_REPORT);
+	dlg.addPage(pPage2, "Report");
+
+	CPageVarialbles* pPage3 = new CPageVarialbles();
+	pPage3->Create(IDD_PAGE_VARIABLE);
+	dlg.addPage(pPage3, "Variable");
+
+	dlg.DoModal();
+}
+
+void CServoDlg::OnUpdateMenuProjectVarialbleList(CCmdUI* pCmdUI)
 {
 	pCmdUI->Enable(TRUE);
 }
@@ -989,6 +1039,9 @@
 		m_pRobotTaskDlg->MoveWindow(x, rcBar.top - h, w, h);
 		m_pRobotTaskDlg->ShowWindow(SW_SHOW);
 	}
+	else if (id == IDC_BUTTON_CIM) {
+		AfxMessageBox("IDC_BUTTON_CIM");
+	}
 	return 0;
 }
 
diff --git a/SourceCode/Bond/Servo/ServoDlg.h b/SourceCode/Bond/Servo/ServoDlg.h
index 454d778..d0ce0f2 100644
--- a/SourceCode/Bond/Servo/ServoDlg.h
+++ b/SourceCode/Bond/Servo/ServoDlg.h
@@ -90,6 +90,8 @@
 	afx_msg void OnUpdateMenuFileSecsTest(CCmdUI* pCmdUI);
 	afx_msg void OnMenuFileExit();
 	afx_msg void OnUpdateMenuFileExit(CCmdUI* pCmdUI);
+	afx_msg void OnMenuProjectVarialbleList();
+	afx_msg void OnUpdateMenuProjectVarialbleList(CCmdUI* pCmdUI);
 	afx_msg void OnMenuTestMessageSet();
 	afx_msg void OnUpdateMenuTestMessageSet(CCmdUI* pCmdUI);
 	afx_msg void OnMenuTestMessageClear();
diff --git a/SourceCode/Bond/Servo/resource.h b/SourceCode/Bond/Servo/resource.h
index a43bde2..3a430cc 100644
--- a/SourceCode/Bond/Servo/resource.h
+++ b/SourceCode/Bond/Servo/resource.h
Binary files differ
diff --git a/SourceCode/Bond/x64/Debug/CollectionEventList.txt b/SourceCode/Bond/x64/Debug/CollectionEventList.txt
new file mode 100644
index 0000000..48df026
--- /dev/null
+++ b/SourceCode/Bond/x64/Debug/CollectionEventList.txt
@@ -0,0 +1,39 @@
+300,AccessMode_To_Manual,,(300)
+301,AccessMode_To_Auto,,(301)
+600,ControlStateChanged,,(600)
+700,ProcessStateChanged,,(700)
+10000,RecipeChanged,,(10000)
+10030,CarrierArrived,,(10300)
+10031,CarrierRemoved,,(10300)
+10040,ReadyToLoad,,(10300)
+10041,ReadyToUnLoad,,(10300)
+10051,CarrierIDWaitingForHost,,(10051)
+10052,CarrierIDVerificationOK,,(10052)
+10053,CarrierIDVerificationNG,,(10052)
+10061,SlotMapWaitingForHost,,(10061)
+10062,SlotMapVerificationOK,,(10062)
+10063,SlotMapVerificationNG,,(10062)
+10071,GlassIDReadWaitingForHost,,(10071)
+10072,GlassIDReadVerificationOK,,(10072)
+10073,GlassIDReadVerificationNG,,(10072)
+10080,CarrierStart,,(10080)
+10081,CarrierCompleted,,(10080)
+10082,CarrierStopped,,(10080)
+20000,GlassSlotStart,,(20000)
+20001,GlassSlotCompleted,,(20000)
+30000,PrJobPooled,,(30000)
+30001,PrJobAbort,,(30000)
+30010,PrJobProcessing,,(30000)
+30011,PrJobCompleted,,(30000)
+30013,PrJobPaused,,(30000)
+30014,PrJobResume,,(30000)
+30020,PrJobDeleted,,(30000)
+31000,CJobQueued,,(31000)
+31001,CJobAbort,,(31000)
+31010,CJobExecuting,,(31000)
+31020,CJobCompleted,,(31000)
+31021,CJobDeleted,,(31000)
+31031,CJobPaused,,(31000)
+31032,CJobResume,,(31000)
+40000,E90_SPSM_NoState_To_NeedsProcessing,,(40000)
+40001,E90_SPSM_InProcess_To_ProcessCompleted,,(40000)
diff --git a/SourceCode/Bond/x64/Debug/ReportList.txt b/SourceCode/Bond/x64/Debug/ReportList.txt
new file mode 100644
index 0000000..f614e93
--- /dev/null
+++ b/SourceCode/Bond/x64/Debug/ReportList.txt
@@ -0,0 +1,17 @@
+RPTID,(VID1,VID2,...)
+300,(1,300)
+301,(1,300)
+600,(500,600,601)
+700,(500,700,701)
+10000,(200,201)
+10300,(1,10000)
+10051,(1,10000,10100,10101)
+10061,(1,10000,10100,10200)
+10062,(1,10000,10100,10201,10202)
+10071,(1,10000,10100,10203,20000)
+10072,(1,10000,10100,10203,20000,20001)
+10080,(1,10000,10100)
+20000,(1,10000,10203)
+30000,(1,30000,30001)
+31000,(1,31000,31001)
+40000,(1,10203,20000)
diff --git a/SourceCode/Bond/x64/Debug/VariableList.txt b/SourceCode/Bond/x64/Debug/VariableList.txt
new file mode 100644
index 0000000..5bb7d38
--- /dev/null
+++ b/SourceCode/Bond/x64/Debug/VariableList.txt
@@ -0,0 +1,37 @@
+SVID,SV Name,SV Format,SV Remark
+100,PortTransferState,U1,0=OutOfService\r\n1=TransferBlocked\r\n2=ReadyToLoad\r\n3=ReadyToUnload\r\n4=InService\r\n5=TransferReady
+300,AccessMode,U1,1=Manual\r\n2=Auto
+500,Clock,A50,
+600,CurrentControlState,U1,0:Offline:equipment\r\n1:Offline-Attempt\r\n2:Online\r\n3:Offline:host\r\n4:Online:Local\r\n5:Online:Remote
+601,PreviousControlState,U1,
+700,CurrentProcessState,U1,0:DOWN\r\n1:IDLE\r\n2.SETUP\r\n3.EXCUTING\r\n4.MAINTAIN\r\n5.ALARM
+701,PreviousProcessState,U1,
+800,EFEMPPExecName,A20,
+801,EQPPExecName,A20,
+1000,CJobSpace,U1,
+2000,RbRAxisTorque,I2,机器人R轴扭矩
+2001,RbLAxisTorque,l2,机器人L轴扭矩
+2002,RbZAxisTorque,l2,机器人Z轴扭矩
+2003,RbTHAxisTorque,l2,机器人TH轴扭矩
+2004,RbXAxisTorque,l2,机器人X轴扭矩
+2005,AxisX111,l2,X111相机前移栽电机扭矩
+2006,AxisX112,l2,X112相机后移栽电机扭矩
+2007,AxisU113,l2,U113产品旋转电机扭矩
+2008,AxisX114,l2,X114产品左整列电机扭矩
+2009,AxisY121,l2,Y121产品右整列电机扭矩
+2010,AxisY122,l2,Y122产品前整列电机扭矩
+2011,AxisY123,l2,Y123产品后阵列电机扭矩
+2012,MainAir,U2,总进气压力值
+2013,MainVacuum,l2,总真空压力值
+2014,RbMainVacuum,l2,机器人真空值
+2015,LPMainVacuum,l2,LP真空值#D265
+2016,LPMainAir,U2,LP压空值
+2017,ALVacuum,l2,Aligner真空值
+2018,FFU1RPM,U2,FFU1转速
+2019,FFU2RPM,U2,FFU2转速
+2020,FFU3RPM,U2,FFU3转速
+2021,FFU4RPM,U2,FFU4转速
+2022,ESDValue,I2,静电检测值
+2023,OCREnable,U2,"OCR使能:O:开启 1:屏蔽"
+2024,CCDEnable,U2,"CCD使能:O:开启 1:屏蔽"
+2025,FFUParameter,U2,FFU设定值

--
Gitblit v1.9.3