3460128b4722b53bf92551fb00ce276177efc003..72f3802bd7ab24b672c951a287787b5dea253f3b
2025-08-02 mrDarker
Merge branch 'clh' into liuyang
72f380 对比 | 目录
2025-08-02 mrDarker
1. 添加计算时间戳宏 2. 重写切割两片玻璃函数 3. 添加分组过滤干扰点的函数
201046 对比 | 目录
2025-08-01 mrDarker
1. 添加日志文件
61ac29 对比 | 目录
2025-08-01 LAPTOP-SNT8I5JK\Boounion
1.千传模式,待测;
58edd8 对比 | 目录
2025-08-01 mrDarker
1. 新增以下功能函数并集成: - InitStorage():初始化存储区域 - StartStorage():开始数据存储 - ...
5a8bbd 对比 | 目录
2025-08-01 mrDarker
1. 添加光谱传感器模块
2be151 对比 | 目录
2025-08-01 LAPTOP-SNT8I5JK\Boounion
1.Spooled Data功能实现; 2.Request spooled data消息响应,EAP模拟测试;
cf3544 对比 | 目录
2025-07-30 LAPTOP-SNT8I5JK\Boounion
1.配方列表获取完善;
90ae1c 对比 | 目录
2025-07-30 LAPTOP-SNT8I5JK\Boounion
1.获取配方后自动刷新列表; 2.HsmsAction序列化和反序列化,将来用于缓存上报的数据;
166fa1 对比 | 目录
2025-07-29 LAPTOP-SNT8I5JK\Boounion
1.Port编码错位问题修复; 2.调度时的判断条件优化。 3.支持上料下料混合;
1e0e0a 对比 | 目录
2025-07-29 LAPTOP-SNT8I5JK\Boounion
1.Port Enable修改为保存配置到本地,不再同步与EFEM通讯;
15a7d8 对比 | 目录
2025-07-28 LAPTOP-SNT8I5JK\Boounion
Merge branch 'EAPSimulator' into clh
e51c6d 对比 | 目录
2025-07-28 LAPTOP-SNT8I5JK\Boounion
1.Spooling Config功能EAP模拟测试;
bfe14e 对比 | 目录
2025-07-28 LAPTOP-SNT8I5JK\Boounion
1.暂存
e20a6e 对比 | 目录
2025-07-25 LAPTOP-SNT8I5JK\Boounion
1.Master端,Line Event Report功能修改完善,并通过EAP模拟测试OK;
247a2a 对比 | 目录
2025-07-25 LAPTOP-SNT8I5JK\Boounion
1.EAP模拟端,已增加发送Link Event Report功能接口并正确发送数据,待Master解释和逻辑处理。
d6d85f 对比 | 目录
2025-07-24 LAPTOP-SNT8I5JK\Boounion
1.EAP模拟器,增加Link Report加载功能,列表展示功能,修改Report ID功能,但未真正下发到指令到Master.
8b96ca 对比 | 目录
2025-07-21 LAPTOP-SNT8I5JK\Boounion
1.none
421aab 对比 | 目录
2025-07-19 LAPTOP-SNT8I5JK\Boounion
1.Define Report功能测试,EAP模拟
8860b7 对比 | 目录
2025-07-16 LAPTOP-SNT8I5JK\Boounion
1.CollectionEvent列表从文件加载,界面上显示;
789af4 对比 | 目录
2025-07-15 LAPTOP-SNT8I5JK\Boounion
1.CReport列表在界面中的显示;
669b64 对比 | 目录
2025-07-15 LAPTOP-SNT8I5JK\Boounion
1.Variable列表显示到界面; 2.从文件中加载CReport列表;
e48a55 对比 | 目录
2025-07-14 LAPTOP-SNT8I5JK\Boounion
1.CCollectionEvent,CLoadPort, CVariable类实现; 2.从.txt或csv中加载CVariable列表; 3.添加...
375342 对比 | 目录
2025-07-11 LAPTOP-SNT8I5JK\Boounion
1.EAP模拟器,启用或禁用警告上报功能实现和模拟测试; 2.Master端,收到EAP的启用或警告消息上报消息后,保存相关配置,如后续机器发生警告,...
84925a 对比 | 目录
2025-07-11 LAPTOP-SNT8I5JK\Boounion
1.EAP模拟器,Eanble/Disable Event对话框,可以模拟EAP下发 Enable/Disable Event Report; 2.M...
2de4eb 对比 | 目录
2025-07-11 LAPTOP-SNT8I5JK\Boounion
1.EAP模拟器之警告信息模拟
4a102d 对比 | 目录
2025-07-11 LAPTOP-SNT8I5JK\Boounion
1.终端信息显示模拟测试;
c96ec4 对比 | 目录
2025-07-08 LAPTOP-SNT8I5JK\Boounion
1.增加日期时间同步功能和测试;
d9c3fb 对比 | 目录
2025-07-08 LAPTOP-SNT8I5JK\Boounion
1.UI分组启用和禁用,方便增加更多测试功能时代码整洁简单; 2.增加Are You There测试;
a9e9f7 对比 | 目录
2025-07-08 LAPTOP-SNT8I5JK\Boounion
1.基础通讯,建立连接;
f0f942 对比 | 目录
2025-07-03 LAPTOP-SNT8I5JK\Boounion
1.引入RxWindows和HSMS库
34833f 对比 | 目录
2025-07-03 LAPTOP-SNT8I5JK\Boounion
1.EAPSimulator初始搭建。
0772eb 对比 | 目录
已添加95个文件
已修改42个文件
12023 ■■■■■ 文件已修改
.gitignore 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Document/ESWIN_EAS_Bonder_Inline_Mapping_Address_v1.1.8(1).xlsx 补丁 | 查看 | 原始文档 | blame | 历史
Document/MASTER学习资料/LingSignal - 副本.bmp 补丁 | 查看 | 原始文档 | blame | 历史
Document/MASTER学习资料/LingSignal.bmp 补丁 | 查看 | 原始文档 | blame | 历史
Document/MASTER学习资料/LingSignal2.txt 58 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Document/MASTER学习资料/SECS通讯整理.xlsx 补丁 | 查看 | 原始文档 | blame | 历史
Document/Panel Bonder八零联合 SecsTest CheckList_v3.0.xlsx 补丁 | 查看 | 原始文档 | blame | 历史
Document/VariableList.txt 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Document/simulator/SEComSimulator.Conf 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/EAPSimulator/CAddIDSDlg.cpp 65 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/EAPSimulator/CAddIDSDlg.h 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/EAPSimulator/CCollectionEvent.cpp 110 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/EAPSimulator/CCollectionEvent.h 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/EAPSimulator/CDefineReportsDlg.cpp 193 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/EAPSimulator/CDefineReportsDlg.h 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/EAPSimulator/CEDEventReportDlg.cpp 71 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/EAPSimulator/CEDEventReportDlg.h 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/EAPSimulator/CHsmsActive.cpp 309 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/EAPSimulator/CHsmsActive.h 78 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/EAPSimulator/CLinkReportDetailDlg.cpp 65 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/EAPSimulator/CLinkReportDetailDlg.h 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/EAPSimulator/CLinkReportDlg.cpp 205 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/EAPSimulator/CLinkReportDlg.h 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/EAPSimulator/CModel.cpp 300 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/EAPSimulator/CModel.h 43 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/EAPSimulator/CReport.cpp 98 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/EAPSimulator/CReport.h 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/EAPSimulator/CTerminalDisplayDlg.cpp 73 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/EAPSimulator/CTerminalDisplayDlg.h 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/EAPSimulator/CVariable.cpp 90 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/EAPSimulator/CVariable.h 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/EAPSimulator/Common.h 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/EAPSimulator/Context.cpp 184 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/EAPSimulator/Context.h 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/EAPSimulator/EAPSimulator.cpp 133 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/EAPSimulator/EAPSimulator.h 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/EAPSimulator/EAPSimulator.rc 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/EAPSimulator/EAPSimulator.vcxproj 247 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/EAPSimulator/EAPSimulator.vcxproj.filters 153 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/EAPSimulator/EAPSimulator.vcxproj.user 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/EAPSimulator/EAPSimulatorDlg.cpp 371 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/EAPSimulator/EAPSimulatorDlg.h 59 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/EAPSimulator/Log.cpp 214 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/EAPSimulator/Log.h 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/EAPSimulator/LogEdit.cpp 117 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/EAPSimulator/LogEdit.h 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/EAPSimulator/Resource.h 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/EAPSimulator/framework.h 49 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/EAPSimulator/pch.cpp 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/EAPSimulator/pch.h 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/EAPSimulator/res/EAPSimulator.ico 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/EAPSimulator/res/EAPSimulator.rc2 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/EAPSimulator/res/application.exe.manifest 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/EAPSimulator/targetver.h 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/GangBond2860.sln 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/HSMSSDK/Include/HSMSSDK.h 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/HSMSSDK/Include/IActive.h 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/HSMSSDK/Include/IMessage.h 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/HSMSSDK/Include/ISECS2Item.h 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/SGMeasurement/DLL/32bit/SGIF.h 1641 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/SGMeasurement/DLL/32bit/SGIFPJ.dll 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/SGMeasurement/DLL/32bit/SGIFPJ.lib 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/SGMeasurement/DLL/64bit/SGIF.h 1641 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/SGMeasurement/DLL/64bit/SGIFPJ.dll 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/SGMeasurement/DLL/64bit/SGIFPJ.lib 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/SGMeasurement/DLL/ZY系列通信库参考手册-V2.3.pdf 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/SGMeasurement/Logger.cpp 79 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/SGMeasurement/Logger.h 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/SGMeasurement/SGMeasurement.cpp 104 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/SGMeasurement/SGMeasurement.h 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/SGMeasurement/SGMeasurement.rc 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/SGMeasurement/SGMeasurement.vcxproj 231 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/SGMeasurement/SGMeasurement.vcxproj.filters 75 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/SGMeasurement/SGMeasurement.vcxproj.user 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/SGMeasurement/SGMeasurementDlg.cpp 1150 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/SGMeasurement/SGMeasurementDlg.h 333 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/SGMeasurement/framework.h 49 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/SGMeasurement/pch.cpp 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/SGMeasurement/pch.h 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/SGMeasurement/res/SGMeasurement.ico 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/SGMeasurement/res/SGMeasurement.rc2 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/SGMeasurement/res/menu_close.ico 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/SGMeasurement/res/menu_restore.ico 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/SGMeasurement/resource.h 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/SGMeasurement/targetver.h 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CBakeCooling.cpp 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CBonder.cpp 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CCollectionEvent.cpp 113 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CCollectionEvent.h 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CEFEM.cpp 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CEquipment.cpp 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CEquipment.h 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CLoadPort.cpp 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CMaster.cpp 230 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CMaster.h 19 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CMeasurement.cpp 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CMyStatusbar.cpp 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CMyStatusbar.h 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CPageCollectionEvent.cpp 126 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CPageCollectionEvent.h 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CPageGraph2.cpp 84 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CPagePortProperty.cpp 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CPagePortStatus.cpp 15 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CPageReport.cpp 126 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CPageReport.h 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CPageVarialbles.cpp 133 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CPageVarialbles.h 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CPortStatusReport.cpp 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CReport.cpp 98 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CReport.h 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CVacuumBake.cpp 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CVariable.cpp 90 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CVariable.h 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/Common.h 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/Configuration.cpp 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/Configuration.h 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/HsmsAction.cpp 59 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/HsmsAction.h 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/HsmsPassive.cpp 782 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/HsmsPassive.h 92 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/Model.cpp 48 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/Model.h 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/PageRecipe.cpp 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/Servo.rc 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/Servo.vcxproj 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/Servo.vcxproj.filters 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/Servo.vcxproj.user 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/ServoDlg.cpp 75 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/ServoDlg.h 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/TopToolbar.cpp 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/TopToolbar.h 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/resource.h 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/x64/Debug/CollectionEventList.txt 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/x64/Debug/ReportList.txt 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/x64/Debug/Res/RunCt_Gray_32.ico 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/x64/Debug/Res/RunCt_High_32.ico 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/x64/Debug/VariableList.txt 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.gitignore
@@ -57,4 +57,4 @@
SourceCode/Bond/x64/Debug/Config/robot_offset.ini
*.tlog
*.pch
SourceCode/Bond/EAPSimulator/x64/Debug/
SourceCode/Bond/EAPSimulator/x64/
Document/ESWIN_EAS_Bonder_Inline_Mapping_Address_v1.1.8(1).xlsx
Binary files differ
Document/MASTERѧϰ×ÊÁÏ/LingSignal - ¸±±¾.bmp
Document/MASTERѧϰ×ÊÁÏ/LingSignal.bmp
Document/MASTERѧϰ×ÊÁÏ/LingSignal2.txt
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,58 @@
| ä¿¡å·åç§°                            | EAS角色(读/写) | è¯´æ˜Ž                |
| ------------------------------- | ---------- | ----------------- |
| Downstream Inline               | è¯»          | ä¸‹æ¸¸Inline状态,设备告知主机 |
| Downstream Trouble              | è¯»          | ä¸‹æ¸¸å¼‚常通知,设备发给主机     |
| Interlock                       | è¯»          | äº’锁状态,设备反馈         |
| Send Able                       | è¯»          | è®¾å¤‡æ˜¯å¦å‡†å¤‡å¥½å‘送Glass信号  |
| Send Start                      | å†™          | ä¸»æœºæŒ‡ä»¤è®¾å¤‡å¼€å§‹å‘送Glass   |
| Job Transfer                    | å†™          | ä¸»æœºæŒ‡ä»¤è®¾å¤‡è¿›è¡ŒJob转移     |
| Send Complete                   | è¯»          | è®¾å¤‡åé¦ˆå‘送完成信号        |
| Shutter State                   | è¯»          | è®¾å¤‡æŒ¡æ¿çŠ¶æ€ï¼Œè®¾å¤‡åé¦ˆ       |
| Pin State                       | è¯»          | è®¾å¤‡é’ˆè„šçŠ¶æ€            |
| Slot Pair Flag                  | è¯»          | è®¾å¤‡åé¦ˆSlot配对状态      |
| Arm Slot Pair Flag              | è¯»          | æœºæ¢°è‡‚Slot配对状态       |
| 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
Document/MASTERѧϰ×ÊÁÏ/SECSͨѶÕûÀí.xlsx
Binary files differ
Document/Panel Bonder°ËÁãÁªºÏ SecsTest CheckList_v3.0.xlsx
Binary files differ
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,机器人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设定值
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>
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();
}
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();
};
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;
    }
}
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;
    };
}
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);
}
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();
};
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);
}
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();
};
SourceCode/Bond/EAPSimulator/CHsmsActive.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,309 @@
#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) {
            // S5F1
            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::hsmsTransmitSpooledData()
{
    IMessage* pMessage = nullptr;
    int nRet = HSMS_Create1Message(pMessage, m_nSessionId, 6 | REPLY, 23, ++m_nSystemByte);
    pMessage->getBody()->setU1(0, "RSDC");
    m_pActive->sendMessage(pMessage);
    HSMS_Destroy1Message(pMessage);
    return 0;
}
int CHsmsActive::hsmsPurgeSpooledData()
{
    IMessage* pMessage = nullptr;
    int nRet = HSMS_Create1Message(pMessage, m_nSessionId, 6 | REPLY, 23, ++m_nSystemByte);
    pMessage->getBody()->setU1(1, "RSDC");
    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);
}
SourceCode/Bond/EAPSimulator/CHsmsActive.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,78 @@
#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);
    // å‘送或清空缓存的消息
    int hsmsTransmitSpooledData();
    int hsmsPurgeSpooledData();
    // é€šè¿‡çš„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;
};
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();
}
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();
};
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();
}
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();
};
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;
}
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;
};
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;
    }
}
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;
    };
}
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);
}
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();
};
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;
    }
}
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;
    };
}
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
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;
}
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;
};
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;
    // æ¿€æ´»â€œWindows 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);
    // åˆå§‹åŒ–Rx库
    RX_Init();
    HSMS_Initialize();
    CEAPSimulatorDlg dlg;
    m_pMainWnd = &dlg;
    INT_PTR nResponse = dlg.DoModal();
    if (nResponse == IDOK)
    {
        // TODO: åœ¨æ­¤æ”¾ç½®å¤„理何时用
        //  â€œç¡®å®šâ€æ¥å…³é—­å¯¹è¯æ¡†çš„代码
    }
    else if (nResponse == IDCANCEL)
    {
        // TODO: åœ¨æ­¤æ”¾ç½®å¤„理何时用
        //  â€œå–消”来关闭对话框的代码
    }
    else if (nResponse == -1)
    {
        TRACE(traceAppMsg, 0, "警告: å¯¹è¯æ¡†åˆ›å»ºå¤±è´¥ï¼Œåº”用程序将意外终止。\n");
        TRACE(traceAppMsg, 0, "警告: å¦‚果您在对话框上使用 MFC æŽ§ä»¶ï¼Œåˆ™æ— æ³• #define _AFX_NO_MFC_CONTROLS_IN_DIALOGS。\n");
    }
    // åˆ é™¤ä¸Šé¢åˆ›å»ºçš„ shell ç®¡ç†å™¨ã€‚
    if (pShellManager != 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();
}
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;
SourceCode/Bond/EAPSimulator/EAPSimulator.rc
Binary files differ
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>
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>
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>
SourceCode/Bond/EAPSimulator/EAPSimulatorDlg.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,371 @@

// 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)
    ON_BN_CLICKED(IDC_BUTTON_TRANSMIT_SPOOLED_DATA, &CEAPSimulatorDlg::OnBnClickedButtonTransmitSpooledData)
    ON_BN_CLICKED(IDC_BUTTON_PURGE_SPOOLED_DATA, &CEAPSimulatorDlg::OnBnClickedButtonPurgeSpooledData)
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);
    }
}
// å¦‚果向对话框添加最小化按钮,则需要下面的代码
//  æ¥ç»˜åˆ¶è¯¥å›¾æ ‡ã€‚  å¯¹äºŽä½¿ç”¨æ–‡æ¡£/视图模型的 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);
    GetDlgItem(IDC_BUTTON_TRANSMIT_SPOOLED_DATA)->EnableWindow(enabled);
    GetDlgItem(IDC_BUTTON_PURGE_SPOOLED_DATA)->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);
}
void CEAPSimulatorDlg::OnBnClickedButtonTransmitSpooledData()
{
    theApp.m_model.m_pHsmsActive->hsmsTransmitSpooledData();
}
void CEAPSimulatorDlg::OnBnClickedButtonPurgeSpooledData()
{
    theApp.m_model.m_pHsmsActive->hsmsPurgeSpooledData();
}
SourceCode/Bond/EAPSimulator/EAPSimulatorDlg.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,59 @@

// 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();
    afx_msg void OnBnClickedButtonTransmitSpooledData();
    afx_msg void OnBnClickedButtonPurgeSpooledData();
};
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;
}
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;
};
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();
    }
}
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);
};
SourceCode/Bond/EAPSimulator/Resource.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,60 @@
//{{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_BUTTON_TRANSMIT_SPOOLED_DATA 1013
#define IDC_EDIT_CEID                   1014
#define IDC_BUTTON_PURGE_SPOOLED_DATA   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
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
SourceCode/Bond/EAPSimulator/pch.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,5 @@
// pch.cpp: ä¸Žé¢„编译标头对应的源文件
#include "pch.h"
// å½“使用预编译的头时,需要使用此源文件,编译才能成功。
SourceCode/Bond/EAPSimulator/pch.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,17 @@
// pch.h: è¿™æ˜¯é¢„编译标头文件。
// ä¸‹æ–¹åˆ—出的文件仅编译一次,提高了将来生成的生成性能。
// è¿™è¿˜å°†å½±å“ IntelliSense æ€§èƒ½ï¼ŒåŒ…括代码完成和许多代码浏览功能。
// ä½†æ˜¯ï¼Œå¦‚果此处列出的文件中的任何一个在生成之间有更新,它们全部都将被重新编译。
// è¯·å‹¿åœ¨æ­¤å¤„添加要频繁更新的文件,这将使得性能优势无效。
#ifndef PCH_H
#define PCH_H
// æ·»åŠ è¦åœ¨æ­¤å¤„é¢„ç¼–è¯‘çš„æ ‡å¤´
#include "framework.h"
#include "..\RxWindows1.0\include\RxWindowsLib.h"
#include "..\HSMSSDK\Include\HSMSSDK.h"
#endif //PCH_H
SourceCode/Bond/EAPSimulator/res/EAPSimulator.ico
SourceCode/Bond/EAPSimulator/res/EAPSimulator.rc2
Binary files differ
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>
SourceCode/Bond/EAPSimulator/targetver.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,8 @@
#pragma once
// åŒ…括 SDKDDKVer.h å°†å®šä¹‰å¯ç”¨çš„æœ€é«˜ç‰ˆæœ¬çš„ Windows å¹³å°ã€‚
//如果要为以前的 Windows å¹³å°ç”Ÿæˆåº”用程序,请包括 WinSDKVer.h,并
// å°† _WIN32_WINNT å®è®¾ç½®ä¸ºè¦æ”¯æŒçš„平台,然后再包括 SDKDDKVer.h。
#include <SDKDDKVer.h>
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 17
VisualStudioVersion = 17.13.35913.81 d17.13
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BEQLibrary", "BEQLibrary\BEQLibrary.vcxproj", "{8421CE64-06F9-48F4-A3F3-ACFB683C94D4}"
EndProject
@@ -14,6 +14,10 @@
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
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SGMeasurement", "SGMeasurement\SGMeasurement.vcxproj", "{F8087F20-3A3E-18F2-09E3-9C139642EB58}"
EndProject
Global
    GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -71,6 +75,22 @@
        {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
        {F8087F20-3A3E-18F2-09E3-9C139642EB58}.Debug|x64.ActiveCfg = Debug|x64
        {F8087F20-3A3E-18F2-09E3-9C139642EB58}.Debug|x64.Build.0 = Debug|x64
        {F8087F20-3A3E-18F2-09E3-9C139642EB58}.Debug|x86.ActiveCfg = Debug|Win32
        {F8087F20-3A3E-18F2-09E3-9C139642EB58}.Debug|x86.Build.0 = Debug|Win32
        {F8087F20-3A3E-18F2-09E3-9C139642EB58}.Release|x64.ActiveCfg = Release|x64
        {F8087F20-3A3E-18F2-09E3-9C139642EB58}.Release|x64.Build.0 = Release|x64
        {F8087F20-3A3E-18F2-09E3-9C139642EB58}.Release|x86.ActiveCfg = Release|Win32
        {F8087F20-3A3E-18F2-09E3-9C139642EB58}.Release|x86.Build.0 = Release|Win32
    EndGlobalSection
    GlobalSection(SolutionProperties) = preSolution
        HideSolutionNode = FALSE
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
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;
};
SourceCode/Bond/HSMSSDK/Include/IMessage.h
@@ -29,4 +29,6 @@
    virtual HEADER* getHeader() = 0;
    virtual ISECS2Item* getBody() = 0;
    virtual const char* toString() = 0;
    virtual int serialize(char* pszBuffer, int nBufferSize) = 0;
    virtual int unserialize(const char* pszBuffer, int nBufferSize) = 0;
};
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,7 @@
    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 void setU1(unsigned char value, const char* pszNote) = 0;
    virtual ISECS2Item* addItem() = 0;
};
SourceCode/Bond/SGMeasurement/DLL/32bit/SGIF.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,1641 @@
#ifdef SGIF_EXPORTS
#define EXP __declspec(dllexport)
#else
#define EXP __declspec(dllimport)
#endif
#include "Winsock2.h"
#include "Ws2tcpip.h"
#include <stdlib.h>
#include <stdio.h>
#include <windows.h>
#pragma comment(lib, "WS2_32.lib")
// Return Code List
typedef enum {
    RC_OK = 0x0000,
    // The operation is completed successfully.
    ///////////////////////////////////////////////
    // Communication error from controller notification
    //
    RC_NAK_COMMAND = 0x1001,        // Command error
    RC_NAK_COMMAND_LENGTH,            // Command length error
    RC_NAK_TIMEOUT,                    // Timeout
    RC_NAK_CHECKSUM,                // Check sum error
    RC_NAK_INVALID_STATE,            // Status error
    RC_NAK_OTHER,                    // Other error
    RC_NAK_PARAMETER,                // Parameter error
    RC_NAK_OUT_STAGE,                // OUT calculation count limitation error
    RC_NAK_OUT_HEAD_NUM,            // No. of used head/OUT over error
    RC_NAK_PARAM_RANGE_DATA_STORED,    // OUT No which data reserved over acctive out count
    RC_NAK_OUT_INVALID_CALC,        // OUT which cannot be used for calculation was specified for calculation.
    RC_NAK_OUT_VOID,                // OUT which specified for calculation is not found.
    RC_NAK_INVALID_CYCLE,            // Unavailable sampling cycle
    RC_NAK_CTRL_ERROR,                // Main unit error
    RC_NAK_SRAM_ERROR,                // Setting value error
    ///////////////////////////////////////////////
    // Communication DLL error notification
    //
    RC_ERR_OPEN_DEVICE = 0x2000,// Opening the device failed.
    RC_ERR_NO_DEVICE,            // The device is not open.
    RC_ERR_SEND,                // Command sending error
    RC_ERR_RECEIVE,                // Response receiving error
    RC_ERR_TIMEOUT,                // Timeout
    RC_ERR_NODATA,                // No data
    RC_ERR_NOMEMORY,            // No free memory
    RC_ERR_DISCONNECT,            // Cable disconnection suspected
    RC_ERR_UNKNOWN,                // Undefined error
    RC_ERR_DEVID_OVER,            // over dev_id scale
    RC_ERR_NET_NO_CONN,            // no connected at the deviceID
    RC_ERR_IP_EXISTED,
    RC_ERR_SELECT,                // select of /socket error
    RC_ERR_NULL_PARAMETER,        // NULL point exception from parameter
    RC_ERR_DIY_FUNC,            // error due to dir function
    RC_ERR_OVER_PARAMENTER,        // paramenter over the limition
    RC_ERR_NOT_SUPPORT            // åŠŸèƒ½ä¸æ”¯æŒ
} RC;
//device Version
typedef enum {
    SG3035 = 0,
    SG3030 = 1,
    SG3085 = 2,
    SG3080 = 3,
    SG5025 = 4,
    SG5020 = 5,
    SG5055 = 6,
    SG5050 = 7,
    SG5085 = 8,
    SG5080 = 9,
    SG5155 = 10,
    SG5150 = 11,
    SC04025 = 12,
    SC03560 = 13,
    SGI500 = 14,
    SGI505 = 15,
    SGI400 = 16,
    SGI405 = 17,
    SGI150 = 18,
    SGI155 = 19,
    SGI080 = 20,
    SGI085 = 21,
    SGI050 = 22,
    SGI055 = 23,
    SGI030 = 24,
    SGI035 = 25,
    SGI020 = 26,
    SGI025 = 27,
    SG3155 = 28,
    SG3150 = 29,
    SC01045 = 30,
    SC10015 = 31,
    SC20011 = 32,
    SC01236 = 33,
    SCI04025 = 34,
    SCI03560 = 35,
    SCI01045 = 36,
    SCI10015 = 37,
    SCI20011 = 38,
    SCI01236 = 39,
}SGIF_DEVICE_TYPE;
// Measurement value structures
typedef enum {
    SGIF_FLOATRESULT_VALID,            // valid data
    SGIF_FLOATRESULT_RANGEOVER_P,    // over range at positive (+) side
    SGIF_FLOATRESULT_RANGEOVER_N,    // over range at negative (-) side
    SGIF_FLOATRESULT_WAITING,        // Wait for comparator result
    SGIF_FLOATRESULT_ALARM,            // alarm
    SGIF_FLOATRESULT_INVALID,        // Invalid (error, etc.)
} SGIF_FLOATRESULT;
// Set ABLE
typedef enum {
    SGIF_ABLEMODE_AUTO,                // AUTO
    SGIF_ABLEMODE_MANUAL,            // manual
} SGIF_ABLEMODE;
// Set Measurement Mode
typedef enum {
    SGIF_MEASUREMODE_NORMAL,                        // normal
    SGIF_MEASUREMODE_HALF_T,                        // translucent object
    SGIF_MEASUREMODE_TRAN_1,                        // transparent object
    SGIF_MEASUREMODE_TRAN_2,                        // transparent object 2
    SGIF_MEASUREMODE_MRS,                            // multireflective object
    SGIF_MEASUREMODE_OPAQUE = SGIF_MEASUREMODE_MRS,    // Semi opaque object
} SGIF_MEASUREMODE;
// Set Basic Point
typedef enum {
    SGIF_BASICPOINT_NEAR,            // NEAR
    SGIF_BASICPOINT_FAR,            // FAR
} SGIF_BASICPOINT;
// Set Mounting Mode
typedef enum {
    SGIF_REFLECTIONMODE_DIFFUSION,    // diffuse reflection
    SGIF_REFLECTIONMODE_MIRROR,        // specular reflection
} SGIF_REFLECTIONMODE;
// Set Median
typedef enum {
    SGIF_MEDIAN_OFF,                // OFF
    SGIF_MEDIAN_7,                    // 7 point
    SGIF_MEDIAN_15,                    // 15 point
    SGIF_MEDIAN_31,                    // 31 point
} SGIF_MEDIAN;
// Set LASER CTRL group.
typedef enum {
    SGIF_LASER_CTRL_GROUP_1,        // LASER CTRL 1
    SGIF_LASER_CTRL_GROUP_2,        // LASER CTRL 2
} SGIF_LASER_CTRL_GROUP;
// Set a range.
typedef enum {
    SGIF_RANGE_CENTER,                // CENTER
    SGIF_RANGE_FAR,                    // FAR
} SGIF_RANGE;
// Set Mutual Interference Prevention Group
typedef enum {
    SGIF_MUTUAL_INTERFERENCE_PREVENTION_GROUP_A,    // Group A
    SGIF_MUTUAL_INTERFERENCE_PREVENTION_GROUP_B,    // Group B
    SGIF_MUTUAL_INTERFERENCE_PREVENTION_GROUP_C,    // Group C
} SGIF_MUTUAL_INTERFERENCE_PREVENTION_GROUP;
// Set calculation method.
typedef enum {
    SGIF_CALCMETHOD_HEADA,                    // head A
    SGIF_CALCMETHOD_HEADB,                    // head B
    SGIF_CALCMETHOD_HEAD_HEADA_PLUS_HEADB,    // head A+head B
    SGIF_CALCMETHOD_HEAD_HEADA_MINUS_HEADB,    // head A-head B
    SGIF_CALCMETHOD_HEAD_HEADA_TRANSPARENT,    // head A transparent object
    SGIF_CALCMETHOD_HEAD_HEADB_TRANSPARENT,    // head B transparent object
    SGIF_CALCMETHOD_HEAD = 0,    // head
    SGIF_CALCMETHOD_OUT,        // OUT
    SGIF_CALCMETHOD_ADD,        // ADD
    SGIF_CALCMETHOD_SUB,        // SUB
    SGIF_CALCMETHOD_AVE,        // AVE
    SGIF_CALCMETHOD_MAX,        // MAX
    SGIF_CALCMETHOD_MIN,        // MIN
    SGIF_CALCMETHOD_PP,            // P-P
} SGIF_CALCMETHOD;
// Set Target Surface
typedef enum {
    SGIF_CALCTARGET_PEAK_1,        // peak 1
    SGIF_CALCTARGET_PEAK_2,        // peak 2
    SGIF_CALCTARGET_PEAK_3,        // peak 3
    SGIF_CALCTARGET_PEAK_4,        // peak 4
    SGIF_CALCTARGET_PEAK_1_2,    // peak 1-peak 2
    SGIF_CALCTARGET_PEAK_1_3,    // peak 1-peak 3
    SGIF_CALCTARGET_PEAK_1_4,    // peak 1-peak 4
    SGIF_CALCTARGET_PEAK_2_3,    // peak 2-peak 3
    SGIF_CALCTARGET_PEAK_2_4,    // peak 2-peak 4
    SGIF_CALCTARGET_PEAK_3_4,    // peak 3-peak 4
} SGIF_CALCTARGET;
// Set Filter Mode
typedef enum {
    SGIF_FILTERMODE_MOVING_AVERAGE,            // moving average
} SGIF_FILTERMODE;
// Specify the filter parameter. (The number of averaging for moving average, or the cutoff frequency for LPF/HPF.)
typedef enum {
    SGIF_FILTERPARA_AVE_1 = 0,        // 1 time
    SGIF_FILTERPARA_AVE_4,            // 4 times
    SGIF_FILTERPARA_AVE_16,            // 16 times
    SGIF_FILTERPARA_AVE_64,            // 64 times
    SGIF_FILTERPARA_AVE_256,        // 256 times
    SGIF_FILTERPARA_AVE_1024,        // 1024 times
    SGIF_FILTERPARA_AVE_4096,        // 4096 times
    SGIF_FILTERPARA_AVE_16384,        // 16384 times
    SGIF_FILTERPARA_AVE_65536,        // 65536 times
    SGIF_FILTERPARA_AVE_262144,        // 262144 times
}SGIF_FILTERPARA;
// Set Trigger Mode
typedef enum {
    SGIF_TRIGGERMODE_EXT1,        // external trigger 1
    SGIF_TRIGGERMODE_EXT2,        // external trigger 2
} SGIF_TRIGGERMODE;
// Set the Measurement Mode.
typedef enum {
    SGIF_CALCMODE_NORMAL,            // normal
    SGIF_CALCMODE_PEAKHOLD,            // peak hold
    SGIF_CALCMODE_BOTTOMHOLD,        // bottom hold
    SGIF_CALCMODE_PEAKTOPEAKHOLD,    // peak-to-peak hold
    SGIF_CALCMODE_SAMPLEHOLD,        // sample hold
} SGIF_CALCMODE;
// Set Minimum Display Unit
typedef enum {
    SGIF_DISPLAYUNIT_0000_01MM = 0,    // 0.01mm
    SGIF_DISPLAYUNIT_000_001MM,        // 0.001mm
    SGIF_DISPLAYUNIT_00_0001MM,        // 0.0001mm
    SGIF_DISPLAYUNIT_0_00001MM,        // 0.00001mm
    SGIF_DISPLAYUNIT_00000_1UM,        // 0.1um
    SGIF_DISPLAYUNIT_0000_01UM,        // 0.01um
    SGIF_DISPLAYUNIT_000_001UM,        // 0.001um
} SGIF_DISPLAYUNIT;
// Specify OUT
typedef enum {
    SGIF_OUTNO_01 = 0x0001,            // OUT01
    SGIF_OUTNO_02 = 0x0002,            // OUT02
    SGIF_OUTNO_03 = 0x0004,            // OUT03
    SGIF_OUTNO_04 = 0x0008,            // OUT04
    SGIF_OUTNO_ALL = 0x000F,        // All OUTs
} SGIF_OUTNO;
// Set Storage (Cycle)
typedef enum {
    SGIF_STORAGECYCLE_1,            // sampling rate x 1
    SGIF_STORAGECYCLE_2,            // sampling rate x 2
    SGIF_STORAGECYCLE_5,            // sampling rate x 5
    SGIF_STORAGECYCLE_10,            // sampling rate x 10
    SGIF_STORAGECYCLE_20,            // sampling rate x 20
    SGIF_STORAGECYCLE_50,            // sampling rate x 50
    SGIF_STORAGECYCLE_100,            // sampling rate x 100
    SGIF_STORAGECYCLE_200,            // sampling rate x 200
    SGIF_STORAGECYCLE_500,            // sampling rate x 500
    SGIF_STORAGECYCLE_1000,            // sampling rate x 1000
    SGIF_STORAGECYCLE_TIMING,        // Timing sync
} SGIF_STORAGECYCLE;
// Set Sampling Rate
typedef enum {
    //SG5000系列
    SGIF_5000_SAMPLINGCYCLE_590KHZ,     // 590kHz
    SGIF_5000_SAMPLINGCYCLE_400KHZ,        // 400kHz
    SGIF_5000_SAMPLINGCYCLE_200KHZ,        // 200kHz
    SGIF_5000_SAMPLINGCYCLE_88KHZ,        // 88kHz
    SGIF_5000_SAMPLINGCYCLE_50KHZ,        // 50kHz
    SGIF_5000_SAMPLINGCYCLE_20KHZ,        // 20kHz
    SGIF_5000_SAMPLINGCYCLE_10KHZ,        // 10kHz
    SGIF_5000_SAMPLINGCYCLE_5KHZ,        // 5kHz
    SGIF_5000_SAMPLINGCYCLE_2KHZ,        // 2kHz
    SGIF_5000_SAMPLINGCYCLE_1KHZ,        // 1kHz+
    //SG3000系列
    SGIF_3000_SAMPLINGCYCLE_88KHZ = 10,    // 88kHz
    SGIF_3000_SAMPLINGCYCLE_50KHZ,        // 50kHz
    SGIF_3000_SAMPLINGCYCLE_20KHZ,        // 20kHz
    SGIF_3000_SAMPLINGCYCLE_10KHZ,        // 10kHz
    SGIF_3000_SAMPLINGCYCLE_5KHZ,        // 5kHz
    //SGIF_3000_SAMPLINGCYCLE_2KHZ,        // 2kHz
    SGIF_3000_SAMPLINGCYCLE_1KHZ,        // 1kHz
    //SCI系列
    SCI_SAMPLINGCYCLE_33KHZ = 30,    // 33kHz
    SCI_SAMPLINGCYCLE_20KHZ,        // 20kHz
    SCI_SAMPLINGCYCLE_15KHZ,        // 15kHz
    SCI_SAMPLINGCYCLE_10KHZ,        // 10kHz
    SCI_SAMPLINGCYCLE_5KHZ,            // 5kHz
    SCI_SAMPLINGCYCLE_2KHZ,            // 2kHz
    SCI_SAMPLINGCYCLE_1KHZ,            // 1kHz
    SCI_SAMPLINGCYCLE_05KHZ,        // 0.5kHz
} SGIF_SAMPLINGCYCLE;
// Set Mutual interference prevention
typedef enum {
    SGIF_MUTUAL_INTERFERENCE_PREVENTION_OFF,    // OFF
    SGIF_MUTUAL_INTERFERENCE_PREVENTION_AB_ON,    // AB-ON
    SGIF_MUTUAL_INTERFERENCE_PREVENTION_ABC_ON,    // ABC-ON
} SGIF_MUTUAL_INTERFERENCE_PREVENTION;
// Set Strobe Time
typedef enum {
    SGIF_STOROBETIME_2MS,        // 2ms
    SGIF_STOROBETIME_5MS,        // 5ms
    SGIF_STOROBETIME_10MS,        // 10ms
    SGIF_STOROBETIME_20MS,        // 20ms
} SGIF_STOROBETIME;
// Mode Switch
typedef enum {
    SGIF_MODE_NORMAL,                // normal mode
    SGIF_MODE_COMMUNICATION,        // setting mode
} SGIF_MODE;
//Encoder ext
typedef enum {
    SGIF_EmRunningMode_cont,//off
    SGIF_EmRunningMode_time,
    SGIF_EmRunningMode_trig,
}SGIF_EmRunningMode;
typedef enum {
    SGIF_EmDirection_all,//+-
    SGIF_EmDirection_pos,
    SGIF_EmDirection_neg,
}SGIF_EmDirection;
typedef enum {
    SGIF_EmEncoderInput_1x1,
    SGIF_EmEncoderInput_2x1,
    SGIF_EmEncoderInput_2x2,
    SGIF_EmEncoderInput_2x4,
}SGIF_EmEncoderInput;
typedef enum {
    SGIF_EmInputTime_100 = 100,
    SGIF_EmInputTime_200 = 200,
    SGIF_EmInputTime_500 = 500,
    SGIF_EmInputTime_1000 = 1000,
    SGIF_EmInputTime_2000 = 2000,
    SGIF_EmInputTime_5000 = 5000,
    SGIF_EmInputTime_10000 = 10000,
    SGIF_EmInputTime_20000 = 20000,
}SGIF_EmInputTime;
// Measurement value
typedef struct {
    int                    OutNo;            // OUT No(1-4)
    SGIF_FLOATRESULT    FloatResult;    // valid or invalid data
    float                Value;            // Measurement value
} SGIF_FLOATVALUE_OUT;
typedef struct {
    SGIF_FLOATRESULT    FloatResult;    // valid or invalid data
    float                Value;            // Measurement value
} SGIF_FLOATVALUE;
// IP address
typedef struct {
    IN_ADDR                IPAddress;
} SGIF_OPENPARAM_ETHERNET;
//Mask Minimum Display Unit(0.01mm)
#define MASKUNIT 100
#ifdef __cplusplus
extern "C"
{
#endif
    EXP RC WINAPI SGIF_GetDeviceType(IN int DeviceID, OUT SGIF_DEVICE_TYPE* deviceType);
    // Measured control commands
    ///
    /// \brief SGIF_GetCameraSpotType    å…‰æ–‘类型(不支持SCI)
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param ControlType:                è¾“出0:小光斑,1:大光斑
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_GetCameraSpotType(IN int DeviceID, OUT int *EissionSpotType);
    ///////////////////////////////////////////////
    // Measurement control commands
    //
    // Measured value output (single)
    ///
    /// \brief SGIF_GetCalcDataSingle    æµ‹é‡å€¼è¾“出
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param OutNo:                    è¾“出OUT编号
    /// \param CalcData:                æµ‹é‡å€¼
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_GetCalcDataSingle(IN int DeviceID, IN int OutNo, OUT SGIF_FLOATVALUE_OUT * CalcData);
    // Measured value output (multiple)
    ///
    /// \brief SGIF_GetCalcDataMulti    å¤šä¸ªæµ‹é‡å€¼è¾“出
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param OutNo:                    è¾“出OUT编号组合
    /// \param CalcData:                æµ‹é‡å€¼æ•°ç»„
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_GetCalcDataMulti(IN int DeviceID, IN SGIF_OUTNO OutNo, OUT SGIF_FLOATVALUE_OUT * CalcData);
    // Measured value output (ALL)
    ///
    /// \brief SGIF_GetCalcDataALL        å…¨éƒ¨æµ‹é‡å€¼è¾“出
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param CalcData:                æµ‹é‡å€¼æ•°ç»„
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_GetCalcDataALL(IN int DeviceID, OUT SGIF_FLOATVALUE_OUT * CalcData);
    // Timing ON/OFF (single)
    ///
    /// \brief SGIF_SetTimingSingle        è®¡æ—¶ON/OFF(一个)
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param OutNo:                    è¾“出OUT编号
    /// \param OnOff:                    å¼€æˆ–å…³
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_SetTimingSingle(IN int DeviceID, IN int OutNo, IN BOOL OnOff);
    // Timing ON/OFF (multiple)
    ///
    /// \brief SGIF_SetTimingMulti        è®¡æ—¶ON/OFF(多个)
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param OutNo:                    è¾“出OUT编号组合
    /// \param OnOff:                    å¼€æˆ–å…³
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_SetTimingMulti(IN int DeviceID, IN SGIF_OUTNO OutNo, IN BOOL OnOff);
    // Timing ON/OFF (synchronous)
    ///
    /// \brief SGIF_SetTimingSync        è®¡æ—¶ON/OFF(同步)
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param OnOff:                    å¼€æˆ–å…³
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_SetTimingSync(IN int DeviceID, IN BOOL OnOff);
    // Auto-zero ON/OFF (single)
    ///
    /// \brief SGIF_SetZeroSingle        è‡ªåŠ¨å½’é›¶ï¼ˆä¸€ä¸ªï¼‰
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param OutNo:                    è¾“出OUT编号
    /// \param OnOff:                    å¼€æˆ–å…³
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_SetZeroSingle(IN int DeviceID, IN int OutNo, IN BOOL OnOff);
    // Auto-zero ON/OFF (multiple)
    ///
    /// \brief SGIF_SetZeroMulti        è‡ªåŠ¨å½’é›¶ï¼ˆå¤šä¸ªï¼‰
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param OutNo:                    è¾“出OUT编号组合
    /// \param OnOff:                    å¼€æˆ–å…³
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_SetZeroMulti(IN int DeviceID, IN SGIF_OUTNO OutNo, IN BOOL OnOff);
    // Auto-zero ON/OFF (synchronous)
    ///
    /// \brief SGIF_SetZeroSync            è‡ªåŠ¨å½’é›¶ï¼ˆåŒæ­¥ï¼‰
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param OnOff:                    å¼€æˆ–å…³
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_SetZeroSync(IN int DeviceID, IN BOOL OnOff);
    // Measured value reset (single)
    ///
    /// \brief SGIF_SetResetSingle        é‡ç½®ï¼ˆä¸€ä¸ªï¼‰
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param OutNo:                    è¾“出OUT编号
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_SetResetSingle(IN int DeviceID, IN int OutNo);
    // Measured value reset (multiple)
    ///
    /// \brief SGIF_SetResetMulti        é‡ç½®ï¼ˆå¤šä¸ªï¼‰
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param OutNo:                    è¾“出OUT编号组合
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_SetResetMulti(IN int DeviceID, IN SGIF_OUTNO OutNo);
    // Measured value reset (synchronous)
    ///
    /// \brief SGIF_SetResetSync        é‡ç½®ï¼ˆåŒæ­¥ï¼‰
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_SetResetSync(IN int DeviceID);
    // Program Change
    ///
    /// \brief SGIF_SetProgramNo        ç¨‹åºåˆ‡æ¢
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param ProgramNo:                ç¨‹åºç¼–号(0到7)
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_SetProgramNo(IN int DeviceID, IN int ProgramNo);
    // Program Check
    ///
    /// \brief SGIF_GetProgramNo        ç¨‹åºç¡®è®¤
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param ProgramNo:                ç¨‹åºç¼–号(0到7)
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_GetProgramNo(IN int DeviceID, OUT int * ProgramNo);
    // Starting the Data Storage
    ///
    /// \brief SGIF_DataStorageStart    æ•°æ®å­˜å‚¨å¼€å§‹
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_DataStorageStart(IN int DeviceID);
    // Stopping the Data Storage
    ///
    /// \brief SGIF_DataStorageStop        æ•°æ®å­˜å‚¨åœæ­¢
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_DataStorageStop(IN int DeviceID);
    // Outputting the Data Storage
    ///
    /// \brief SGIF_DataStorageGetData    æ•°æ®å­˜å‚¨æ•°æ®è¾“出
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param OutNo                    è¾“出OUT编号
    /// \param NumOfBuffer                ç¼“冲区大小(最多可接受多少个数据)
    /// \param OutBuffer                æ•°æ®æ•°ç»„
    /// \param NumReceived                å®žé™…接收的数据个数
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_DataStorageGetData(IN int DeviceID, IN int OutNo, IN int NumOfBuffer, OUT float * OutBuffer, OUT int *NumReceived);
    // Initializing the Data Storage
    ///
    /// \brief SGIF_DataStorageInit        æ•°æ®å­˜å‚¨åˆå§‹åŒ–
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_DataStorageInit(IN int DeviceID);
    // Data Storage Accumulation Status Output
    ///
    /// \brief SGIF_DataStorageGetStatus    æ•°æ®å­˜å‚¨çŠ¶æ€è¾“å‡º
    /// \param DeviceID                        è®¾å¤‡ID号,范围为0-63.
    /// \param lsStorage                    å­˜å‚¨çŠ¶æ€
    /// \param NumStorageData                å„输出口存储数量数组
    /// \return
    ///     >0:                                å¤±è´¥.
    ///     =0:                                æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_DataStorageGetStatus(IN int DeviceID, OUT BOOL * lsStorage, OUT int  * NumStorageData);
    ///////////////////////////////////////////////
    // Setting change commands
    //
    // Set Tolerance
    ///
    /// \brief SGIF_SetTolerance            å…¬å·®è®¾å®š
    /// \param DeviceID                        è®¾å¤‡ID号,范围为0-63.
    /// \param OutNo                        è¾“出OUT编号
    /// \param UpperLimit                    ä¸Šé™ï¼Œä¼ å…¥ä¸ºæœ‰æ•ˆæ•°å­—(去掉小数点后的整形)
    /// \param LowerLimit                    ä¸‹é™ï¼Œä¼ å…¥ä¸ºæœ‰æ•ˆæ•°å­—(去掉小数点后的整形)
    /// \param Hystersys                    æ»žåŽï¼Œä¼ å…¥ä¸ºæœ‰æ•ˆæ•°å­—(去掉小数点后的整形)
    /// \return
    ///     >0:                                å¤±è´¥.
    ///     =0:                                æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_SetTolerance(IN int DeviceID, IN int OutNo, IN int UpperLimit, IN int LowerLimit, IN int Hystersys);
    // Set ABLE
    ///
    /// \brief SGIF_SetAbleMode                Able模式设定
    /// \param DeviceID                        è®¾å¤‡ID号,范围为0-63.
    /// \param HeadNo                        ä¼ æ„Ÿå¤´ç¼–号
    /// \param AbleMode                        Ä£Ê½
    /// \return
    ///     >0:                                å¤±è´¥.
    ///     =0:                                æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_SetAbleMode(IN int DeviceID, IN int HeadNo, IN SGIF_ABLEMODE AbleMode);
    // Set ABLE Control Range
    ///
    /// \brief SGIF_SetAbleMinMax            Able控制范围设定
    /// \param DeviceID                        è®¾å¤‡ID号,范围为0-63.
    /// \param HeadNo                        ä¼ æ„Ÿå¤´ç¼–号
    /// \param Min                            ä¸‹é™
    /// \param Max                            ä¸Šé™
    /// \return
    ///     >0:                                å¤±è´¥.
    ///     =0:                                æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_SetAbleMinMax(IN int DeviceID, IN int HeadNo, IN int Min, IN int Max);
    // Set Detection mode
    ///
    /// \brief SGIF_SetMeasureMode            æµ‹é‡æ¨¡å¼è®¾å®š
    /// \param DeviceID                        è®¾å¤‡ID号,范围为0-63.
    /// \param HeadNo                        ä¼ æ„Ÿå¤´ç¼–号
    /// \MeasureMode                        æµ‹é‡æ¨¡å¼
    /// \return
    ///     >0:                                å¤±è´¥.
    ///     =0:                                æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_SetMeasureMode(IN int DeviceID, IN int HeadNo, IN SGIF_MEASUREMODE MeasureMode);
    // Set Base point
    ///
    /// \brief SGIF_SetBasicPoint            åŸºå‡†ç‚¹è®¾å®š
    /// \param DeviceID                        è®¾å¤‡ID号,范围为0-63.
    /// \param HeadNo                        ä¼ æ„Ÿå¤´ç¼–号
    /// \param BasicPoint                    åŸºå‡†ç‚¹
    /// \return
    ///     >0:                                å¤±è´¥.
    ///     =0:                                æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_SetBasicPoint(IN int DeviceID, IN int HeadNo, IN SGIF_BASICPOINT BasicPoint);
    // Set Number of Times of Alarm Processing
    ///
    /// \brief SGIF_SetNumAlarm                è­¦æŠ¥æ•°é‡è®¾å®š
    /// \param DeviceID                        è®¾å¤‡ID号,范围为0-63.
    /// \param HeadNo                        ä¼ æ„Ÿå¤´ç¼–号
    /// \param AlarmNum                        è­¦æŠ¥æ•°é‡
    /// \return
    ///     >0:                                å¤±è´¥.
    ///     =0:                                æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_SetNumAlarm(IN int DeviceID, IN int HeadNo, IN int AlarmNum);
    // Set Number of Times of Alarm Recovery
    ///
    /// \brief SGIF_SetNumRecovery            æ¢å¤æ•°é‡è®¾å®š
    /// \param DeviceID                        è®¾å¤‡ID号,范围为0-63.
    /// \param HeadNo                        ä¼ æ„Ÿå¤´ç¼–号
    /// \param RecoveryNum                    æ¢å¤æ¬¡æ•°
    /// \return
    ///     >0:                                å¤±è´¥.
    ///     =0:                                æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_SetNumRecovery(IN int DeviceID, IN int HeadNo, IN int RecoveryNum);
    // Set Alarm Level
    ///
    /// \brief SGIF_SetAlarmLevel            è­¦æŠ¥çº§åˆ«è®¾å®š
    /// \param DeviceID                        è®¾å¤‡ID号,范围为0-63.
    /// \param HeadNo                        ä¼ æ„Ÿå¤´ç¼–号
    /// \param AlarmLevel                    è­¦æŠ¥çº§åˆ«
    /// \return
    ///     >0:                                å¤±è´¥.
    ///     =0:                                æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_SetAlarmLevel(IN int DeviceID, IN int HeadNo, IN int AlarmLevel);
    // Starting the ABLE Calibration
    ///
    /// \brief SGIF_AbleStart                Able校准开始
    /// \param DeviceID                        è®¾å¤‡ID号,范围为0-63.
    /// \param HeadNo                        ä¼ æ„Ÿå¤´ç¼–号
    /// \return
    ///     >0:                                å¤±è´¥.
    ///     =0:                                æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_AbleStart(IN int DeviceID, IN int HeadNo);
    // Finishing the ABLE Calibration
    ///
    /// \brief SGIF_AbleStop                Able校准完成
    /// \param DeviceID                        è®¾å¤‡ID号,范围为0-63.
    /// \return
    ///     >0:                                å¤±è´¥.
    ///     =0:                                æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_AbleStop(IN int DeviceID);
    // Stopping the ABLE Calibration
    ///
    /// \brief SGIF_AbleCancel                AbleУ׼ֹͣ
    /// \param DeviceID                        è®¾å¤‡ID号,范围为0-63.
    /// \return
    ///     >0:                                å¤±è´¥.
    ///     =0:                                æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_AbleCancel(IN int DeviceID);
    // Set Mounting Mode
    ///
    /// \brief SGIF_SetReflectionMode        å®‰è£…模式设定
    /// \param DeviceID                        è®¾å¤‡ID号,范围为0-63.
    /// \param HeadNo                        ä¼ æ„Ÿå¤´ç¼–号
    /// \param ReflectionMode                åå°„模式
    /// \return
    ///     >0:                                å¤±è´¥.
    ///     =0:                                æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_SetReflectionMode(IN int DeviceID, IN int HeadNo, IN SGIF_REFLECTIONMODE ReflectionMode);
    // Set Mask
    ///
    /// \brief SGIF_SetMask                    å±è”½è®¾å®š
    /// \param DeviceID                        è®¾å¤‡ID号,范围为0-63.
    /// \param HeadNo                        ä¼ æ„Ÿå¤´ç¼–号
    /// \param OnOff                        å¼€å…³
    /// \param HeadNo                        ç‚¹ä½1
    /// \param HeadNo                        ç‚¹ä½2
    /// \return
    ///     >0:                                å¤±è´¥.
    ///     =0:                                æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_SetMask(IN int DeviceID, IN int HeadNo, IN BOOL OnOff, IN int Pos1, IN int Pos2);
    // Set Median
    ///
    /// \brief SGIF_SetMedian                ä¸­ä½æ•°è®¾å®š
    /// \param DeviceID                        è®¾å¤‡ID号,范围为0-63.
    /// \param HeadNo                        ä¼ æ„Ÿå¤´ç¼–号
    /// \param Median                        ä¸­ä½æ•°
    /// \return
    ///     >0:                                å¤±è´¥.
    ///     =0:                                æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_SetMedian(IN int DeviceID, IN int HeadNo, IN SGIF_MEDIAN Median);
    // Set LASER CTRL group
    ///
    /// \brief SGIF_SetLaserCtrlGroup        Laser Ctrl组设定
    /// \param DeviceID                        è®¾å¤‡ID号,范围为0-63.
    /// \param HeadNo                        ä¼ æ„Ÿå¤´ç¼–号
    /// \param LaserCtrlGroup                Laser Ctrl组
    /// \return
    ///     >0:                                å¤±è´¥.
    ///     =0:                                æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_SetLaserCtrlGroup(IN int DeviceID, IN int HeadNo, IN SGIF_LASER_CTRL_GROUP LaserCtrlGroup);
    // Set Mutual interference prevention group
    ///
    /// \brief SGIF_SetMutualInterferencePreventionGroup        é˜²æ­¢äº’相干扰组设定
    /// \param DeviceID                                            è®¾å¤‡ID号,范围为0-63.
    /// \param HeadNo                                            ä¼ æ„Ÿå¤´ç¼–号
    /// \param Group                                            ç»„
    /// \return
    ///     >0:                                                    å¤±è´¥.
    ///     =0:                                                    æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_SetMutualInterferencePreventionGroup(IN int DeviceID, IN int HeadNo, IN SGIF_MUTUAL_INTERFERENCE_PREVENTION_GROUP Group);
    // Set Calculation method
    ///
    /// \brief SGIF_SetCalcMethod        è®¡ç®—方式设定
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param OutNo                    è¾“出OUT编号
    /// \param CalcMethod                è®¡ç®—方法
    /// \param HeadOutNo                ä¼ æ„Ÿå¤´è¾“出编号
    /// \return
    ///     >0:                                                    å¤±è´¥.
    ///     =0:                                                    æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_SetCalcMethod(IN int DeviceID, IN int OutNo, IN SGIF_CALCMETHOD CalcMethod, IN int HeadOutNo);
    // Set Surface to be measured
    ///
    /// \brief SGIF_SetCalcTarget        æµ‹é‡ç›®æ ‡è®¾å®š
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param OutNo                    è¾“出OUT编号
    /// \param CalcTarget                è®¡ç®—标签
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_SetCalcTarget(IN int DeviceID, IN int OutNo, IN SGIF_CALCTARGET CalcTarget);
    // Set OUT to be calculated (ADD, SUB)
    ///
    /// \brief SGIF_SetOutAddSub        å¾…计算的OUT(Add,Sub)设定
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param OutNo                    è¾“出OUT编号
    /// \param AddSub1                    å¾…计算的OUT
    /// \param AddSub2                    å¾…计算的OUT
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_SetOutAddSub(IN int DeviceID, IN int OutNo, IN int AddSub1, IN int AddSub2);
    // Set OUT to be calculated (AVE, MAX, MIN, P-P)
    ///
    /// \brief SGIF_SetOutOperation        å¾…计算的OUT(Ave,Max,Min,P-P)设定
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param OutNo                    è¾“出OUT编号
    /// \param TargetOut                å¤šä¸ªOUT组合
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_SetOutOperation(IN int DeviceID, IN int OutNo, IN SGIF_OUTNO TargetOut);
    // Set Scaling
    ///
    /// \brief SGIF_SetScaling            ç¼©æ”¾è®¾å®š
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param OutNo                    è¾“出OUT编号
    /// \param InputValue1                ç‚¹1的测量值(输入值),传有效数字(去掉小数点后的整形)
    /// \param OutputValue1                ç‚¹1的显示值(输出值),传有效数字(去掉小数点后的整形)
    /// \param InputValue2                ç‚¹2的测量值(输入值),传有效数字(去掉小数点后的整形)
    /// \param OutputValue2                ç‚¹2的显示值(输出值),传有效数字(去掉小数点后的整形)
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_SetScaling(IN int DeviceID, IN int OutNo, IN int InputValue1, IN int OutputValue1, IN int InputValue2, IN int OutputValue2);
    // Set Filter Mode
    ///
    /// \brief SGIF_SetFilter            æ»¤æ³¢å™¨è®¾å®š
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param OutNo                    è¾“出OUT编号
    /// \param FilterMode                æ»¤æ³¢æ¨¡å¼
    /// \param FilterPara                æ»¤æ³¢å‚æ•°
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_SetFilter(IN int DeviceID, IN int OutNo, IN SGIF_FILTERMODE FilterMode, IN SGIF_FILTERPARA FilterPara);
    // Set Trigger Mode
    ///
    /// \brief SGIF_SetTriggerMode        è§¦å‘模式设定
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param OutNo                    è¾“出OUT编号
    /// \param TriggerMode                è§¦å‘模式
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_SetTriggerMode(IN int DeviceID, IN int OutNo, IN SGIF_TRIGGERMODE TriggerMode);
    // Set Offset
    ///
    /// \brief SGIF_SetOffset            åç§»è®¾å®š
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param OutNo                    è¾“出OUT编号
    /// \param Offset                    åç§»é‡
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_SetOffset(IN int DeviceID, IN int OutNo, IN int Offset);
    // Set Calculation Mode
    ///
    /// \brief SGIF_SetCalcMode            æ£€æµ‹æ¨¡å¼ï¼ˆæµ‹é‡æ¨¡å¼ï¼‰è®¾å®š
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param OutNo                    è¾“出OUT编号
    /// \param CalcMode                    æ£€æµ‹æ¨¡å¼ç¼–号
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_SetCalcMode(IN int DeviceID, IN int OutNo, IN SGIF_CALCMODE CalcMode);
    // Set Minimum Display Unit
    ///
    /// \brief SGIF_SetDisplayUnit        è®¾å®šæ˜¾ç¤ºå•位设定
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param OutNo                    è¾“出OUT编号
    /// \param DisplayUnit                æ˜¾ç¤ºå•位
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_SetDisplayUnit(IN int DeviceID, IN int OutNo, IN SGIF_DISPLAYUNIT DisplayUnit);
    // Set Synchronization
    ///
    /// \brief SGIF_SetSynchronization        åŒæ­¥è®¾å®š
    /// \param DeviceID                        è®¾å¤‡ID号,范围为0-63.
    /// \param OutNo                        è¾“出OUT编号
    /// \param OnOff                        å¼€å…³
    /// \return
    ///     >0:                                å¤±è´¥.
    ///     =0:                                æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_SetSynchronization(IN int DeviceID, IN int OutNo, IN BOOL OnOff);
    // Set Storage (OUT No. specification)
    ///
    /// \brief SGIF_SetStorageTarget        å­˜å‚¨ï¼ˆOUT编号规格)设定
    /// \param DeviceID                        è®¾å¤‡ID号,范围为0-63.
    /// \param OutNo                        è¾“出OUT编号
    /// \param OnOff                        å¼€å…³
    /// \return
    ///     >0:                                å¤±è´¥.
    ///     =0:                                æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_SetStorageTarget(IN int DeviceID, IN int OutNo, IN BOOL OnOff);
    // Set Sampling Rate
    ///
    /// \brief SGIF_SetSamplingCycle        é‡‡æ ·å‘¨æœŸè®¾å®š
    /// \param DeviceID                        è®¾å¤‡ID号,范围为0-63.
    /// \param SamplingCycle                é‡‡æ ·å‘¨æœŸ
    /// \return
    ///     >0:                                å¤±è´¥.
    ///     =0:                                æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_SetSamplingCycle(IN int DeviceID, IN SGIF_SAMPLINGCYCLE SamplingCycle);
    // Set Mutual Interference Prevention
    ///
    /// \brief SGIF_SetMutualInterferencePrevention        é˜²æ­¢äº’相干扰组设定
    /// \param DeviceID                                    è®¾å¤‡ID号,范围为0-63.
    /// \param OnOff                                    ç»„设定
    /// \return
    ///     >0:                                            å¤±è´¥.
    ///     =0:                                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_SetMutualInterferencePrevention(IN int DeviceID, IN SGIF_MUTUAL_INTERFERENCE_PREVENTION OnOff);
    // Set Strobe Time
    ///
    /// \brief SGIF_SetStrobeTime            é€‰é€šæ—¶é—´è®¾å®š
    /// \param DeviceID                        è®¾å¤‡ID号,范围为0-63.
    /// \param StrobeTime                    é€‰é€šæ—¶é—´
    /// \return
    ///     >0:                                å¤±è´¥.
    ///     =0:                                æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_SetStrobeTime(IN int DeviceID, IN SGIF_STOROBETIME StrobeTime);
    // Set Data Storage
    ///
    /// \brief SGIF_SetDataStorage            æ•°æ®å­˜å‚¨è®¾å®š
    /// \param DeviceID                        è®¾å¤‡ID号,范围为0-63.
    /// \param NumStorage                    å¾…存储数据的编号
    /// \param StorageCycle                    å­˜å‚¨å‘¨æœŸ
    /// \return
    ///     >0:                                å¤±è´¥.
    ///     =0:                                æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_SetDataStorage(IN int DeviceID, IN int NumStorage, IN SGIF_STORAGECYCLE StorageCycle);
    // EncoderSetting
    ///
    /// \brief SGIF_SetRunningMode            è¿è¡Œæ¨¡å¼è®¾ç½®(不支持SCI设备)
    /// \param DeviceID                        è®¾å¤‡ID号,范围为0-63.
    /// \param runningmode                    è¿è¡Œæ¨¡å¼ 0:OFF/1:定时/2:触发
    /// \param CatchDirection               æ£€æµ‹æ–¹å‘ 0:正负计时/1:正计时/2:负计时
    /// \return
    ///     >0:                                å¤±è´¥.
    ///     =0:                                æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_SetRunningMode(IN int DeviceID, IN SGIF_EmRunningMode Runningmode, IN SGIF_EmDirection CatchDirection);
    // EncoderInputSetting
    ///
    /// \brief SGIF_SetEncoderMode            ç¼–码器输入模式设置(不支持SCI设备)
    /// \param DeviceID                        è®¾å¤‡ID号,范围为0-63.
    /// \param Inputmode                    è¿è¡Œæ¨¡å¼ 0:1相1递增/1:2相1递增/2:2相2递增,3:2相4递增
    /// \param MinInputTime                    æœ€å°è¾“入时间
    /// \param TrigInterval                    è§¦å‘é—´éš”
    /// \return
    ///     >0:                                å¤±è´¥.
    ///     =0:                                æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_SetEncoderMode(IN int DeviceID, IN SGIF_EmEncoderInput Inputmode,IN SGIF_EmInputTime InputTime,IN int TrigInterval);
    // SGIF_SetFormula
    ///
    /// \brief SGIF_SetFormula                è®¾ç½®é…æ–¹
    /// \param DeviceID                        è®¾å¤‡ID号,范围为0-63.
    /// \param filePath                        é…æ–¹è·¯å¾„
    /// \return
    ///     >0:                                å¤±è´¥.
    ///     =0:                                æˆåŠŸ.
    ///  derive
    EXP RC WINAPI SGIF_SetFormula(IN int DeviceID, IN char* filePath );
    // SGIF_SetFormula
    ///
    /// \brief SGIF_SetFormula                è®¾ç½®é…æ–¹
    /// \param DeviceID                        è®¾å¤‡ID号,范围为0-63.
    /// \param filePath                        é…æ–¹è·¯å¾„
    /// \return
    ///     >0:                                å¤±è´¥.
    ///     =0:                                æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_DeriveFormula(IN int DeviceID, IN char* filePath);
    ///////////////////////////////////////////////
    // Setting confirmation commands
    //
    // Get Tolerance
    ///
    /// \brief SGIF_GetTolerance            å…¬å·®è®¾å®šèŽ·å–
    /// \param DeviceID                        è®¾å¤‡ID号,范围为0-63.
    /// \param OutNo                        è¾“出OUT编号
    /// \param UpperLimit                    ä¸Šé™ï¼Œä¼ å‡ºä¸ºæœ‰æ•ˆæ•°å­—(去掉小数点后的整形)
    /// \param LowerLimit                    ä¸‹é™ï¼Œä¼ å‡ºä¸ºæœ‰æ•ˆæ•°å­—(去掉小数点后的整形)
    /// \param Hysteresis                    æ»žåŽï¼Œä¼ å‡ºä¸ºæœ‰æ•ˆæ•°å­—(去掉小数点后的整形)
    /// \return
    ///     >0:                                å¤±è´¥.
    ///     =0:                                æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_GetTolerance(IN int DeviceID, IN int OutNo, OUT int * UpperLimit, OUT int * LowerLimit, OUT int * Hysteresis);
    // Get ABLE
    ///
    /// \brief SGIF_GetAbleMode                Able设定获取
    /// \param DeviceID                        è®¾å¤‡ID号,范围为0-63.
    /// \param HeadNo                        ä¼ æ„Ÿå¤´ç¼–号
    /// \param AbleMode                        Ableģʽ
    /// \return
    ///     >0:                                å¤±è´¥.
    ///     =0:                                æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_GetAbleMode(IN int DeviceID, IN int HeadNo, OUT SGIF_ABLEMODE * AbleMode);
    // Get ABLE Control Range
    ///
    /// \brief SGIF_GetAbleMinMax            Able控制范围获取
    /// \param DeviceID                        è®¾å¤‡ID号,范围为0-63.
    /// \param HeadNo                        ä¼ æ„Ÿå¤´ç¼–号
    /// \param Min                            æœ€å°å€¼
    /// \param Max                            æœ€å¤§å€¼
    /// \return
    ///     >0:                                å¤±è´¥.
    ///     =0:                                æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_GetAbleMinMax(IN int DeviceID, IN int HeadNo, OUT int * Min, OUT int * Max);
    // Get Detection mode
    ///
    /// \brief SGIF_GetMeasureMode            æµ‹é‡æ¨¡å¼èŽ·å–
    /// \param DeviceID                        è®¾å¤‡ID号,范围为0-63.
    /// \param HeadNo                        ä¼ æ„Ÿå¤´ç¼–号
    /// \param MeasureMode                    æµ‹é‡æ¨¡å¼
    /// \return
    ///     >0:                                å¤±è´¥.
    ///     =0:                                æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_GetMeasureMode(IN int DeviceID, IN int HeadNo, OUT SGIF_MEASUREMODE * MeasureMode);
    // Get Base point
    ///
    /// \brief SGIF_GetBasicPoint            åŸºå‡†ç‚¹èŽ·å–
    /// \param DeviceID                        è®¾å¤‡ID号,范围为0-63.
    /// \param HeadNo                        ä¼ æ„Ÿå¤´ç¼–号
    /// \param BasicPoint                    åŸºå‡†ç‚¹
    /// \return
    ///     >0:                                å¤±è´¥.
    ///     =0:                                æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_GetBasicPoint(IN int DeviceID, IN int HeadNo, OUT SGIF_BASICPOINT * BasicPoint);
    // Get Number of Times of Alarm Processing
    ///
    /// \brief SGIF_GetNumAlarm                è­¦æŠ¥å¤„理次数获取
    /// \param DeviceID                        è®¾å¤‡ID号,范围为0-63.
    /// \param HeadNo                        ä¼ æ„Ÿå¤´ç¼–号
    /// \param AlarmNum                        è­¦æŠ¥æ¬¡æ•°
    /// \return
    ///     >0:                                å¤±è´¥.
    ///     =0:                                æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_GetNumAlarm(IN int DeviceID, IN int HeadNo, OUT int * AlarmNum);
    // Get Number of Times of Alarm Recovery
    ///
    /// \brief SGIF_GetNumRecovery            è­¦æŠ¥æ¢å¤æ¬¡æ•°èŽ·å–
    /// \param DeviceID                        è®¾å¤‡ID号,范围为0-63.
    /// \param HeadNo                        ä¼ æ„Ÿå¤´ç¼–号
    /// \param RecoveryNum                    æ¢å¤æ¬¡æ•°
    /// \return
    ///     >0:                                å¤±è´¥.
    ///     =0:                                æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_GetNumRecovery(IN int DeviceID, IN int HeadNo, OUT int * RecoveryNum);
    // Get Alarm Level
    ///
    /// \brief SGIF_GetAlarmLevel            è­¦æŠ¥çº§åˆ«èŽ·å–
    /// \param DeviceID                        è®¾å¤‡ID号,范围为0-63.
    /// \param HeadNo                        ä¼ æ„Ÿå¤´ç¼–号
    /// \param AlarmLevel                    è­¦æŠ¥çº§åˆ«
    /// \return
    ///     >0:                                å¤±è´¥.
    ///     =0:                                æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_GetAlarmLevel(IN int DeviceID, IN int HeadNo, OUT int * AlarmLevel);
    // Get Mounting Mode
    ///
    /// \brief SGIF_GetReflectionMode        å®‰è£…模式获取
    /// \param DeviceID                        è®¾å¤‡ID号,范围为0-63.
    /// \param HeadNo                        ä¼ æ„Ÿå¤´ç¼–号
    /// \param ReflectionMode                åå°„模式
    /// \return
    ///     >0:                                å¤±è´¥.
    ///     =0:                                æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_GetReflectionMode(IN int DeviceID, IN int HeadNo, OUT SGIF_REFLECTIONMODE * ReflectionMode);
    // Get Mask
    ///
    /// \brief SGIF_GetMask                    å±è”½è®¾å®šèŽ·å–
    /// \param DeviceID                        è®¾å¤‡ID号,范围为0-63.
    /// \param HeadNo                        ä¼ æ„Ÿå¤´ç¼–号
    /// \param OnOff                        å¼€å…³
    /// \param Pos1                            ä½ç½®1
    /// \param Pos2                            ä½ç½®2
    /// \return
    ///     >0:                                å¤±è´¥.
    ///     =0:                                æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_GetMask(IN int DeviceID, IN int HeadNo, OUT BOOL * OnOff, OUT int * Pos1, OUT int * Pos2);
    // Get Median
    ///
    /// \brief SGIF_GetMedian                ä¸­ä½æ•°èŽ·å–
    /// \param DeviceID                        è®¾å¤‡ID号,范围为0-63.
    /// \param HeadNo                        ä¼ æ„Ÿå¤´ç¼–号
    /// \param Median                        ä¸­ä½æ•°
    /// \return
    ///     >0:                                å¤±è´¥.
    ///     =0:                                æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_GetMedian(IN int DeviceID, IN int HeadNo, OUT SGIF_MEDIAN * Median);
    // Get LASER CTRL group
    ///
    /// \brief SGIF_GetLaserCtrlGroup        Laser Ctrl组获取
    /// \param DeviceID                        è®¾å¤‡ID号,范围为0-63.
    /// \param HeadNo                        ä¼ æ„Ÿå¤´ç¼–号
    /// \param LaserCtrlGroup                Laser Ctrl组
    /// \return
    ///     >0:                                å¤±è´¥.
    ///     =0:                                æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_GetLaserCtrlGroup(IN int DeviceID, IN int HeadNo, OUT SGIF_LASER_CTRL_GROUP * LaserCtrlGroup);
    // Get Mutual interference prevention group
    ///
    /// \brief SGIF_GetMutualInterferencePreventionGroup    é˜²æ­¢äº’相干扰组获取
    /// \param DeviceID                                        è®¾å¤‡ID号,范围为0-63.
    /// \param HeadNo                                        ä¼ æ„Ÿå¤´ç¼–号
    /// \param Group                                        ç»„
    /// \return
    ///     >0:                                                å¤±è´¥.
    ///     =0:                                                æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_GetMutualInterferencePreventionGroup(IN int DeviceID, IN int HeadNo, OUT SGIF_MUTUAL_INTERFERENCE_PREVENTION_GROUP * Group);
    // Get Calculation method
    ///
    /// \brief SGIF_GetCalcMethod        è®¡ç®—方式获取
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param OutNo                    è¾“出OUT编号
    /// \param CalcMethod                è®¡ç®—方法
    /// \param HeadOutNo                ä¼ æ„Ÿå¤´æˆ–OUT编号
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_GetCalcMethod(IN int DeviceID, IN int OutNo, OUT SGIF_CALCMETHOD * CalcMethod, OUT int * HeadOutNo);
    // Get Surface to be measured
    ///
    /// \brief SGIF_GetCalcTarget        æµ‹é‡ç›®æ ‡èŽ·å–
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param OutNo                    è¾“出OUT编号
    /// \param CalcTarget                è®¡ç®—标签
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_GetCalcTarget(IN int DeviceID, IN int OutNo, OUT SGIF_CALCTARGET * CalcTarget);
    // Get OUT to be calculated (ADD, SUB)
    ///
    /// \brief SGIF_GetOutAddSub        å¾…计算的OUT(Add,Sub)获取
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param OutNo                    è¾“出OUT编号
    /// \param AddSub1                    å¾…计算的OUT编号1
    /// \param AddSub2                    å¾…计算的OUT编号2
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_GetOutAddSub(IN int DeviceID, IN int OutNo, OUT int * AddSub1, OUT int * AddSub2);
    // Get OUT to be calculated (AVE, MAX, MIN, P-P)
    ///
    /// \brief SGIF_GetOutOperation        å¾…计算的OUT(Ave,Max,Min,P-P)获取
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param OutNo                    è¾“出OUT编号
    /// \param TargetOut                å¤šä¸ªOUT或HEAD组合
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_GetOutOperation(IN int DeviceID, IN int OutNo, OUT SGIF_OUTNO * TargetOut);
    // Get Scaling
    ///
    /// \brief SGIF_GetScaling            ç¼©æ”¾è®¾å®šèŽ·å–
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param OutNo                    è¾“出OUT编号
    /// \param InputValue1                ç‚¹1的测量值(输入值),传出为有效数字(去掉小数点后的整形)
    /// \param OutputValue1                ç‚¹1的显示值(输出值),传出为有效数字(去掉小数点后的整形)
    /// \param InputValue2                ç‚¹2的测量值(输入值),传出为有效数字(去掉小数点后的整形)
    /// \param OutputValue2                ç‚¹2的显示值(输出值),传出为有效数字(去掉小数点后的整形)
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_GetScaling(IN int DeviceID, IN int OutNo, OUT int * InputValue1, OUT int * OutputValue1, OUT int * InputValue2, OUT int * OutputValue2);
    // Get Filter Mode
    ///
    /// \brief SGIF_GetFilter            æ»¤æ³¢å™¨è®¾å®šèŽ·å–
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param OutNo                    è¾“出OUT编号
    /// \param FilterMode                æ»¤æ³¢å™¨æ¨¡å¼
    /// \param FilterPara                æ»¤æ³¢å‚æ•°
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_GetFilter(IN int DeviceID, IN int OutNo, OUT SGIF_FILTERMODE * FilterMode, OUT SGIF_FILTERPARA * FilterPara);
    // Get Trigger Mode
    ///
    /// \brief SGIF_GetTriggerMode        è§¦å‘模式获取
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param OutNo                    è¾“出OUT编号
    /// \param TriggerMode                è§¦å‘模式
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_GetTriggerMode(IN int DeviceID, IN int OutNo, OUT SGIF_TRIGGERMODE * TriggerMode);
    // Get Offset
    ///
    /// \brief SGIF_GetOffset            åç§»èŽ·å–
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param OutNo                    è¾“出OUT编号
    /// \param Offset                    åç§»é‡
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_GetOffset(IN int DeviceID, IN int OutNo, OUT int * Offset);
    // Get Calculation Mode
    ///
    /// \brief SGIF_GetCalcMode            æ£€æµ‹æ¨¡å¼ï¼ˆæµ‹é‡æ¨¡å¼ï¼‰èŽ·å–
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param OutNo                    è¾“出OUT编号
    /// \param CalcMode                    æµ‹é‡æ¨¡å¼
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_GetCalcMode(IN int DeviceID, IN int OutNo, OUT SGIF_CALCMODE * CalcMode);
    // Get Minimum Display Unit
    ///
    /// \brief SGIF_GetDisplayUnit        æ˜¾ç¤ºæœ€å°å•位获取
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param OutNo                    è¾“出OUT编号
    /// \param DisplayUnit                æ˜¾ç¤ºæœ€å°å•位
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_GetDisplayUnit(IN int DeviceID, IN int OutNo, OUT SGIF_DISPLAYUNIT * DisplayUnit);
    // Get Synchronization
    ///
    /// \brief SGIF_GetSynchronization        åŒæ­¥è®¾å®šèŽ·å–
    /// \param DeviceID                        è®¾å¤‡ID号,范围为0-63.
    /// \param OutNo                        è¾“出OUT编号
    /// \param OnOff                        å¼€å…³
    /// \return
    ///     >0:                                å¤±è´¥.
    ///     =0:                                æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_GetSynchronization(IN int DeviceID, IN int OutNo, OUT BOOL * OnOff);
    // Get Storage (OUT No. specification)
    ///
    /// \brief SGIF_GetStorageTarget        å­˜å‚¨ï¼ˆOUT编号设定)获取
    /// \param DeviceID                        è®¾å¤‡ID号,范围为0-63.
    /// \param OutNo                        è¾“出OUT编号
    /// \param OnOff                        å¼€å…³
    /// \return
    ///     >0:                                å¤±è´¥.
    ///     =0:                                æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_GetStorageTarget(IN int DeviceID, IN int OutNo, OUT BOOL * OnOff);
    // Get Sampling Rate
    ///
    /// \brief SGIF_GetSamplingCycle        é‡‡æ ·å‘¨æœŸèŽ·å–
    /// \param DeviceID                        è®¾å¤‡ID号,范围为0-63.
    /// \param SamplingCycle                é‡‡æ ·å‘¨æœŸ
    /// \return
    ///     >0:                                å¤±è´¥.
    ///     =0:                                æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_GetSamplingCycle(IN int DeviceID, OUT SGIF_SAMPLINGCYCLE * SamplingCycle);
    // Get Mutual Interference Prevention
    ///
    /// \brief SGIF_GetMutualInterferencePrevention        é˜²æ­¢äº’相干扰获取
    /// \param DeviceID                                    è®¾å¤‡ID号,范围为0-63.
    /// \param OnOff                                    å¼€å…³
    /// \return
    ///     >0:                                            å¤±è´¥.
    ///     =0:                                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_GetMutualInterferencePrevention(IN int DeviceID, OUT SGIF_MUTUAL_INTERFERENCE_PREVENTION * OnOff);
    // Get Strobe Time
    ///
    /// \brief SGIF_GetStrobeTime        é€‰é€šæ—¶é—´èŽ·å–
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param OutputFormat                è¾“出形式
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_GetStrobeTime(IN int DeviceID, OUT SGIF_STOROBETIME * StrobeTime);
    // Get Data Storage
    ///
    /// \brief SGIF_GetDataStorage        æ•°æ®å­˜å‚¨èŽ·å–
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param NumStorage                å¸¦å­˜å‚¨æ•°æ®ç¼–号
    /// \param StorageCycle                å­˜å‚¨å‘¨æœŸ
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_GetDataStorage(IN int DeviceID, OUT int * NumStorage, OUT SGIF_STORAGECYCLE * StorageCycle);
    // Get Active head count
    ///
    /// \brief SGIF_GetNumOfUsedHeads        ä¸»åЍOUT计数获取
    /// \param DeviceID                        è®¾å¤‡ID号,范围为0-63.
    /// \param NumOfUsedHeads                ä¸»åЍOUT/传感头计数
    /// \return
    ///     >0:                                å¤±è´¥.
    ///     =0:                                æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_GetNumOfUsedHeads(IN int DeviceID, OUT int * NumOfUsedHeads);
    // Get Active OUT count
    ///
    /// \brief SGIF_GetNumOfUsedOut            ä¸»åŠ¨ä¼ æ„Ÿå¤´è®¡æ•°èŽ·å–
    /// \param DeviceID                        è®¾å¤‡ID号,范围为0-63.
    /// \param NumOfUsedHeads                ä¸»åЍOUT/传感头计数
    /// \return
    ///     >0:                                å¤±è´¥.
    ///     =0:                                æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_GetNumOfUsedOut(IN int DeviceID, OUT int * NumOfUsedOut);
    // Get Active Running Time
    ///
    /// \brief SGIF_GetDeviceRuningTime        èŽ·å–ç›¸æœºè¿è¡Œæ—¶é•¿ï¼Œå•ä½s
    /// \param DeviceID                        è®¾å¤‡ID号,范围为0-63.
    /// \param HeadNo                        0:控制器; 1-4:传感头编号
    /// \param RuningTime                    è¿è¡Œæ—¶é—´
    /// \return
    ///     >0:                                å¤±è´¥.
    ///     =0:                                æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_GetDeviceRuningTime(IN int DeviceID, IN int HeadNo, OUT unsigned int * RuningTime);
    ///////////////////////////////////////////////
    // Other commands
    //
    // Opens the Ethernet device.
    ///
    /// \brief SGIF_OpenDeviceETHER            æ‰“开设备网络连接
    /// \param DeviceID                        è®¾å¤‡ID号,范围为0-63.
    /// \param OpenParam                    ç½‘络连接参数
    /// \return
    ///     >0:                                å¤±è´¥.
    ///     =0:                                æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_OpenDeviceETHER(IN int DeviceID, SGIF_OPENPARAM_ETHERNET * OpenParam,DWORD TIMEOUT=3);
    // Closes the currently open device.
    ///
    /// \brief SGIF_CloseDevice                å…³é—­è®¾å¤‡ç½‘络连接
    /// \param DeviceID                        è®¾å¤‡ID号,范围为0-63.
    /// \return
    ///     >0:                                å¤±è´¥.
    ///     =0:                                æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_CloseDevice(IN int DeviceID);
    ///////////////////////////////////////////////
    // Mode change commands
    //
    // Mode Switch
    ///
    /// \brief SGIF_SetMode                    æ¨¡å¼åˆ‡æ¢
    /// \param DeviceID                        è®¾å¤‡ID号,范围为0-63.
    /// \param Mode                            Ä£Ê½
    /// \return
    ///     >0:                                å¤±è´¥.
    ///     =0:                                æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_SetMode(IN int DeviceID, IN SGIF_MODE Mode);
    EXP RC WINAPI SGIF_Refresh(IN int DeviceID);
    //////////////////////////////////////////////一次回调相关///////////////////////////////////////
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param OutBuffer                æ•°æ®æ•°ç»„
    /// \param NumReceived                å®žé™…接收的数据个数
    ///
    typedef void(*SGIF_DataStorageOneTimeCallBack)(OUT int DeviceID);
    ///////////////////////////////////////////////
    /// \brief SGIF_SetOneDataStorage        æ³¨å†Œä¸€æ¬¡å›žè°ƒ
    /// \param DeviceID                        è®¾å¤‡ID号,范围为0-63.
    /// \param SGIF_BatchOneTimeCallBack    å›žè°ƒå‡½æ•°
    /// \return
    ///     >0:                                å¤±è´¥.
    ///     =0:                                æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_SetOneDataStorage(IN int DeviceID, IN SGIF_DataStorageOneTimeCallBack CallFunc);
    //////////////////////////////////////////////////////////////////////////////////////////////
    // Get encoder store value
    /// \brief SGIF_GetEncoderStoreValue编码器值存储数据输出(仅SCI设备支持)
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param OutNo                    ç¼–码器编号
    /// \param NumOfBuffer                ç¼“冲区大小(最多可接受多少个数据)
    /// \param OutBuffer                æ•°æ®æ•°ç»„
    /// \param NumReceived                å®žé™…接收的数据个数
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_GetEncoderStoreValue(IN int DeviceID, IN int OutNo, IN int NumOfBuffer, OUT int * OutBuffer, OUT int *NumReceived);
    // Get encoder value
    /// \brief SGIF_GetEncoderCurrentValue    è¯»å–编码器当前值(仅SCI设备支持)
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param OutNo                    ç¼–码器编号(1-3)
    /// \param OutBuffer                æ•°æ®æŒ‡é’ˆ
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_GetEncoderCurrentValue(IN int DeviceID, IN int OutNo, OUT int * OutBuffer);
    // encoder Reset
    /// \brief SGIF_EncoderReset        ç¼–码器值置零(仅SCI设备支持)
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param OutNo                    ç¼–码器编号(1-3)
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_EncoderReset(IN int DeviceID, IN int OutNo);
    // Set Encoder Number
    /// \brief SGIF_SetEncoderNumber    é€‰æ‹©ç¼–码器(仅SCI设备支持)
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param OutNo                    ç¼–码器编号(1-3)
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_SetEncoderNumber(IN int DeviceID, IN int OutNo);
    // Get encoder number
    /// \brief SGIF_GetEncoderNumber    è¯»å–设置的编码器编号(仅SCI设备支持)
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param OutBuffer                æ•°æ®æŒ‡é’ˆ
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_GetEncoderNumber(IN int DeviceID, OUT int * OutBuffer);
    //Set Encoder Parameters
    /// \brief SGIF_SetEncoderParameters设置编码器参数(仅SCI设备支持)
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param OutNo                    ç¼–码器编号(1-3)
    /// \param InputMode                è¾“入模式(0-3)
    /// \param InputTime                æœ€ä½Žè¾“入时间(100,200,500,1000,2000,5000,10000,20000)(ns)
    /// \param interval                    é—´éš”(1-10000)
    /// \param OperatingMode            è¿è¡Œæ¨¡å¼ï¼ˆ0-2)
    /// \param DetectionDirection        æ£€æµ‹æ–¹å‘(0-2)
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_SetEncoderParameters(IN int DeviceID, IN int OutNo, IN int InputMode, IN int InputTime, IN int interval, IN int OperatingMode, IN int DetectionDirection);
    //Get Encoder Parameters
    /// \brief SGIF_GetEncoderParameters读取编码器参数(仅SCI设备支持)
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param OutNo                    ç¼–码器编号(1-3)
    /// \param InputMode                è¾“入模式(0-3)
    /// \param InputTime                æœ€ä½Žè¾“入时间(100,200,500,1000,2000,5000,10000,20000)(ns)
    /// \param interval                    é—´éš”(1-10000)
    /// \param OperatingMode            è¿è¡Œæ¨¡å¼ï¼ˆ0-2)
    /// \param DetectionDirection        æ£€æµ‹æ–¹å‘(0-2)
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///4
    EXP RC WINAPI SGIF_GetEncoderParameters(IN int DeviceID, IN int OutNo, OUT int * InputMode, OUT int * InputTime, OUT int * interval, OUT int * OperatingMode, OUT int * DetectionDirection);
    //Set Analog Output
    /// \brief SGIF_SetAnalogOutput        è®¾ç½®æ¨¡æ‹Ÿé‡è¾“出(仅SCI设备支持)
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param OutNo                    æ¨¡æ‹Ÿé‡ç¼–号(1-3)
    /// \param OutputChannel            è¾“出通道(0-3)
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_SetAnalogOutput(IN int DeviceID, IN int OutNo, IN int OutputChannel);
    // Retrieve Analog Output Channel Number
    /// \brief SGIF_GetAnalogOutputChannel    èŽ·å–æ¨¡æ‹Ÿé‡è¾“å‡ºé€šé“ç¼–å·(仅SCI设备支持)
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param OutNo                    æ¨¡æ‹Ÿé‡ç¼–号(1-3)
    /// \param OutBuffer                æ•°æ®æŒ‡é’ˆ
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_GetAnalogOutputChannel(IN int DeviceID, IN int OutNo, OUT int * OutBuffer);
    //Set IO Digital Output
    /// \brief SGIF_SetIODigitalOutput    è®¾ç½®IO数字输出(仅SCI设备支持)
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param OutNo                    æ•°å­—输出编号(1-4)
    /// \param Level                    è¾“出位数(0:OFF,1:HI,2:GO,3:LO,4:STROBE)
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_SetIODigitalOutput(IN int DeviceID, IN int OutNo, IN int Level);
    // Retrieve IO Digital Output Channel Number
    /// \brief SGIF_GetIOOutputChannel    èŽ·å–IO数字量输出通道编号(仅SCI设备支持)
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param OutNo                    æ•°å­—输出编号(1-4)
    /// \param OutBuffer                æ•°æ®æŒ‡é’ˆ
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_GetIOOutputChannel(IN int DeviceID, IN int OutNo, OUT int * OutBuffer);
#ifdef __cplusplus
}
#endif
SourceCode/Bond/SGMeasurement/DLL/32bit/SGIFPJ.dll
Binary files differ
SourceCode/Bond/SGMeasurement/DLL/32bit/SGIFPJ.lib
Binary files differ
SourceCode/Bond/SGMeasurement/DLL/64bit/SGIF.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,1641 @@
#ifdef SGIF_EXPORTS
#define EXP __declspec(dllexport)
#else
#define EXP __declspec(dllimport)
#endif
#include "Winsock2.h"
#include "Ws2tcpip.h"
#include <stdlib.h>
#include <stdio.h>
#include <windows.h>
#pragma comment(lib, "WS2_32.lib")
// Return Code List
typedef enum {
    RC_OK = 0x0000,
    // The operation is completed successfully.
    ///////////////////////////////////////////////
    // Communication error from controller notification
    //
    RC_NAK_COMMAND = 0x1001,        // Command error
    RC_NAK_COMMAND_LENGTH,            // Command length error
    RC_NAK_TIMEOUT,                    // Timeout
    RC_NAK_CHECKSUM,                // Check sum error
    RC_NAK_INVALID_STATE,            // Status error
    RC_NAK_OTHER,                    // Other error
    RC_NAK_PARAMETER,                // Parameter error
    RC_NAK_OUT_STAGE,                // OUT calculation count limitation error
    RC_NAK_OUT_HEAD_NUM,            // No. of used head/OUT over error
    RC_NAK_PARAM_RANGE_DATA_STORED,    // OUT No which data reserved over acctive out count
    RC_NAK_OUT_INVALID_CALC,        // OUT which cannot be used for calculation was specified for calculation.
    RC_NAK_OUT_VOID,                // OUT which specified for calculation is not found.
    RC_NAK_INVALID_CYCLE,            // Unavailable sampling cycle
    RC_NAK_CTRL_ERROR,                // Main unit error
    RC_NAK_SRAM_ERROR,                // Setting value error
    ///////////////////////////////////////////////
    // Communication DLL error notification
    //
    RC_ERR_OPEN_DEVICE = 0x2000,// Opening the device failed.
    RC_ERR_NO_DEVICE,            // The device is not open.
    RC_ERR_SEND,                // Command sending error
    RC_ERR_RECEIVE,                // Response receiving error
    RC_ERR_TIMEOUT,                // Timeout
    RC_ERR_NODATA,                // No data
    RC_ERR_NOMEMORY,            // No free memory
    RC_ERR_DISCONNECT,            // Cable disconnection suspected
    RC_ERR_UNKNOWN,                // Undefined error
    RC_ERR_DEVID_OVER,            // over dev_id scale
    RC_ERR_NET_NO_CONN,            // no connected at the deviceID
    RC_ERR_IP_EXISTED,
    RC_ERR_SELECT,                // select of /socket error
    RC_ERR_NULL_PARAMETER,        // NULL point exception from parameter
    RC_ERR_DIY_FUNC,            // error due to dir function
    RC_ERR_OVER_PARAMENTER,        // paramenter over the limition
    RC_ERR_NOT_SUPPORT            // åŠŸèƒ½ä¸æ”¯æŒ
} RC;
//device Version
typedef enum {
    SG3035 = 0,
    SG3030 = 1,
    SG3085 = 2,
    SG3080 = 3,
    SG5025 = 4,
    SG5020 = 5,
    SG5055 = 6,
    SG5050 = 7,
    SG5085 = 8,
    SG5080 = 9,
    SG5155 = 10,
    SG5150 = 11,
    SC04025 = 12,
    SC03560 = 13,
    SGI500 = 14,
    SGI505 = 15,
    SGI400 = 16,
    SGI405 = 17,
    SGI150 = 18,
    SGI155 = 19,
    SGI080 = 20,
    SGI085 = 21,
    SGI050 = 22,
    SGI055 = 23,
    SGI030 = 24,
    SGI035 = 25,
    SGI020 = 26,
    SGI025 = 27,
    SG3155 = 28,
    SG3150 = 29,
    SC01045 = 30,
    SC10015 = 31,
    SC20011 = 32,
    SC01236 = 33,
    SCI04025 = 34,
    SCI03560 = 35,
    SCI01045 = 36,
    SCI10015 = 37,
    SCI20011 = 38,
    SCI01236 = 39,
}SGIF_DEVICE_TYPE;
// Measurement value structures
typedef enum {
    SGIF_FLOATRESULT_VALID,            // valid data
    SGIF_FLOATRESULT_RANGEOVER_P,    // over range at positive (+) side
    SGIF_FLOATRESULT_RANGEOVER_N,    // over range at negative (-) side
    SGIF_FLOATRESULT_WAITING,        // Wait for comparator result
    SGIF_FLOATRESULT_ALARM,            // alarm
    SGIF_FLOATRESULT_INVALID,        // Invalid (error, etc.)
} SGIF_FLOATRESULT;
// Set ABLE
typedef enum {
    SGIF_ABLEMODE_AUTO,                // AUTO
    SGIF_ABLEMODE_MANUAL,            // manual
} SGIF_ABLEMODE;
// Set Measurement Mode
typedef enum {
    SGIF_MEASUREMODE_NORMAL,                        // normal
    SGIF_MEASUREMODE_HALF_T,                        // translucent object
    SGIF_MEASUREMODE_TRAN_1,                        // transparent object
    SGIF_MEASUREMODE_TRAN_2,                        // transparent object 2
    SGIF_MEASUREMODE_MRS,                            // multireflective object
    SGIF_MEASUREMODE_OPAQUE = SGIF_MEASUREMODE_MRS,    // Semi opaque object
} SGIF_MEASUREMODE;
// Set Basic Point
typedef enum {
    SGIF_BASICPOINT_NEAR,            // NEAR
    SGIF_BASICPOINT_FAR,            // FAR
} SGIF_BASICPOINT;
// Set Mounting Mode
typedef enum {
    SGIF_REFLECTIONMODE_DIFFUSION,    // diffuse reflection
    SGIF_REFLECTIONMODE_MIRROR,        // specular reflection
} SGIF_REFLECTIONMODE;
// Set Median
typedef enum {
    SGIF_MEDIAN_OFF,                // OFF
    SGIF_MEDIAN_7,                    // 7 point
    SGIF_MEDIAN_15,                    // 15 point
    SGIF_MEDIAN_31,                    // 31 point
} SGIF_MEDIAN;
// Set LASER CTRL group.
typedef enum {
    SGIF_LASER_CTRL_GROUP_1,        // LASER CTRL 1
    SGIF_LASER_CTRL_GROUP_2,        // LASER CTRL 2
} SGIF_LASER_CTRL_GROUP;
// Set a range.
typedef enum {
    SGIF_RANGE_CENTER,                // CENTER
    SGIF_RANGE_FAR,                    // FAR
} SGIF_RANGE;
// Set Mutual Interference Prevention Group
typedef enum {
    SGIF_MUTUAL_INTERFERENCE_PREVENTION_GROUP_A,    // Group A
    SGIF_MUTUAL_INTERFERENCE_PREVENTION_GROUP_B,    // Group B
    SGIF_MUTUAL_INTERFERENCE_PREVENTION_GROUP_C,    // Group C
} SGIF_MUTUAL_INTERFERENCE_PREVENTION_GROUP;
// Set calculation method.
typedef enum {
    SGIF_CALCMETHOD_HEADA,                    // head A
    SGIF_CALCMETHOD_HEADB,                    // head B
    SGIF_CALCMETHOD_HEAD_HEADA_PLUS_HEADB,    // head A+head B
    SGIF_CALCMETHOD_HEAD_HEADA_MINUS_HEADB,    // head A-head B
    SGIF_CALCMETHOD_HEAD_HEADA_TRANSPARENT,    // head A transparent object
    SGIF_CALCMETHOD_HEAD_HEADB_TRANSPARENT,    // head B transparent object
    SGIF_CALCMETHOD_HEAD = 0,    // head
    SGIF_CALCMETHOD_OUT,        // OUT
    SGIF_CALCMETHOD_ADD,        // ADD
    SGIF_CALCMETHOD_SUB,        // SUB
    SGIF_CALCMETHOD_AVE,        // AVE
    SGIF_CALCMETHOD_MAX,        // MAX
    SGIF_CALCMETHOD_MIN,        // MIN
    SGIF_CALCMETHOD_PP,            // P-P
} SGIF_CALCMETHOD;
// Set Target Surface
typedef enum {
    SGIF_CALCTARGET_PEAK_1,        // peak 1
    SGIF_CALCTARGET_PEAK_2,        // peak 2
    SGIF_CALCTARGET_PEAK_3,        // peak 3
    SGIF_CALCTARGET_PEAK_4,        // peak 4
    SGIF_CALCTARGET_PEAK_1_2,    // peak 1-peak 2
    SGIF_CALCTARGET_PEAK_1_3,    // peak 1-peak 3
    SGIF_CALCTARGET_PEAK_1_4,    // peak 1-peak 4
    SGIF_CALCTARGET_PEAK_2_3,    // peak 2-peak 3
    SGIF_CALCTARGET_PEAK_2_4,    // peak 2-peak 4
    SGIF_CALCTARGET_PEAK_3_4,    // peak 3-peak 4
} SGIF_CALCTARGET;
// Set Filter Mode
typedef enum {
    SGIF_FILTERMODE_MOVING_AVERAGE,            // moving average
} SGIF_FILTERMODE;
// Specify the filter parameter. (The number of averaging for moving average, or the cutoff frequency for LPF/HPF.)
typedef enum {
    SGIF_FILTERPARA_AVE_1 = 0,        // 1 time
    SGIF_FILTERPARA_AVE_4,            // 4 times
    SGIF_FILTERPARA_AVE_16,            // 16 times
    SGIF_FILTERPARA_AVE_64,            // 64 times
    SGIF_FILTERPARA_AVE_256,        // 256 times
    SGIF_FILTERPARA_AVE_1024,        // 1024 times
    SGIF_FILTERPARA_AVE_4096,        // 4096 times
    SGIF_FILTERPARA_AVE_16384,        // 16384 times
    SGIF_FILTERPARA_AVE_65536,        // 65536 times
    SGIF_FILTERPARA_AVE_262144,        // 262144 times
}SGIF_FILTERPARA;
// Set Trigger Mode
typedef enum {
    SGIF_TRIGGERMODE_EXT1,        // external trigger 1
    SGIF_TRIGGERMODE_EXT2,        // external trigger 2
} SGIF_TRIGGERMODE;
// Set the Measurement Mode.
typedef enum {
    SGIF_CALCMODE_NORMAL,            // normal
    SGIF_CALCMODE_PEAKHOLD,            // peak hold
    SGIF_CALCMODE_BOTTOMHOLD,        // bottom hold
    SGIF_CALCMODE_PEAKTOPEAKHOLD,    // peak-to-peak hold
    SGIF_CALCMODE_SAMPLEHOLD,        // sample hold
} SGIF_CALCMODE;
// Set Minimum Display Unit
typedef enum {
    SGIF_DISPLAYUNIT_0000_01MM = 0,    // 0.01mm
    SGIF_DISPLAYUNIT_000_001MM,        // 0.001mm
    SGIF_DISPLAYUNIT_00_0001MM,        // 0.0001mm
    SGIF_DISPLAYUNIT_0_00001MM,        // 0.00001mm
    SGIF_DISPLAYUNIT_00000_1UM,        // 0.1um
    SGIF_DISPLAYUNIT_0000_01UM,        // 0.01um
    SGIF_DISPLAYUNIT_000_001UM,        // 0.001um
} SGIF_DISPLAYUNIT;
// Specify OUT
typedef enum {
    SGIF_OUTNO_01 = 0x0001,            // OUT01
    SGIF_OUTNO_02 = 0x0002,            // OUT02
    SGIF_OUTNO_03 = 0x0004,            // OUT03
    SGIF_OUTNO_04 = 0x0008,            // OUT04
    SGIF_OUTNO_ALL = 0x000F,        // All OUTs
} SGIF_OUTNO;
// Set Storage (Cycle)
typedef enum {
    SGIF_STORAGECYCLE_1,            // sampling rate x 1
    SGIF_STORAGECYCLE_2,            // sampling rate x 2
    SGIF_STORAGECYCLE_5,            // sampling rate x 5
    SGIF_STORAGECYCLE_10,            // sampling rate x 10
    SGIF_STORAGECYCLE_20,            // sampling rate x 20
    SGIF_STORAGECYCLE_50,            // sampling rate x 50
    SGIF_STORAGECYCLE_100,            // sampling rate x 100
    SGIF_STORAGECYCLE_200,            // sampling rate x 200
    SGIF_STORAGECYCLE_500,            // sampling rate x 500
    SGIF_STORAGECYCLE_1000,            // sampling rate x 1000
    SGIF_STORAGECYCLE_TIMING,        // Timing sync
} SGIF_STORAGECYCLE;
// Set Sampling Rate
typedef enum {
    //SG5000系列
    SGIF_5000_SAMPLINGCYCLE_590KHZ,     // 590kHz
    SGIF_5000_SAMPLINGCYCLE_400KHZ,        // 400kHz
    SGIF_5000_SAMPLINGCYCLE_200KHZ,        // 200kHz
    SGIF_5000_SAMPLINGCYCLE_88KHZ,        // 88kHz
    SGIF_5000_SAMPLINGCYCLE_50KHZ,        // 50kHz
    SGIF_5000_SAMPLINGCYCLE_20KHZ,        // 20kHz
    SGIF_5000_SAMPLINGCYCLE_10KHZ,        // 10kHz
    SGIF_5000_SAMPLINGCYCLE_5KHZ,        // 5kHz
    SGIF_5000_SAMPLINGCYCLE_2KHZ,        // 2kHz
    SGIF_5000_SAMPLINGCYCLE_1KHZ,        // 1kHz+
    //SG3000系列
    SGIF_3000_SAMPLINGCYCLE_88KHZ = 10,    // 88kHz
    SGIF_3000_SAMPLINGCYCLE_50KHZ,        // 50kHz
    SGIF_3000_SAMPLINGCYCLE_20KHZ,        // 20kHz
    SGIF_3000_SAMPLINGCYCLE_10KHZ,        // 10kHz
    SGIF_3000_SAMPLINGCYCLE_5KHZ,        // 5kHz
    //SGIF_3000_SAMPLINGCYCLE_2KHZ,        // 2kHz
    SGIF_3000_SAMPLINGCYCLE_1KHZ,        // 1kHz
    //SCI系列
    SCI_SAMPLINGCYCLE_33KHZ = 30,    // 33kHz
    SCI_SAMPLINGCYCLE_20KHZ,        // 20kHz
    SCI_SAMPLINGCYCLE_15KHZ,        // 15kHz
    SCI_SAMPLINGCYCLE_10KHZ,        // 10kHz
    SCI_SAMPLINGCYCLE_5KHZ,            // 5kHz
    SCI_SAMPLINGCYCLE_2KHZ,            // 2kHz
    SCI_SAMPLINGCYCLE_1KHZ,            // 1kHz
    SCI_SAMPLINGCYCLE_05KHZ,        // 0.5kHz
} SGIF_SAMPLINGCYCLE;
// Set Mutual interference prevention
typedef enum {
    SGIF_MUTUAL_INTERFERENCE_PREVENTION_OFF,    // OFF
    SGIF_MUTUAL_INTERFERENCE_PREVENTION_AB_ON,    // AB-ON
    SGIF_MUTUAL_INTERFERENCE_PREVENTION_ABC_ON,    // ABC-ON
} SGIF_MUTUAL_INTERFERENCE_PREVENTION;
// Set Strobe Time
typedef enum {
    SGIF_STOROBETIME_2MS,        // 2ms
    SGIF_STOROBETIME_5MS,        // 5ms
    SGIF_STOROBETIME_10MS,        // 10ms
    SGIF_STOROBETIME_20MS,        // 20ms
} SGIF_STOROBETIME;
// Mode Switch
typedef enum {
    SGIF_MODE_NORMAL,                // normal mode
    SGIF_MODE_COMMUNICATION,        // setting mode
} SGIF_MODE;
//Encoder ext
typedef enum {
    SGIF_EmRunningMode_cont,//off
    SGIF_EmRunningMode_time,
    SGIF_EmRunningMode_trig,
}SGIF_EmRunningMode;
typedef enum {
    SGIF_EmDirection_all,//+-
    SGIF_EmDirection_pos,
    SGIF_EmDirection_neg,
}SGIF_EmDirection;
typedef enum {
    SGIF_EmEncoderInput_1x1,
    SGIF_EmEncoderInput_2x1,
    SGIF_EmEncoderInput_2x2,
    SGIF_EmEncoderInput_2x4,
}SGIF_EmEncoderInput;
typedef enum {
    SGIF_EmInputTime_100 = 100,
    SGIF_EmInputTime_200 = 200,
    SGIF_EmInputTime_500 = 500,
    SGIF_EmInputTime_1000 = 1000,
    SGIF_EmInputTime_2000 = 2000,
    SGIF_EmInputTime_5000 = 5000,
    SGIF_EmInputTime_10000 = 10000,
    SGIF_EmInputTime_20000 = 20000,
}SGIF_EmInputTime;
// Measurement value
typedef struct {
    int                    OutNo;            // OUT No(1-4)
    SGIF_FLOATRESULT    FloatResult;    // valid or invalid data
    float                Value;            // Measurement value
} SGIF_FLOATVALUE_OUT;
typedef struct {
    SGIF_FLOATRESULT    FloatResult;    // valid or invalid data
    float                Value;            // Measurement value
} SGIF_FLOATVALUE;
// IP address
typedef struct {
    IN_ADDR                IPAddress;
} SGIF_OPENPARAM_ETHERNET;
//Mask Minimum Display Unit(0.01mm)
#define MASKUNIT 100
#ifdef __cplusplus
extern "C"
{
#endif
    EXP RC WINAPI SGIF_GetDeviceType(IN int DeviceID, OUT SGIF_DEVICE_TYPE* deviceType);
    // Measured control commands
    ///
    /// \brief SGIF_GetCameraSpotType    å…‰æ–‘类型(不支持SCI)
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param ControlType:                è¾“出0:小光斑,1:大光斑
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_GetCameraSpotType(IN int DeviceID, OUT int *EissionSpotType);
    ///////////////////////////////////////////////
    // Measurement control commands
    //
    // Measured value output (single)
    ///
    /// \brief SGIF_GetCalcDataSingle    æµ‹é‡å€¼è¾“出
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param OutNo:                    è¾“出OUT编号
    /// \param CalcData:                æµ‹é‡å€¼
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_GetCalcDataSingle(IN int DeviceID, IN int OutNo, OUT SGIF_FLOATVALUE_OUT * CalcData);
    // Measured value output (multiple)
    ///
    /// \brief SGIF_GetCalcDataMulti    å¤šä¸ªæµ‹é‡å€¼è¾“出
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param OutNo:                    è¾“出OUT编号组合
    /// \param CalcData:                æµ‹é‡å€¼æ•°ç»„
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_GetCalcDataMulti(IN int DeviceID, IN SGIF_OUTNO OutNo, OUT SGIF_FLOATVALUE_OUT * CalcData);
    // Measured value output (ALL)
    ///
    /// \brief SGIF_GetCalcDataALL        å…¨éƒ¨æµ‹é‡å€¼è¾“出
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param CalcData:                æµ‹é‡å€¼æ•°ç»„
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_GetCalcDataALL(IN int DeviceID, OUT SGIF_FLOATVALUE_OUT * CalcData);
    // Timing ON/OFF (single)
    ///
    /// \brief SGIF_SetTimingSingle        è®¡æ—¶ON/OFF(一个)
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param OutNo:                    è¾“出OUT编号
    /// \param OnOff:                    å¼€æˆ–å…³
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_SetTimingSingle(IN int DeviceID, IN int OutNo, IN BOOL OnOff);
    // Timing ON/OFF (multiple)
    ///
    /// \brief SGIF_SetTimingMulti        è®¡æ—¶ON/OFF(多个)
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param OutNo:                    è¾“出OUT编号组合
    /// \param OnOff:                    å¼€æˆ–å…³
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_SetTimingMulti(IN int DeviceID, IN SGIF_OUTNO OutNo, IN BOOL OnOff);
    // Timing ON/OFF (synchronous)
    ///
    /// \brief SGIF_SetTimingSync        è®¡æ—¶ON/OFF(同步)
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param OnOff:                    å¼€æˆ–å…³
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_SetTimingSync(IN int DeviceID, IN BOOL OnOff);
    // Auto-zero ON/OFF (single)
    ///
    /// \brief SGIF_SetZeroSingle        è‡ªåŠ¨å½’é›¶ï¼ˆä¸€ä¸ªï¼‰
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param OutNo:                    è¾“出OUT编号
    /// \param OnOff:                    å¼€æˆ–å…³
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_SetZeroSingle(IN int DeviceID, IN int OutNo, IN BOOL OnOff);
    // Auto-zero ON/OFF (multiple)
    ///
    /// \brief SGIF_SetZeroMulti        è‡ªåŠ¨å½’é›¶ï¼ˆå¤šä¸ªï¼‰
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param OutNo:                    è¾“出OUT编号组合
    /// \param OnOff:                    å¼€æˆ–å…³
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_SetZeroMulti(IN int DeviceID, IN SGIF_OUTNO OutNo, IN BOOL OnOff);
    // Auto-zero ON/OFF (synchronous)
    ///
    /// \brief SGIF_SetZeroSync            è‡ªåŠ¨å½’é›¶ï¼ˆåŒæ­¥ï¼‰
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param OnOff:                    å¼€æˆ–å…³
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_SetZeroSync(IN int DeviceID, IN BOOL OnOff);
    // Measured value reset (single)
    ///
    /// \brief SGIF_SetResetSingle        é‡ç½®ï¼ˆä¸€ä¸ªï¼‰
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param OutNo:                    è¾“出OUT编号
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_SetResetSingle(IN int DeviceID, IN int OutNo);
    // Measured value reset (multiple)
    ///
    /// \brief SGIF_SetResetMulti        é‡ç½®ï¼ˆå¤šä¸ªï¼‰
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param OutNo:                    è¾“出OUT编号组合
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_SetResetMulti(IN int DeviceID, IN SGIF_OUTNO OutNo);
    // Measured value reset (synchronous)
    ///
    /// \brief SGIF_SetResetSync        é‡ç½®ï¼ˆåŒæ­¥ï¼‰
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_SetResetSync(IN int DeviceID);
    // Program Change
    ///
    /// \brief SGIF_SetProgramNo        ç¨‹åºåˆ‡æ¢
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param ProgramNo:                ç¨‹åºç¼–号(0到7)
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_SetProgramNo(IN int DeviceID, IN int ProgramNo);
    // Program Check
    ///
    /// \brief SGIF_GetProgramNo        ç¨‹åºç¡®è®¤
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param ProgramNo:                ç¨‹åºç¼–号(0到7)
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_GetProgramNo(IN int DeviceID, OUT int * ProgramNo);
    // Starting the Data Storage
    ///
    /// \brief SGIF_DataStorageStart    æ•°æ®å­˜å‚¨å¼€å§‹
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_DataStorageStart(IN int DeviceID);
    // Stopping the Data Storage
    ///
    /// \brief SGIF_DataStorageStop        æ•°æ®å­˜å‚¨åœæ­¢
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_DataStorageStop(IN int DeviceID);
    // Outputting the Data Storage
    ///
    /// \brief SGIF_DataStorageGetData    æ•°æ®å­˜å‚¨æ•°æ®è¾“出
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param OutNo                    è¾“出OUT编号
    /// \param NumOfBuffer                ç¼“冲区大小(最多可接受多少个数据)
    /// \param OutBuffer                æ•°æ®æ•°ç»„
    /// \param NumReceived                å®žé™…接收的数据个数
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_DataStorageGetData(IN int DeviceID, IN int OutNo, IN int NumOfBuffer, OUT float * OutBuffer, OUT int *NumReceived);
    // Initializing the Data Storage
    ///
    /// \brief SGIF_DataStorageInit        æ•°æ®å­˜å‚¨åˆå§‹åŒ–
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_DataStorageInit(IN int DeviceID);
    // Data Storage Accumulation Status Output
    ///
    /// \brief SGIF_DataStorageGetStatus    æ•°æ®å­˜å‚¨çŠ¶æ€è¾“å‡º
    /// \param DeviceID                        è®¾å¤‡ID号,范围为0-63.
    /// \param lsStorage                    å­˜å‚¨çŠ¶æ€
    /// \param NumStorageData                å„输出口存储数量数组
    /// \return
    ///     >0:                                å¤±è´¥.
    ///     =0:                                æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_DataStorageGetStatus(IN int DeviceID, OUT BOOL * lsStorage, OUT int  * NumStorageData);
    ///////////////////////////////////////////////
    // Setting change commands
    //
    // Set Tolerance
    ///
    /// \brief SGIF_SetTolerance            å…¬å·®è®¾å®š
    /// \param DeviceID                        è®¾å¤‡ID号,范围为0-63.
    /// \param OutNo                        è¾“出OUT编号
    /// \param UpperLimit                    ä¸Šé™ï¼Œä¼ å…¥ä¸ºæœ‰æ•ˆæ•°å­—(去掉小数点后的整形)
    /// \param LowerLimit                    ä¸‹é™ï¼Œä¼ å…¥ä¸ºæœ‰æ•ˆæ•°å­—(去掉小数点后的整形)
    /// \param Hystersys                    æ»žåŽï¼Œä¼ å…¥ä¸ºæœ‰æ•ˆæ•°å­—(去掉小数点后的整形)
    /// \return
    ///     >0:                                å¤±è´¥.
    ///     =0:                                æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_SetTolerance(IN int DeviceID, IN int OutNo, IN int UpperLimit, IN int LowerLimit, IN int Hystersys);
    // Set ABLE
    ///
    /// \brief SGIF_SetAbleMode                Able模式设定
    /// \param DeviceID                        è®¾å¤‡ID号,范围为0-63.
    /// \param HeadNo                        ä¼ æ„Ÿå¤´ç¼–号
    /// \param AbleMode                        Ä£Ê½
    /// \return
    ///     >0:                                å¤±è´¥.
    ///     =0:                                æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_SetAbleMode(IN int DeviceID, IN int HeadNo, IN SGIF_ABLEMODE AbleMode);
    // Set ABLE Control Range
    ///
    /// \brief SGIF_SetAbleMinMax            Able控制范围设定
    /// \param DeviceID                        è®¾å¤‡ID号,范围为0-63.
    /// \param HeadNo                        ä¼ æ„Ÿå¤´ç¼–号
    /// \param Min                            ä¸‹é™
    /// \param Max                            ä¸Šé™
    /// \return
    ///     >0:                                å¤±è´¥.
    ///     =0:                                æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_SetAbleMinMax(IN int DeviceID, IN int HeadNo, IN int Min, IN int Max);
    // Set Detection mode
    ///
    /// \brief SGIF_SetMeasureMode            æµ‹é‡æ¨¡å¼è®¾å®š
    /// \param DeviceID                        è®¾å¤‡ID号,范围为0-63.
    /// \param HeadNo                        ä¼ æ„Ÿå¤´ç¼–号
    /// \MeasureMode                        æµ‹é‡æ¨¡å¼
    /// \return
    ///     >0:                                å¤±è´¥.
    ///     =0:                                æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_SetMeasureMode(IN int DeviceID, IN int HeadNo, IN SGIF_MEASUREMODE MeasureMode);
    // Set Base point
    ///
    /// \brief SGIF_SetBasicPoint            åŸºå‡†ç‚¹è®¾å®š
    /// \param DeviceID                        è®¾å¤‡ID号,范围为0-63.
    /// \param HeadNo                        ä¼ æ„Ÿå¤´ç¼–号
    /// \param BasicPoint                    åŸºå‡†ç‚¹
    /// \return
    ///     >0:                                å¤±è´¥.
    ///     =0:                                æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_SetBasicPoint(IN int DeviceID, IN int HeadNo, IN SGIF_BASICPOINT BasicPoint);
    // Set Number of Times of Alarm Processing
    ///
    /// \brief SGIF_SetNumAlarm                è­¦æŠ¥æ•°é‡è®¾å®š
    /// \param DeviceID                        è®¾å¤‡ID号,范围为0-63.
    /// \param HeadNo                        ä¼ æ„Ÿå¤´ç¼–号
    /// \param AlarmNum                        è­¦æŠ¥æ•°é‡
    /// \return
    ///     >0:                                å¤±è´¥.
    ///     =0:                                æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_SetNumAlarm(IN int DeviceID, IN int HeadNo, IN int AlarmNum);
    // Set Number of Times of Alarm Recovery
    ///
    /// \brief SGIF_SetNumRecovery            æ¢å¤æ•°é‡è®¾å®š
    /// \param DeviceID                        è®¾å¤‡ID号,范围为0-63.
    /// \param HeadNo                        ä¼ æ„Ÿå¤´ç¼–号
    /// \param RecoveryNum                    æ¢å¤æ¬¡æ•°
    /// \return
    ///     >0:                                å¤±è´¥.
    ///     =0:                                æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_SetNumRecovery(IN int DeviceID, IN int HeadNo, IN int RecoveryNum);
    // Set Alarm Level
    ///
    /// \brief SGIF_SetAlarmLevel            è­¦æŠ¥çº§åˆ«è®¾å®š
    /// \param DeviceID                        è®¾å¤‡ID号,范围为0-63.
    /// \param HeadNo                        ä¼ æ„Ÿå¤´ç¼–号
    /// \param AlarmLevel                    è­¦æŠ¥çº§åˆ«
    /// \return
    ///     >0:                                å¤±è´¥.
    ///     =0:                                æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_SetAlarmLevel(IN int DeviceID, IN int HeadNo, IN int AlarmLevel);
    // Starting the ABLE Calibration
    ///
    /// \brief SGIF_AbleStart                Able校准开始
    /// \param DeviceID                        è®¾å¤‡ID号,范围为0-63.
    /// \param HeadNo                        ä¼ æ„Ÿå¤´ç¼–号
    /// \return
    ///     >0:                                å¤±è´¥.
    ///     =0:                                æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_AbleStart(IN int DeviceID, IN int HeadNo);
    // Finishing the ABLE Calibration
    ///
    /// \brief SGIF_AbleStop                Able校准完成
    /// \param DeviceID                        è®¾å¤‡ID号,范围为0-63.
    /// \return
    ///     >0:                                å¤±è´¥.
    ///     =0:                                æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_AbleStop(IN int DeviceID);
    // Stopping the ABLE Calibration
    ///
    /// \brief SGIF_AbleCancel                AbleУ׼ֹͣ
    /// \param DeviceID                        è®¾å¤‡ID号,范围为0-63.
    /// \return
    ///     >0:                                å¤±è´¥.
    ///     =0:                                æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_AbleCancel(IN int DeviceID);
    // Set Mounting Mode
    ///
    /// \brief SGIF_SetReflectionMode        å®‰è£…模式设定
    /// \param DeviceID                        è®¾å¤‡ID号,范围为0-63.
    /// \param HeadNo                        ä¼ æ„Ÿå¤´ç¼–号
    /// \param ReflectionMode                åå°„模式
    /// \return
    ///     >0:                                å¤±è´¥.
    ///     =0:                                æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_SetReflectionMode(IN int DeviceID, IN int HeadNo, IN SGIF_REFLECTIONMODE ReflectionMode);
    // Set Mask
    ///
    /// \brief SGIF_SetMask                    å±è”½è®¾å®š
    /// \param DeviceID                        è®¾å¤‡ID号,范围为0-63.
    /// \param HeadNo                        ä¼ æ„Ÿå¤´ç¼–号
    /// \param OnOff                        å¼€å…³
    /// \param HeadNo                        ç‚¹ä½1
    /// \param HeadNo                        ç‚¹ä½2
    /// \return
    ///     >0:                                å¤±è´¥.
    ///     =0:                                æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_SetMask(IN int DeviceID, IN int HeadNo, IN BOOL OnOff, IN int Pos1, IN int Pos2);
    // Set Median
    ///
    /// \brief SGIF_SetMedian                ä¸­ä½æ•°è®¾å®š
    /// \param DeviceID                        è®¾å¤‡ID号,范围为0-63.
    /// \param HeadNo                        ä¼ æ„Ÿå¤´ç¼–号
    /// \param Median                        ä¸­ä½æ•°
    /// \return
    ///     >0:                                å¤±è´¥.
    ///     =0:                                æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_SetMedian(IN int DeviceID, IN int HeadNo, IN SGIF_MEDIAN Median);
    // Set LASER CTRL group
    ///
    /// \brief SGIF_SetLaserCtrlGroup        Laser Ctrl组设定
    /// \param DeviceID                        è®¾å¤‡ID号,范围为0-63.
    /// \param HeadNo                        ä¼ æ„Ÿå¤´ç¼–号
    /// \param LaserCtrlGroup                Laser Ctrl组
    /// \return
    ///     >0:                                å¤±è´¥.
    ///     =0:                                æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_SetLaserCtrlGroup(IN int DeviceID, IN int HeadNo, IN SGIF_LASER_CTRL_GROUP LaserCtrlGroup);
    // Set Mutual interference prevention group
    ///
    /// \brief SGIF_SetMutualInterferencePreventionGroup        é˜²æ­¢äº’相干扰组设定
    /// \param DeviceID                                            è®¾å¤‡ID号,范围为0-63.
    /// \param HeadNo                                            ä¼ æ„Ÿå¤´ç¼–号
    /// \param Group                                            ç»„
    /// \return
    ///     >0:                                                    å¤±è´¥.
    ///     =0:                                                    æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_SetMutualInterferencePreventionGroup(IN int DeviceID, IN int HeadNo, IN SGIF_MUTUAL_INTERFERENCE_PREVENTION_GROUP Group);
    // Set Calculation method
    ///
    /// \brief SGIF_SetCalcMethod        è®¡ç®—方式设定
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param OutNo                    è¾“出OUT编号
    /// \param CalcMethod                è®¡ç®—方法
    /// \param HeadOutNo                ä¼ æ„Ÿå¤´è¾“出编号
    /// \return
    ///     >0:                                                    å¤±è´¥.
    ///     =0:                                                    æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_SetCalcMethod(IN int DeviceID, IN int OutNo, IN SGIF_CALCMETHOD CalcMethod, IN int HeadOutNo);
    // Set Surface to be measured
    ///
    /// \brief SGIF_SetCalcTarget        æµ‹é‡ç›®æ ‡è®¾å®š
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param OutNo                    è¾“出OUT编号
    /// \param CalcTarget                è®¡ç®—标签
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_SetCalcTarget(IN int DeviceID, IN int OutNo, IN SGIF_CALCTARGET CalcTarget);
    // Set OUT to be calculated (ADD, SUB)
    ///
    /// \brief SGIF_SetOutAddSub        å¾…计算的OUT(Add,Sub)设定
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param OutNo                    è¾“出OUT编号
    /// \param AddSub1                    å¾…计算的OUT
    /// \param AddSub2                    å¾…计算的OUT
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_SetOutAddSub(IN int DeviceID, IN int OutNo, IN int AddSub1, IN int AddSub2);
    // Set OUT to be calculated (AVE, MAX, MIN, P-P)
    ///
    /// \brief SGIF_SetOutOperation        å¾…计算的OUT(Ave,Max,Min,P-P)设定
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param OutNo                    è¾“出OUT编号
    /// \param TargetOut                å¤šä¸ªOUT组合
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_SetOutOperation(IN int DeviceID, IN int OutNo, IN SGIF_OUTNO TargetOut);
    // Set Scaling
    ///
    /// \brief SGIF_SetScaling            ç¼©æ”¾è®¾å®š
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param OutNo                    è¾“出OUT编号
    /// \param InputValue1                ç‚¹1的测量值(输入值),传有效数字(去掉小数点后的整形)
    /// \param OutputValue1                ç‚¹1的显示值(输出值),传有效数字(去掉小数点后的整形)
    /// \param InputValue2                ç‚¹2的测量值(输入值),传有效数字(去掉小数点后的整形)
    /// \param OutputValue2                ç‚¹2的显示值(输出值),传有效数字(去掉小数点后的整形)
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_SetScaling(IN int DeviceID, IN int OutNo, IN int InputValue1, IN int OutputValue1, IN int InputValue2, IN int OutputValue2);
    // Set Filter Mode
    ///
    /// \brief SGIF_SetFilter            æ»¤æ³¢å™¨è®¾å®š
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param OutNo                    è¾“出OUT编号
    /// \param FilterMode                æ»¤æ³¢æ¨¡å¼
    /// \param FilterPara                æ»¤æ³¢å‚æ•°
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_SetFilter(IN int DeviceID, IN int OutNo, IN SGIF_FILTERMODE FilterMode, IN SGIF_FILTERPARA FilterPara);
    // Set Trigger Mode
    ///
    /// \brief SGIF_SetTriggerMode        è§¦å‘模式设定
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param OutNo                    è¾“出OUT编号
    /// \param TriggerMode                è§¦å‘模式
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_SetTriggerMode(IN int DeviceID, IN int OutNo, IN SGIF_TRIGGERMODE TriggerMode);
    // Set Offset
    ///
    /// \brief SGIF_SetOffset            åç§»è®¾å®š
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param OutNo                    è¾“出OUT编号
    /// \param Offset                    åç§»é‡
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_SetOffset(IN int DeviceID, IN int OutNo, IN int Offset);
    // Set Calculation Mode
    ///
    /// \brief SGIF_SetCalcMode            æ£€æµ‹æ¨¡å¼ï¼ˆæµ‹é‡æ¨¡å¼ï¼‰è®¾å®š
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param OutNo                    è¾“出OUT编号
    /// \param CalcMode                    æ£€æµ‹æ¨¡å¼ç¼–号
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_SetCalcMode(IN int DeviceID, IN int OutNo, IN SGIF_CALCMODE CalcMode);
    // Set Minimum Display Unit
    ///
    /// \brief SGIF_SetDisplayUnit        è®¾å®šæ˜¾ç¤ºå•位设定
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param OutNo                    è¾“出OUT编号
    /// \param DisplayUnit                æ˜¾ç¤ºå•位
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_SetDisplayUnit(IN int DeviceID, IN int OutNo, IN SGIF_DISPLAYUNIT DisplayUnit);
    // Set Synchronization
    ///
    /// \brief SGIF_SetSynchronization        åŒæ­¥è®¾å®š
    /// \param DeviceID                        è®¾å¤‡ID号,范围为0-63.
    /// \param OutNo                        è¾“出OUT编号
    /// \param OnOff                        å¼€å…³
    /// \return
    ///     >0:                                å¤±è´¥.
    ///     =0:                                æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_SetSynchronization(IN int DeviceID, IN int OutNo, IN BOOL OnOff);
    // Set Storage (OUT No. specification)
    ///
    /// \brief SGIF_SetStorageTarget        å­˜å‚¨ï¼ˆOUT编号规格)设定
    /// \param DeviceID                        è®¾å¤‡ID号,范围为0-63.
    /// \param OutNo                        è¾“出OUT编号
    /// \param OnOff                        å¼€å…³
    /// \return
    ///     >0:                                å¤±è´¥.
    ///     =0:                                æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_SetStorageTarget(IN int DeviceID, IN int OutNo, IN BOOL OnOff);
    // Set Sampling Rate
    ///
    /// \brief SGIF_SetSamplingCycle        é‡‡æ ·å‘¨æœŸè®¾å®š
    /// \param DeviceID                        è®¾å¤‡ID号,范围为0-63.
    /// \param SamplingCycle                é‡‡æ ·å‘¨æœŸ
    /// \return
    ///     >0:                                å¤±è´¥.
    ///     =0:                                æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_SetSamplingCycle(IN int DeviceID, IN SGIF_SAMPLINGCYCLE SamplingCycle);
    // Set Mutual Interference Prevention
    ///
    /// \brief SGIF_SetMutualInterferencePrevention        é˜²æ­¢äº’相干扰组设定
    /// \param DeviceID                                    è®¾å¤‡ID号,范围为0-63.
    /// \param OnOff                                    ç»„设定
    /// \return
    ///     >0:                                            å¤±è´¥.
    ///     =0:                                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_SetMutualInterferencePrevention(IN int DeviceID, IN SGIF_MUTUAL_INTERFERENCE_PREVENTION OnOff);
    // Set Strobe Time
    ///
    /// \brief SGIF_SetStrobeTime            é€‰é€šæ—¶é—´è®¾å®š
    /// \param DeviceID                        è®¾å¤‡ID号,范围为0-63.
    /// \param StrobeTime                    é€‰é€šæ—¶é—´
    /// \return
    ///     >0:                                å¤±è´¥.
    ///     =0:                                æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_SetStrobeTime(IN int DeviceID, IN SGIF_STOROBETIME StrobeTime);
    // Set Data Storage
    ///
    /// \brief SGIF_SetDataStorage            æ•°æ®å­˜å‚¨è®¾å®š
    /// \param DeviceID                        è®¾å¤‡ID号,范围为0-63.
    /// \param NumStorage                    å¾…存储数据的编号
    /// \param StorageCycle                    å­˜å‚¨å‘¨æœŸ
    /// \return
    ///     >0:                                å¤±è´¥.
    ///     =0:                                æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_SetDataStorage(IN int DeviceID, IN int NumStorage, IN SGIF_STORAGECYCLE StorageCycle);
    // EncoderSetting
    ///
    /// \brief SGIF_SetRunningMode            è¿è¡Œæ¨¡å¼è®¾ç½®(不支持SCI设备)
    /// \param DeviceID                        è®¾å¤‡ID号,范围为0-63.
    /// \param runningmode                    è¿è¡Œæ¨¡å¼ 0:OFF/1:定时/2:触发
    /// \param CatchDirection               æ£€æµ‹æ–¹å‘ 0:正负计时/1:正计时/2:负计时
    /// \return
    ///     >0:                                å¤±è´¥.
    ///     =0:                                æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_SetRunningMode(IN int DeviceID, IN SGIF_EmRunningMode Runningmode, IN SGIF_EmDirection CatchDirection);
    // EncoderInputSetting
    ///
    /// \brief SGIF_SetEncoderMode            ç¼–码器输入模式设置(不支持SCI设备)
    /// \param DeviceID                        è®¾å¤‡ID号,范围为0-63.
    /// \param Inputmode                    è¿è¡Œæ¨¡å¼ 0:1相1递增/1:2相1递增/2:2相2递增,3:2相4递增
    /// \param MinInputTime                    æœ€å°è¾“入时间
    /// \param TrigInterval                    è§¦å‘é—´éš”
    /// \return
    ///     >0:                                å¤±è´¥.
    ///     =0:                                æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_SetEncoderMode(IN int DeviceID, IN SGIF_EmEncoderInput Inputmode,IN SGIF_EmInputTime InputTime,IN int TrigInterval);
    // SGIF_SetFormula
    ///
    /// \brief SGIF_SetFormula                è®¾ç½®é…æ–¹
    /// \param DeviceID                        è®¾å¤‡ID号,范围为0-63.
    /// \param filePath                        é…æ–¹è·¯å¾„
    /// \return
    ///     >0:                                å¤±è´¥.
    ///     =0:                                æˆåŠŸ.
    ///  derive
    EXP RC WINAPI SGIF_SetFormula(IN int DeviceID, IN char* filePath );
    // SGIF_SetFormula
    ///
    /// \brief SGIF_SetFormula                è®¾ç½®é…æ–¹
    /// \param DeviceID                        è®¾å¤‡ID号,范围为0-63.
    /// \param filePath                        é…æ–¹è·¯å¾„
    /// \return
    ///     >0:                                å¤±è´¥.
    ///     =0:                                æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_DeriveFormula(IN int DeviceID, IN char* filePath);
    ///////////////////////////////////////////////
    // Setting confirmation commands
    //
    // Get Tolerance
    ///
    /// \brief SGIF_GetTolerance            å…¬å·®è®¾å®šèŽ·å–
    /// \param DeviceID                        è®¾å¤‡ID号,范围为0-63.
    /// \param OutNo                        è¾“出OUT编号
    /// \param UpperLimit                    ä¸Šé™ï¼Œä¼ å‡ºä¸ºæœ‰æ•ˆæ•°å­—(去掉小数点后的整形)
    /// \param LowerLimit                    ä¸‹é™ï¼Œä¼ å‡ºä¸ºæœ‰æ•ˆæ•°å­—(去掉小数点后的整形)
    /// \param Hysteresis                    æ»žåŽï¼Œä¼ å‡ºä¸ºæœ‰æ•ˆæ•°å­—(去掉小数点后的整形)
    /// \return
    ///     >0:                                å¤±è´¥.
    ///     =0:                                æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_GetTolerance(IN int DeviceID, IN int OutNo, OUT int * UpperLimit, OUT int * LowerLimit, OUT int * Hysteresis);
    // Get ABLE
    ///
    /// \brief SGIF_GetAbleMode                Able设定获取
    /// \param DeviceID                        è®¾å¤‡ID号,范围为0-63.
    /// \param HeadNo                        ä¼ æ„Ÿå¤´ç¼–号
    /// \param AbleMode                        Ableģʽ
    /// \return
    ///     >0:                                å¤±è´¥.
    ///     =0:                                æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_GetAbleMode(IN int DeviceID, IN int HeadNo, OUT SGIF_ABLEMODE * AbleMode);
    // Get ABLE Control Range
    ///
    /// \brief SGIF_GetAbleMinMax            Able控制范围获取
    /// \param DeviceID                        è®¾å¤‡ID号,范围为0-63.
    /// \param HeadNo                        ä¼ æ„Ÿå¤´ç¼–号
    /// \param Min                            æœ€å°å€¼
    /// \param Max                            æœ€å¤§å€¼
    /// \return
    ///     >0:                                å¤±è´¥.
    ///     =0:                                æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_GetAbleMinMax(IN int DeviceID, IN int HeadNo, OUT int * Min, OUT int * Max);
    // Get Detection mode
    ///
    /// \brief SGIF_GetMeasureMode            æµ‹é‡æ¨¡å¼èŽ·å–
    /// \param DeviceID                        è®¾å¤‡ID号,范围为0-63.
    /// \param HeadNo                        ä¼ æ„Ÿå¤´ç¼–号
    /// \param MeasureMode                    æµ‹é‡æ¨¡å¼
    /// \return
    ///     >0:                                å¤±è´¥.
    ///     =0:                                æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_GetMeasureMode(IN int DeviceID, IN int HeadNo, OUT SGIF_MEASUREMODE * MeasureMode);
    // Get Base point
    ///
    /// \brief SGIF_GetBasicPoint            åŸºå‡†ç‚¹èŽ·å–
    /// \param DeviceID                        è®¾å¤‡ID号,范围为0-63.
    /// \param HeadNo                        ä¼ æ„Ÿå¤´ç¼–号
    /// \param BasicPoint                    åŸºå‡†ç‚¹
    /// \return
    ///     >0:                                å¤±è´¥.
    ///     =0:                                æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_GetBasicPoint(IN int DeviceID, IN int HeadNo, OUT SGIF_BASICPOINT * BasicPoint);
    // Get Number of Times of Alarm Processing
    ///
    /// \brief SGIF_GetNumAlarm                è­¦æŠ¥å¤„理次数获取
    /// \param DeviceID                        è®¾å¤‡ID号,范围为0-63.
    /// \param HeadNo                        ä¼ æ„Ÿå¤´ç¼–号
    /// \param AlarmNum                        è­¦æŠ¥æ¬¡æ•°
    /// \return
    ///     >0:                                å¤±è´¥.
    ///     =0:                                æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_GetNumAlarm(IN int DeviceID, IN int HeadNo, OUT int * AlarmNum);
    // Get Number of Times of Alarm Recovery
    ///
    /// \brief SGIF_GetNumRecovery            è­¦æŠ¥æ¢å¤æ¬¡æ•°èŽ·å–
    /// \param DeviceID                        è®¾å¤‡ID号,范围为0-63.
    /// \param HeadNo                        ä¼ æ„Ÿå¤´ç¼–号
    /// \param RecoveryNum                    æ¢å¤æ¬¡æ•°
    /// \return
    ///     >0:                                å¤±è´¥.
    ///     =0:                                æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_GetNumRecovery(IN int DeviceID, IN int HeadNo, OUT int * RecoveryNum);
    // Get Alarm Level
    ///
    /// \brief SGIF_GetAlarmLevel            è­¦æŠ¥çº§åˆ«èŽ·å–
    /// \param DeviceID                        è®¾å¤‡ID号,范围为0-63.
    /// \param HeadNo                        ä¼ æ„Ÿå¤´ç¼–号
    /// \param AlarmLevel                    è­¦æŠ¥çº§åˆ«
    /// \return
    ///     >0:                                å¤±è´¥.
    ///     =0:                                æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_GetAlarmLevel(IN int DeviceID, IN int HeadNo, OUT int * AlarmLevel);
    // Get Mounting Mode
    ///
    /// \brief SGIF_GetReflectionMode        å®‰è£…模式获取
    /// \param DeviceID                        è®¾å¤‡ID号,范围为0-63.
    /// \param HeadNo                        ä¼ æ„Ÿå¤´ç¼–号
    /// \param ReflectionMode                åå°„模式
    /// \return
    ///     >0:                                å¤±è´¥.
    ///     =0:                                æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_GetReflectionMode(IN int DeviceID, IN int HeadNo, OUT SGIF_REFLECTIONMODE * ReflectionMode);
    // Get Mask
    ///
    /// \brief SGIF_GetMask                    å±è”½è®¾å®šèŽ·å–
    /// \param DeviceID                        è®¾å¤‡ID号,范围为0-63.
    /// \param HeadNo                        ä¼ æ„Ÿå¤´ç¼–号
    /// \param OnOff                        å¼€å…³
    /// \param Pos1                            ä½ç½®1
    /// \param Pos2                            ä½ç½®2
    /// \return
    ///     >0:                                å¤±è´¥.
    ///     =0:                                æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_GetMask(IN int DeviceID, IN int HeadNo, OUT BOOL * OnOff, OUT int * Pos1, OUT int * Pos2);
    // Get Median
    ///
    /// \brief SGIF_GetMedian                ä¸­ä½æ•°èŽ·å–
    /// \param DeviceID                        è®¾å¤‡ID号,范围为0-63.
    /// \param HeadNo                        ä¼ æ„Ÿå¤´ç¼–号
    /// \param Median                        ä¸­ä½æ•°
    /// \return
    ///     >0:                                å¤±è´¥.
    ///     =0:                                æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_GetMedian(IN int DeviceID, IN int HeadNo, OUT SGIF_MEDIAN * Median);
    // Get LASER CTRL group
    ///
    /// \brief SGIF_GetLaserCtrlGroup        Laser Ctrl组获取
    /// \param DeviceID                        è®¾å¤‡ID号,范围为0-63.
    /// \param HeadNo                        ä¼ æ„Ÿå¤´ç¼–号
    /// \param LaserCtrlGroup                Laser Ctrl组
    /// \return
    ///     >0:                                å¤±è´¥.
    ///     =0:                                æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_GetLaserCtrlGroup(IN int DeviceID, IN int HeadNo, OUT SGIF_LASER_CTRL_GROUP * LaserCtrlGroup);
    // Get Mutual interference prevention group
    ///
    /// \brief SGIF_GetMutualInterferencePreventionGroup    é˜²æ­¢äº’相干扰组获取
    /// \param DeviceID                                        è®¾å¤‡ID号,范围为0-63.
    /// \param HeadNo                                        ä¼ æ„Ÿå¤´ç¼–号
    /// \param Group                                        ç»„
    /// \return
    ///     >0:                                                å¤±è´¥.
    ///     =0:                                                æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_GetMutualInterferencePreventionGroup(IN int DeviceID, IN int HeadNo, OUT SGIF_MUTUAL_INTERFERENCE_PREVENTION_GROUP * Group);
    // Get Calculation method
    ///
    /// \brief SGIF_GetCalcMethod        è®¡ç®—方式获取
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param OutNo                    è¾“出OUT编号
    /// \param CalcMethod                è®¡ç®—方法
    /// \param HeadOutNo                ä¼ æ„Ÿå¤´æˆ–OUT编号
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_GetCalcMethod(IN int DeviceID, IN int OutNo, OUT SGIF_CALCMETHOD * CalcMethod, OUT int * HeadOutNo);
    // Get Surface to be measured
    ///
    /// \brief SGIF_GetCalcTarget        æµ‹é‡ç›®æ ‡èŽ·å–
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param OutNo                    è¾“出OUT编号
    /// \param CalcTarget                è®¡ç®—标签
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_GetCalcTarget(IN int DeviceID, IN int OutNo, OUT SGIF_CALCTARGET * CalcTarget);
    // Get OUT to be calculated (ADD, SUB)
    ///
    /// \brief SGIF_GetOutAddSub        å¾…计算的OUT(Add,Sub)获取
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param OutNo                    è¾“出OUT编号
    /// \param AddSub1                    å¾…计算的OUT编号1
    /// \param AddSub2                    å¾…计算的OUT编号2
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_GetOutAddSub(IN int DeviceID, IN int OutNo, OUT int * AddSub1, OUT int * AddSub2);
    // Get OUT to be calculated (AVE, MAX, MIN, P-P)
    ///
    /// \brief SGIF_GetOutOperation        å¾…计算的OUT(Ave,Max,Min,P-P)获取
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param OutNo                    è¾“出OUT编号
    /// \param TargetOut                å¤šä¸ªOUT或HEAD组合
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_GetOutOperation(IN int DeviceID, IN int OutNo, OUT SGIF_OUTNO * TargetOut);
    // Get Scaling
    ///
    /// \brief SGIF_GetScaling            ç¼©æ”¾è®¾å®šèŽ·å–
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param OutNo                    è¾“出OUT编号
    /// \param InputValue1                ç‚¹1的测量值(输入值),传出为有效数字(去掉小数点后的整形)
    /// \param OutputValue1                ç‚¹1的显示值(输出值),传出为有效数字(去掉小数点后的整形)
    /// \param InputValue2                ç‚¹2的测量值(输入值),传出为有效数字(去掉小数点后的整形)
    /// \param OutputValue2                ç‚¹2的显示值(输出值),传出为有效数字(去掉小数点后的整形)
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_GetScaling(IN int DeviceID, IN int OutNo, OUT int * InputValue1, OUT int * OutputValue1, OUT int * InputValue2, OUT int * OutputValue2);
    // Get Filter Mode
    ///
    /// \brief SGIF_GetFilter            æ»¤æ³¢å™¨è®¾å®šèŽ·å–
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param OutNo                    è¾“出OUT编号
    /// \param FilterMode                æ»¤æ³¢å™¨æ¨¡å¼
    /// \param FilterPara                æ»¤æ³¢å‚æ•°
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_GetFilter(IN int DeviceID, IN int OutNo, OUT SGIF_FILTERMODE * FilterMode, OUT SGIF_FILTERPARA * FilterPara);
    // Get Trigger Mode
    ///
    /// \brief SGIF_GetTriggerMode        è§¦å‘模式获取
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param OutNo                    è¾“出OUT编号
    /// \param TriggerMode                è§¦å‘模式
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_GetTriggerMode(IN int DeviceID, IN int OutNo, OUT SGIF_TRIGGERMODE * TriggerMode);
    // Get Offset
    ///
    /// \brief SGIF_GetOffset            åç§»èŽ·å–
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param OutNo                    è¾“出OUT编号
    /// \param Offset                    åç§»é‡
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_GetOffset(IN int DeviceID, IN int OutNo, OUT int * Offset);
    // Get Calculation Mode
    ///
    /// \brief SGIF_GetCalcMode            æ£€æµ‹æ¨¡å¼ï¼ˆæµ‹é‡æ¨¡å¼ï¼‰èŽ·å–
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param OutNo                    è¾“出OUT编号
    /// \param CalcMode                    æµ‹é‡æ¨¡å¼
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_GetCalcMode(IN int DeviceID, IN int OutNo, OUT SGIF_CALCMODE * CalcMode);
    // Get Minimum Display Unit
    ///
    /// \brief SGIF_GetDisplayUnit        æ˜¾ç¤ºæœ€å°å•位获取
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param OutNo                    è¾“出OUT编号
    /// \param DisplayUnit                æ˜¾ç¤ºæœ€å°å•位
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_GetDisplayUnit(IN int DeviceID, IN int OutNo, OUT SGIF_DISPLAYUNIT * DisplayUnit);
    // Get Synchronization
    ///
    /// \brief SGIF_GetSynchronization        åŒæ­¥è®¾å®šèŽ·å–
    /// \param DeviceID                        è®¾å¤‡ID号,范围为0-63.
    /// \param OutNo                        è¾“出OUT编号
    /// \param OnOff                        å¼€å…³
    /// \return
    ///     >0:                                å¤±è´¥.
    ///     =0:                                æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_GetSynchronization(IN int DeviceID, IN int OutNo, OUT BOOL * OnOff);
    // Get Storage (OUT No. specification)
    ///
    /// \brief SGIF_GetStorageTarget        å­˜å‚¨ï¼ˆOUT编号设定)获取
    /// \param DeviceID                        è®¾å¤‡ID号,范围为0-63.
    /// \param OutNo                        è¾“出OUT编号
    /// \param OnOff                        å¼€å…³
    /// \return
    ///     >0:                                å¤±è´¥.
    ///     =0:                                æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_GetStorageTarget(IN int DeviceID, IN int OutNo, OUT BOOL * OnOff);
    // Get Sampling Rate
    ///
    /// \brief SGIF_GetSamplingCycle        é‡‡æ ·å‘¨æœŸèŽ·å–
    /// \param DeviceID                        è®¾å¤‡ID号,范围为0-63.
    /// \param SamplingCycle                é‡‡æ ·å‘¨æœŸ
    /// \return
    ///     >0:                                å¤±è´¥.
    ///     =0:                                æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_GetSamplingCycle(IN int DeviceID, OUT SGIF_SAMPLINGCYCLE * SamplingCycle);
    // Get Mutual Interference Prevention
    ///
    /// \brief SGIF_GetMutualInterferencePrevention        é˜²æ­¢äº’相干扰获取
    /// \param DeviceID                                    è®¾å¤‡ID号,范围为0-63.
    /// \param OnOff                                    å¼€å…³
    /// \return
    ///     >0:                                            å¤±è´¥.
    ///     =0:                                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_GetMutualInterferencePrevention(IN int DeviceID, OUT SGIF_MUTUAL_INTERFERENCE_PREVENTION * OnOff);
    // Get Strobe Time
    ///
    /// \brief SGIF_GetStrobeTime        é€‰é€šæ—¶é—´èŽ·å–
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param OutputFormat                è¾“出形式
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_GetStrobeTime(IN int DeviceID, OUT SGIF_STOROBETIME * StrobeTime);
    // Get Data Storage
    ///
    /// \brief SGIF_GetDataStorage        æ•°æ®å­˜å‚¨èŽ·å–
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param NumStorage                å¸¦å­˜å‚¨æ•°æ®ç¼–号
    /// \param StorageCycle                å­˜å‚¨å‘¨æœŸ
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_GetDataStorage(IN int DeviceID, OUT int * NumStorage, OUT SGIF_STORAGECYCLE * StorageCycle);
    // Get Active head count
    ///
    /// \brief SGIF_GetNumOfUsedHeads        ä¸»åЍOUT计数获取
    /// \param DeviceID                        è®¾å¤‡ID号,范围为0-63.
    /// \param NumOfUsedHeads                ä¸»åЍOUT/传感头计数
    /// \return
    ///     >0:                                å¤±è´¥.
    ///     =0:                                æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_GetNumOfUsedHeads(IN int DeviceID, OUT int * NumOfUsedHeads);
    // Get Active OUT count
    ///
    /// \brief SGIF_GetNumOfUsedOut            ä¸»åŠ¨ä¼ æ„Ÿå¤´è®¡æ•°èŽ·å–
    /// \param DeviceID                        è®¾å¤‡ID号,范围为0-63.
    /// \param NumOfUsedHeads                ä¸»åЍOUT/传感头计数
    /// \return
    ///     >0:                                å¤±è´¥.
    ///     =0:                                æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_GetNumOfUsedOut(IN int DeviceID, OUT int * NumOfUsedOut);
    // Get Active Running Time
    ///
    /// \brief SGIF_GetDeviceRuningTime        èŽ·å–ç›¸æœºè¿è¡Œæ—¶é•¿ï¼Œå•ä½s
    /// \param DeviceID                        è®¾å¤‡ID号,范围为0-63.
    /// \param HeadNo                        0:控制器; 1-4:传感头编号
    /// \param RuningTime                    è¿è¡Œæ—¶é—´
    /// \return
    ///     >0:                                å¤±è´¥.
    ///     =0:                                æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_GetDeviceRuningTime(IN int DeviceID, IN int HeadNo, OUT unsigned int * RuningTime);
    ///////////////////////////////////////////////
    // Other commands
    //
    // Opens the Ethernet device.
    ///
    /// \brief SGIF_OpenDeviceETHER            æ‰“开设备网络连接
    /// \param DeviceID                        è®¾å¤‡ID号,范围为0-63.
    /// \param OpenParam                    ç½‘络连接参数
    /// \return
    ///     >0:                                å¤±è´¥.
    ///     =0:                                æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_OpenDeviceETHER(IN int DeviceID, SGIF_OPENPARAM_ETHERNET * OpenParam,DWORD TIMEOUT=3);
    // Closes the currently open device.
    ///
    /// \brief SGIF_CloseDevice                å…³é—­è®¾å¤‡ç½‘络连接
    /// \param DeviceID                        è®¾å¤‡ID号,范围为0-63.
    /// \return
    ///     >0:                                å¤±è´¥.
    ///     =0:                                æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_CloseDevice(IN int DeviceID);
    ///////////////////////////////////////////////
    // Mode change commands
    //
    // Mode Switch
    ///
    /// \brief SGIF_SetMode                    æ¨¡å¼åˆ‡æ¢
    /// \param DeviceID                        è®¾å¤‡ID号,范围为0-63.
    /// \param Mode                            Ä£Ê½
    /// \return
    ///     >0:                                å¤±è´¥.
    ///     =0:                                æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_SetMode(IN int DeviceID, IN SGIF_MODE Mode);
    EXP RC WINAPI SGIF_Refresh(IN int DeviceID);
    //////////////////////////////////////////////一次回调相关///////////////////////////////////////
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param OutBuffer                æ•°æ®æ•°ç»„
    /// \param NumReceived                å®žé™…接收的数据个数
    ///
    typedef void(*SGIF_DataStorageOneTimeCallBack)(OUT int DeviceID);
    ///////////////////////////////////////////////
    /// \brief SGIF_SetOneDataStorage        æ³¨å†Œä¸€æ¬¡å›žè°ƒ
    /// \param DeviceID                        è®¾å¤‡ID号,范围为0-63.
    /// \param SGIF_BatchOneTimeCallBack    å›žè°ƒå‡½æ•°
    /// \return
    ///     >0:                                å¤±è´¥.
    ///     =0:                                æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_SetOneDataStorage(IN int DeviceID, IN SGIF_DataStorageOneTimeCallBack CallFunc);
    //////////////////////////////////////////////////////////////////////////////////////////////
    // Get encoder store value
    /// \brief SGIF_GetEncoderStoreValue编码器值存储数据输出(仅SCI设备支持)
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param OutNo                    ç¼–码器编号
    /// \param NumOfBuffer                ç¼“冲区大小(最多可接受多少个数据)
    /// \param OutBuffer                æ•°æ®æ•°ç»„
    /// \param NumReceived                å®žé™…接收的数据个数
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_GetEncoderStoreValue(IN int DeviceID, IN int OutNo, IN int NumOfBuffer, OUT int * OutBuffer, OUT int *NumReceived);
    // Get encoder value
    /// \brief SGIF_GetEncoderCurrentValue    è¯»å–编码器当前值(仅SCI设备支持)
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param OutNo                    ç¼–码器编号(1-3)
    /// \param OutBuffer                æ•°æ®æŒ‡é’ˆ
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_GetEncoderCurrentValue(IN int DeviceID, IN int OutNo, OUT int * OutBuffer);
    // encoder Reset
    /// \brief SGIF_EncoderReset        ç¼–码器值置零(仅SCI设备支持)
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param OutNo                    ç¼–码器编号(1-3)
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_EncoderReset(IN int DeviceID, IN int OutNo);
    // Set Encoder Number
    /// \brief SGIF_SetEncoderNumber    é€‰æ‹©ç¼–码器(仅SCI设备支持)
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param OutNo                    ç¼–码器编号(1-3)
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_SetEncoderNumber(IN int DeviceID, IN int OutNo);
    // Get encoder number
    /// \brief SGIF_GetEncoderNumber    è¯»å–设置的编码器编号(仅SCI设备支持)
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param OutBuffer                æ•°æ®æŒ‡é’ˆ
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_GetEncoderNumber(IN int DeviceID, OUT int * OutBuffer);
    //Set Encoder Parameters
    /// \brief SGIF_SetEncoderParameters设置编码器参数(仅SCI设备支持)
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param OutNo                    ç¼–码器编号(1-3)
    /// \param InputMode                è¾“入模式(0-3)
    /// \param InputTime                æœ€ä½Žè¾“入时间(100,200,500,1000,2000,5000,10000,20000)(ns)
    /// \param interval                    é—´éš”(1-10000)
    /// \param OperatingMode            è¿è¡Œæ¨¡å¼ï¼ˆ0-2)
    /// \param DetectionDirection        æ£€æµ‹æ–¹å‘(0-2)
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_SetEncoderParameters(IN int DeviceID, IN int OutNo, IN int InputMode, IN int InputTime, IN int interval, IN int OperatingMode, IN int DetectionDirection);
    //Get Encoder Parameters
    /// \brief SGIF_GetEncoderParameters读取编码器参数(仅SCI设备支持)
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param OutNo                    ç¼–码器编号(1-3)
    /// \param InputMode                è¾“入模式(0-3)
    /// \param InputTime                æœ€ä½Žè¾“入时间(100,200,500,1000,2000,5000,10000,20000)(ns)
    /// \param interval                    é—´éš”(1-10000)
    /// \param OperatingMode            è¿è¡Œæ¨¡å¼ï¼ˆ0-2)
    /// \param DetectionDirection        æ£€æµ‹æ–¹å‘(0-2)
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_GetEncoderParameters(IN int DeviceID, IN int OutNo, OUT int * InputMode, OUT int * InputTime, OUT int * interval, OUT int * OperatingMode, OUT int * DetectionDirection);
    //Set Analog Output
    /// \brief SGIF_SetAnalogOutput        è®¾ç½®æ¨¡æ‹Ÿé‡è¾“出(仅SCI设备支持)
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param OutNo                    æ¨¡æ‹Ÿé‡ç¼–号(1-3)
    /// \param OutputChannel            è¾“出通道(0-3)
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_SetAnalogOutput(IN int DeviceID, IN int OutNo, IN int OutputChannel);
    // Retrieve Analog Output Channel Number
    /// \brief SGIF_GetAnalogOutputChannel    èŽ·å–æ¨¡æ‹Ÿé‡è¾“å‡ºé€šé“ç¼–å·(仅SCI设备支持)
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param OutNo                    æ¨¡æ‹Ÿé‡ç¼–号(1-3)
    /// \param OutBuffer                æ•°æ®æŒ‡é’ˆ
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_GetAnalogOutputChannel(IN int DeviceID, IN int OutNo, OUT int * OutBuffer);
    //Set IO Digital Output
    /// \brief SGIF_SetIODigitalOutput    è®¾ç½®IO数字输出(仅SCI设备支持)
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param OutNo                    æ•°å­—输出编号(1-4)
    /// \param Level                    è¾“出位数(0:OFF,1:HI,2:GO,3:LO,4:STROBE)
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_SetIODigitalOutput(IN int DeviceID, IN int OutNo, IN int Level);
    // Retrieve IO Digital Output Channel Number
    /// \brief SGIF_GetIOOutputChannel    èŽ·å–IO数字量输出通道编号(仅SCI设备支持)
    /// \param DeviceID                    è®¾å¤‡ID号,范围为0-63.
    /// \param OutNo                    æ•°å­—输出编号(1-4)
    /// \param OutBuffer                æ•°æ®æŒ‡é’ˆ
    /// \return
    ///     >0:                            å¤±è´¥.
    ///     =0:                            æˆåŠŸ.
    ///
    EXP RC WINAPI SGIF_GetIOOutputChannel(IN int DeviceID, IN int OutNo, OUT int * OutBuffer);
#ifdef __cplusplus
}
#endif
SourceCode/Bond/SGMeasurement/DLL/64bit/SGIFPJ.dll
Binary files differ
SourceCode/Bond/SGMeasurement/DLL/64bit/SGIFPJ.lib
Binary files differ
SourceCode/Bond/SGMeasurement/DLL/ZYϵÁÐͨÐÅ¿â²Î¿¼ÊÖ²á-V2.3.pdf
Binary files differ
SourceCode/Bond/SGMeasurement/Logger.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,79 @@
#include "pch.h"
#include "Logger.h"
CLogger& CLogger::Instance()
{
    static CLogger instance;
    return instance;
}
CLogger::CLogger()
{
    OpenLogFile();
}
CLogger::~CLogger()
{
    CloseLogFile();
}
void CLogger::OpenLogFile()
{
    CSingleLock lock(&m_csLogLock, TRUE);
    CTime now = CTime::GetCurrentTime();
    CString strLogDir = _T("Log");
    if (!PathFileExists(strLogDir)) {
        CreateDirectory(strLogDir, NULL);
    }
    CString strNewPath;
    strNewPath.Format(_T("%s\\SG_%04d%02d%02d.log"), strLogDir, now.GetYear(), now.GetMonth(), now.GetDay());
    if (m_strCurrentLogPath.CompareNoCase(strNewPath) != 0 || m_logFile.m_pStream == nullptr) {
        if (m_logFile.m_pStream) {
            m_logFile.Flush();
            m_logFile.Close();
        }
        if (m_logFile.Open(strNewPath,
            CFile::modeCreate | CFile::modeNoTruncate | CFile::modeWrite | CFile::typeBinary)) {
            if (m_logFile.GetLength() == 0) {
                WCHAR bom = 0xFEFF;
                m_logFile.Write(&bom, sizeof(WCHAR));
            }
            m_logFile.SeekToEnd();
            m_strCurrentLogPath = strNewPath;
        }
    }
}
void CLogger::WriteLine(CString str)
{
    CSingleLock lock(&m_csLogLock, TRUE);
    OpenLogFile();
    if (m_logFile.m_pStream) {
        CTime now = CTime::GetCurrentTime();
        CString strTime;
        strTime.Format(_T("[%02d:%02d:%02d]"), now.GetHour(), now.GetMinute(), now.GetSecond());
        CString strLine = strTime + str + _T("\r\n");
        m_logFile.Write((LPCTSTR)strLine, strLine.GetLength() * sizeof(WCHAR));
    }
}
void CLogger::CloseLogFile()
{
    CSingleLock lock(&m_csLogLock, TRUE);
    if (m_logFile.m_pStream) {
        m_logFile.Flush();
        m_logFile.Close();
        m_strCurrentLogPath.Empty();
    }
}
SourceCode/Bond/SGMeasurement/Logger.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,28 @@
#pragma once
#include <afx.h>
class CLogger
{
public:
    static CLogger& Instance();  // èŽ·å–å•ä¾‹
    void WriteLine(CString str); // å†™ä¸€è¡Œæ—¥å¿—
    void CloseLogFile();         // å…³é—­æ—¥å¿—文件
private:
    CLogger();
    ~CLogger();
    void OpenLogFile();          // å†…部打开文件
    CCriticalSection m_csLogLock;
    CString m_strCurrentLogPath;
    CStdioFile m_logFile;
};
#define LOG_LINE(x) CLogger::Instance().WriteLine(x)
#define LOG_LINEF(fmt, ...)                     \
    do {                                        \
        CString __log__;                        \
        __log__.Format(fmt, __VA_ARGS__);       \
        CLogger::Instance().WriteLine(__log__); \
    } while (0)
SourceCode/Bond/SGMeasurement/SGMeasurement.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,104 @@

// SGMeasurement.cpp: å®šä¹‰åº”用程序的类行为。
//
#include "pch.h"
#include "framework.h"
#include "SGMeasurement.h"
#include "SGMeasurementDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// CSGMeasurementApp
BEGIN_MESSAGE_MAP(CSGMeasurementApp, CWinApp)
    ON_COMMAND(ID_HELP, &CWinApp::OnHelp)
END_MESSAGE_MAP()
// CSGMeasurementApp æž„造
CSGMeasurementApp::CSGMeasurementApp()
{
    // æ”¯æŒé‡æ–°å¯åŠ¨ç®¡ç†å™¨
    m_dwRestartManagerSupportFlags = AFX_RESTART_MANAGER_SUPPORT_RESTART;
    // TODO: åœ¨æ­¤å¤„添加构造代码,
    // å°†æ‰€æœ‰é‡è¦çš„初始化放置在 InitInstance ä¸­
}
// å”¯ä¸€çš„ CSGMeasurementApp å¯¹è±¡
CSGMeasurementApp theApp;
// CSGMeasurementApp åˆå§‹åŒ–
BOOL CSGMeasurementApp::InitInstance()
{
    // å¦‚果应用程序存在以下情况,Windows XP ä¸Šéœ€è¦ InitCommonControlsEx()
    // ä½¿ç”¨ ComCtl32.dll ç‰ˆæœ¬ 6 æˆ–更高版本来启用可视化方式,则需要 InitCommonControlsEx()。否则,将无法创建窗口。
    INITCOMMONCONTROLSEX InitCtrls;
    InitCtrls.dwSize = sizeof(InitCtrls);
    // å°†å®ƒè®¾ç½®ä¸ºåŒ…括所有要在应用程序中使用的
    // å…¬å…±æŽ§ä»¶ç±»ã€‚
    InitCtrls.dwICC = ICC_WIN95_CLASSES;
    InitCommonControlsEx(&InitCtrls);
    CWinApp::InitInstance();
    // åˆå§‹åŒ– MFC RichEdit æŽ§ä»¶
    AfxInitRichEdit2();
    AfxEnableControlContainer();
    // åˆ›å»º shell ç®¡ç†å™¨ï¼Œä»¥é˜²å¯¹è¯æ¡†åŒ…含
    // ä»»ä½• shell æ ‘视图控件或 shell åˆ—表视图控件。
    CShellManager *pShellManager = new CShellManager;
    // æ¿€æ´»â€œWindows Native”视觉管理器,以便在 MFC æŽ§ä»¶ä¸­å¯ç”¨ä¸»é¢˜
    CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerWindows));
    // æ ‡å‡†åˆå§‹åŒ–
    // å¦‚果未使用这些功能并希望减小
    // æœ€ç»ˆå¯æ‰§è¡Œæ–‡ä»¶çš„大小,则应移除下列
    // ä¸éœ€è¦çš„特定初始化例程
    // æ›´æ”¹ç”¨äºŽå­˜å‚¨è®¾ç½®çš„æ³¨å†Œè¡¨é¡¹
    // TODO: åº”适当修改该字符串,
    // ä¾‹å¦‚修改为公司或组织名
    SetRegistryKey(_T("应用程序向导生成的本地应用程序"));
    CSGMeasurementDlg dlg;
    m_pMainWnd = &dlg;
    INT_PTR nResponse = dlg.DoModal();
    if (nResponse == IDOK)
    {
        // TODO:“确定”来关闭对话框的代码
    }
    else if (nResponse == IDCANCEL)
    {
        // TODO:“取消”来关闭对话框的代码
    }
    else if (nResponse == -1)
    {
        TRACE(traceAppMsg, 0, "警告: å¯¹è¯æ¡†åˆ›å»ºå¤±è´¥ï¼Œåº”用程序将意外终止。\n");
        TRACE(traceAppMsg, 0, "警告: å¦‚果您在对话框上使用 MFC æŽ§ä»¶ï¼Œåˆ™æ— æ³• #define _AFX_NO_MFC_CONTROLS_IN_DIALOGS。\n");
    }
    // åˆ é™¤ä¸Šé¢åˆ›å»ºçš„ shell ç®¡ç†å™¨ã€‚
    if (pShellManager != nullptr)
    {
        delete pShellManager;
    }
#if !defined(_AFXDLL) && !defined(_AFX_NO_MFC_CONTROLS_IN_DIALOGS)
    ControlBarCleanUp();
#endif
    // ç”±äºŽå¯¹è¯æ¡†å·²å…³é—­ï¼Œæ‰€ä»¥å°†è¿”回 FALSE ä»¥ä¾¿é€€å‡ºåº”用程序,而不是启动应用程序的消息泵。
    return FALSE;
}
SourceCode/Bond/SGMeasurement/SGMeasurement.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,32 @@

// SGMeasurement.h: PROJECT_NAME åº”用程序的主头文件
//
#pragma once
#ifndef __AFXWIN_H__
    #error "在包含此文件之前包含 'pch.h' ä»¥ç”Ÿæˆ PCH"
#endif
#include "resource.h"        // ä¸»ç¬¦å·
// CSGMeasurementApp:
// æœ‰å…³æ­¤ç±»çš„实现,请参阅 SGMeasurement.cpp
//
class CSGMeasurementApp : public CWinApp
{
public:
    CSGMeasurementApp();
// é‡å†™
public:
    virtual BOOL InitInstance();
// å®žçް
    DECLARE_MESSAGE_MAP()
};
extern CSGMeasurementApp theApp;
SourceCode/Bond/SGMeasurement/SGMeasurement.rc
Binary files differ
SourceCode/Bond/SGMeasurement/SGMeasurement.vcxproj
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,231 @@
<?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>17.0</VCProjectVersion>
    <ProjectGuid>{F8087F20-3A3E-18F2-09E3-9C139642EB58}</ProjectGuid>
    <Keyword>MFCProj</Keyword>
    <RootNamespace>SGMeasurement</RootNamespace>
    <WindowsTargetPlatformVersion>10.0.22621.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>v141</PlatformToolset>
    <CharacterSet>Unicode</CharacterSet>
    <UseOfMfc>Dynamic</UseOfMfc>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
    <ConfigurationType>Application</ConfigurationType>
    <UseDebugLibraries>false</UseDebugLibraries>
    <PlatformToolset>v141</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>v141</PlatformToolset>
    <CharacterSet>Unicode</CharacterSet>
    <UseOfMfc>Dynamic</UseOfMfc>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
    <ConfigurationType>Application</ConfigurationType>
    <UseDebugLibraries>false</UseDebugLibraries>
    <PlatformToolset>v141</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>
      <AdditionalIncludeDirectories>.\DLL\64bit;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
    </ClCompile>
    <Link>
      <SubSystem>Windows</SubSystem>
      <AdditionalLibraryDirectories>.\DLL\64bit;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
      <AdditionalDependencies>SGIFPJ.lib;%(AdditionalDependencies)</AdditionalDependencies>
    </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>
      <AdditionalIncludeDirectories>.\DLL\32bit;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
    </ClCompile>
    <Link>
      <SubSystem>Windows</SubSystem>
      <AdditionalLibraryDirectories>.\DLL\32bit;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
      <AdditionalDependencies>SGIFPJ.lib;%(AdditionalDependencies)</AdditionalDependencies>
    </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>
      <AdditionalIncludeDirectories>.\DLL\32bit;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
    </ClCompile>
    <Link>
      <SubSystem>Windows</SubSystem>
      <EnableCOMDATFolding>true</EnableCOMDATFolding>
      <OptimizeReferences>true</OptimizeReferences>
      <AdditionalLibraryDirectories>.\DLL\32bit;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
      <AdditionalDependencies>SGIFPJ.lib;%(AdditionalDependencies)</AdditionalDependencies>
    </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>
      <AdditionalIncludeDirectories>.\DLL\64bit;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
    </ClCompile>
    <Link>
      <SubSystem>Windows</SubSystem>
      <EnableCOMDATFolding>true</EnableCOMDATFolding>
      <OptimizeReferences>true</OptimizeReferences>
      <AdditionalLibraryDirectories>.\DLL\64bit;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
      <AdditionalDependencies>SGIFPJ.lib;%(AdditionalDependencies)</AdditionalDependencies>
    </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="framework.h" />
    <ClInclude Include="Logger.h" />
    <ClInclude Include="pch.h" />
    <ClInclude Include="Resource.h" />
    <ClInclude Include="SGMeasurement.h" />
    <ClInclude Include="SGMeasurementDlg.h" />
    <ClInclude Include="targetver.h" />
  </ItemGroup>
  <ItemGroup>
    <ClCompile Include="Logger.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>
    <ClCompile Include="SGMeasurement.cpp" />
    <ClCompile Include="SGMeasurementDlg.cpp" />
  </ItemGroup>
  <ItemGroup>
    <ResourceCompile Include="SGMeasurement.rc" />
  </ItemGroup>
  <ItemGroup>
    <None Include="res\SGMeasurement.rc2" />
  </ItemGroup>
  <ItemGroup>
    <Image Include="res\menu_close.ico" />
    <Image Include="res\menu_restore.ico" />
    <Image Include="res\SGMeasurement.ico" />
  </ItemGroup>
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
  <ImportGroup Label="ExtensionTargets">
  </ImportGroup>
</Project>
SourceCode/Bond/SGMeasurement/SGMeasurement.vcxproj.filters
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,75 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ItemGroup>
    <Filter Include="源文件">
      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
      <Extensions>cpp;c;cc;cxx;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="SGMeasurement.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="SGMeasurementDlg.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="Logger.h">
      <Filter>头文件</Filter>
    </ClInclude>
  </ItemGroup>
  <ItemGroup>
    <ClCompile Include="SGMeasurement.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
    <ClCompile Include="SGMeasurementDlg.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
    <ClCompile Include="pch.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
    <ClCompile Include="Logger.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
  </ItemGroup>
  <ItemGroup>
    <ResourceCompile Include="SGMeasurement.rc">
      <Filter>资源文件</Filter>
    </ResourceCompile>
  </ItemGroup>
  <ItemGroup>
    <None Include="res\SGMeasurement.rc2">
      <Filter>资源文件</Filter>
    </None>
  </ItemGroup>
  <ItemGroup>
    <Image Include="res\SGMeasurement.ico">
      <Filter>资源文件</Filter>
    </Image>
    <Image Include="res\menu_restore.ico">
      <Filter>资源文件</Filter>
    </Image>
    <Image Include="res\menu_close.ico">
      <Filter>资源文件</Filter>
    </Image>
  </ItemGroup>
</Project>
SourceCode/Bond/SGMeasurement/SGMeasurement.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>SGMeasurement.rc</RESOURCE_FILE>
  </PropertyGroup>
</Project>
SourceCode/Bond/SGMeasurement/SGMeasurementDlg.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,1150 @@

// SGMeasurementDlg.cpp: å®žçŽ°æ–‡ä»¶
//
#include "pch.h"
#include "framework.h"
#include "SGMeasurement.h"
#include "SGMeasurementDlg.h"
#include "afxdialogex.h"
#include "SGIF.h"
#include "Logger.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
#define DeviceID 0
// æ‰˜ç›˜å›¾æ ‡ ID ä¸Žæ¶ˆæ¯å®
#define ID_TRAY_RESTORE           2001                // æ¢å¤çª—口
#define ID_TRAY_EXIT           2002                // é€€å‡ºç¨‹åº
#define WM_TRAY_ICON_NOTIFY    (WM_USER + 1000) // æ‰˜ç›˜å›¾æ ‡å›žè°ƒæ¶ˆæ¯ ID
// æ‰˜ç›˜æç¤ºæ–‡æœ¬å®
#define TRAY_ICON_TOOLTIP_TEXT  _T("SGMeasurement")
// æ—¥å¿—颜色宏定义
#define LOG_COLOR_NORMAL   RGB(0, 0, 0)         // æ™®é€šï¼šé»‘色
#define LOG_COLOR_SUCCESS  RGB(0, 128, 0)       // æˆåŠŸï¼šç»¿è‰²
#define LOG_COLOR_ERROR    RGB(255, 0, 0)       // é”™è¯¯ï¼šçº¢è‰²
#define LOG_COLOR_WARNING  RGB(255, 165, 0)     // è­¦å‘Šï¼šæ©™è‰²
#define LOG_COLOR_TIME     RGB(0, 0, 255)       // æ—¶é—´æˆ³ï¼šè“è‰²
// å®šæ—¶å™¨ç›¸å…³å®å®šä¹‰
#define TIMER_INTERVAL_MS        500
#define TIMER_ID_OUTPUT_UPDATE    1
// è®¡æ—¶å®å®šä¹‰
#define MEASURE_FUNC_START() \
    clock_t __startClock = clock();
#define MEASURE_FUNC_END() \
    do { \
        clock_t __endClock = clock(); \
        double __elapsedMs = 1000.0 * (__endClock - __startClock) / CLOCKS_PER_SEC; \
        CString __strElapsed; \
        __strElapsed.Format(_T("%s æ‰§è¡Œè€—时:%.1f ms"), _T(__FUNCTION__), __elapsedMs); \
        AppendLogLineRichStyled(__strElapsed, LOG_COLOR_SUCCESS); \
    } while (0)
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()
CSGMeasurementDlg::CSGMeasurementDlg(CWnd* pParent /*=nullptr*/)
    : CDialogEx(IDD_SGMEASUREMENT_DIALOG, pParent)
    , m_bConnected(false)
    , m_bSaving(false)
    , m_dOutValues{ 0.0, 0.0, 0.0, 0.0 }
    , m_nUseTrigger(0)
    , m_nSavePointCount(100000)
    , m_fJumpThreshold(0.2f)
    , m_nJumpWindow(3)
    , m_nValleyMargin(0)
    , m_nMinGlass1Count(10)
    , m_nFixedCount(5)
    , m_fMaxDelta(0.05f)
    , m_nTrayIconID(0)
    , m_bTrayIconCreated(FALSE)
    , m_bExitingFromTray(FALSE)
{
    m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CSGMeasurementDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialogEx::DoDataExchange(pDX);
    DDX_Text(pDX, IDC_EDIT_OUT1, m_dOutValues[0]);
    DDX_Text(pDX, IDC_EDIT_OUT2, m_dOutValues[1]);
    DDX_Text(pDX, IDC_EDIT_OUT3, m_dOutValues[2]);
    DDX_Text(pDX, IDC_EDIT_OUT4, m_dOutValues[3]);
    DDX_Control(pDX, IDC_RICHEDIT_LOG, m_editLog);
    DDX_Check(pDX, IDC_CHECK_USE_TRIGGER, m_nUseTrigger);
    DDX_Control(pDX, IDC_COMBO_OUTPUT_PORT, m_comboOutputPort);
    DDX_Text(pDX, IDC_EDIT_STORE_COUNT, m_nSavePointCount);
    DDX_Text(pDX, IDC_EDIT_JUMP_WINDOW, m_nJumpWindow);
    DDX_Text(pDX, IDC_EDIT_VALLEY_MARGIN, m_nValleyMargin);
    DDX_Text(pDX, IDC_EDIT_MIN_GLASS_COUNT, m_nMinGlass1Count);
    DDX_Text(pDX, IDC_EDIT_FIXED_COUNT, m_nFixedCount);
    DDX_Text(pDX, IDC_EDIT_JUMP_THRESHOLD, m_fJumpThreshold);
    DDX_Text(pDX, IDC_EDIT_MAX_DELTA, m_fMaxDelta);
}
void CSGMeasurementDlg::ExitApplication()
{
    // æ–­å¼€è®¾å¤‡è¿žæŽ¥ï¼ˆå¦‚已连接)
    if (m_bConnected) {
        DisconnectFromDevice();
    }
    // åˆ é™¤æ‰˜ç›˜å›¾æ ‡ï¼ˆå¦‚已添加)
    if (m_bTrayIconCreated) {
        Shell_NotifyIcon(NIM_DELETE, &m_trayIconData);
        m_bTrayIconCreated = FALSE;
    }
    DestroyWindow();
    CDialogEx::OnClose();
}
void CSGMeasurementDlg::UpdateControlStatus(BOOL bConnected, BOOL bStoring/* = FALSE*/)
{
    // è¿žæŽ¥æŒ‰é’®å’Œæ–­å¼€æŒ‰é’®çŠ¶æ€äº’æ–¥
    GetDlgItem(IDC_BUTTON_CONNECT)->EnableWindow(!bConnected);
    GetDlgItem(IDC_BUTTON_DISCONNECT)->EnableWindow(bConnected);
    // IP地址输入只允许在未连接时修改
    GetDlgItem(IDC_IPADDRESS)->EnableWindow(!bConnected);
    // å­˜å‚¨é…ç½®æŽ§ä»¶ä»…在已连接且未开始存储时允许操作
    BOOL bCanConfigure = bConnected && !bStoring;
    /*GetDlgItem(IDC_CHECK_USE_TRIGGER)->EnableWindow(bCanConfigure);*/
    GetDlgItem(IDC_COMBO_OUTPUT_PORT)->EnableWindow(bCanConfigure);
    GetDlgItem(IDC_EDIT_STORE_COUNT)->EnableWindow(bCanConfigure);
    GetDlgItem(IDC_EDIT_JUMP_THRESHOLD)->EnableWindow(bCanConfigure);
    GetDlgItem(IDC_EDIT_JUMP_WINDOW)->EnableWindow(bCanConfigure);
    GetDlgItem(IDC_EDIT_VALLEY_MARGIN)->EnableWindow(bCanConfigure);
    GetDlgItem(IDC_EDIT_MIN_GLASS_COUNT)->EnableWindow(bCanConfigure);
    GetDlgItem(IDC_EDIT_FIXED_COUNT)->EnableWindow(bCanConfigure);
    GetDlgItem(IDC_EDIT_MAX_DELTA)->EnableWindow(bCanConfigure);
    // å­˜å‚¨ç›¸å…³æŒ‰é’®
    GetDlgItem(IDC_BUTTON_RECEIVE_FROM_CTRL)->EnableWindow(bCanConfigure);
    GetDlgItem(IDC_BUTTON_SEND_TO_CTRL)->EnableWindow(bCanConfigure);
    GetDlgItem(IDC_BUTTON_CLEAR_STORE)->EnableWindow(bCanConfigure);
    GetDlgItem(IDC_BUTTON_START_STORE)->EnableWindow(bCanConfigure);
    GetDlgItem(IDC_BUTTON_STOP_STORE)->EnableWindow(bStoring);
}
void CSGMeasurementDlg::AppendLogLineBatchBegin()
{
    m_editLog.SetRedraw(FALSE);
    m_editLog.SetEventMask(0); // é˜²æ­¢è§¦å‘不必要的通知
}
void CSGMeasurementDlg::AppendLogLineBatchEnd()
{
    m_editLog.SetRedraw(TRUE);
    m_editLog.Invalidate();    // å¼ºåˆ¶é‡ç»˜
    m_editLog.SetEventMask(ENM_CHANGE | ENM_SELCHANGE);
}
void CSGMeasurementDlg::TrimRichEditLineLimit(int nMaxLines)
{
    int nLineCount = m_editLog.GetLineCount();
    if (nLineCount < nMaxLines) {
        return;
    }
    // èŽ·å–å¤šä½™è¡Œçš„å­—ç¬¦æ•°èŒƒå›´
    int charIndex = m_editLog.LineIndex(nMaxLines);
    m_editLog.SetSel(0, charIndex); // é€‰ä¸­å¤šä½™å†…容
    m_editLog.ReplaceSel(_T(""));   // åˆ é™¤
}
void CSGMeasurementDlg::AppendLogLineRichStyled(const CString& strContent, COLORREF color /*= RGB(0, 0, 0)*/)
{
    if (!::IsWindow(GetSafeHwnd()) || !::IsWindow(m_editLog.GetSafeHwnd())) {
        return;
    }
    // æ—¶é—´æˆ³
    CString strTimestamp;
    CTime now = CTime::GetCurrentTime();
    strTimestamp.Format(_T("[%02d:%02d:%02d] "), now.GetHour(), now.GetMinute(), now.GetSecond());
    // æ’入点移到最后(也可以设为 0 è¡¨ç¤ºé¡¶éƒ¨ï¼‰
    m_editLog.SetSel(-1, -1);
    // æ’入时间(蓝色)
    CHARFORMAT2 cfTime = {};
    cfTime.cbSize = sizeof(cfTime);
    cfTime.dwMask = CFM_COLOR;
    cfTime.crTextColor = LOG_COLOR_TIME;
    m_editLog.SetSelectionCharFormat(cfTime);
    m_editLog.ReplaceSel(strTimestamp);
    // ç”Ÿæˆæ—¥å¿—级别标签
    CString strLevel;
    if (color == LOG_COLOR_WARNING) {
        strLevel = _T("[警告]");
    }
    else if (color == LOG_COLOR_ERROR) {
        strLevel = _T("[错误]");
    }
    else if (color == LOG_COLOR_NORMAL) {
        strLevel = _T("[信息]");
    }
    else if (color == LOG_COLOR_SUCCESS) {
        strLevel = _T("[成功]");
    }
    else {
        strLevel = _T("[未知]");
    }
    // æ’入日志正文(传入颜色)
    CHARFORMAT2 cfMsg = {};
    cfMsg.cbSize = sizeof(cfMsg);
    cfMsg.dwMask = CFM_COLOR;
    cfMsg.crTextColor = color;
    m_editLog.SetSelectionCharFormat(cfMsg);
    m_editLog.ReplaceSel(strLevel + strContent + _T("\r\n"));
    // é™åˆ¶æœ€å¤§è¡Œæ•°
    TrimRichEditLineLimit(100);
    // æ‹¼æŽ¥å®Œæ•´æ—¥å¿—行
    CString strFullLogLine;
    strFullLogLine.Format(_T("%s %s"), strLevel, strContent);
    // å†™å…¥æ—¥å¿—文件
    // LOG_LINE(strFullLogLine);
}
void CSGMeasurementDlg::HighlightAllMatches(const CString& strSearch, COLORREF clrHighlight/* = RGB(255, 165, 0)*/)
{
    if (strSearch.IsEmpty()) {
        return;
    }
    long nStart = 0;
    long nEnd = m_editLog.GetTextLength();
    FINDTEXTEX ft = { 0 };
    ft.chrg.cpMin = 0;
    ft.chrg.cpMax = nEnd;
    ft.lpstrText = strSearch.GetString();
    // é«˜äº®å‰ä¸æ¸…除全文颜色,避免历史多色混淆
    while (m_editLog.FindText(FR_DOWN, &ft) != -1) {
        m_editLog.SetSel(ft.chrgText.cpMin, ft.chrgText.cpMax);
        CHARFORMAT2 cf = {};
        cf.cbSize = sizeof(cf);
        cf.dwMask = CFM_COLOR;
        cf.crTextColor = clrHighlight;
        m_editLog.SetSelectionCharFormat(cf);
        // ä¸‹æ¬¡æœç´¢ä»ŽåŽé¢å¼€å§‹
        ft.chrg.cpMin = ft.chrgText.cpMax;
    }
    m_editLog.SetSel(-1, 0);
}
void CSGMeasurementDlg::PrintSampleData(int nOutNo, const std::vector<float>& vecBuffer)
{
    int nReceived = static_cast<int>(vecBuffer.size());
    if (vecBuffer.empty() || nReceived < 0) {
        CString strError;
        strError.Format(_T("OUT%d: æŽ¥æ”¶æ•°æ®ä¸ºç©ºæˆ–无效,无法打印。"), nOutNo);
        AppendLogLineRichStyled(strError, LOG_COLOR_WARNING);
        return;
    }
    CString strLine;
    for (int i = 0; i < nReceived; ++i) {
        CString strOne;
        strOne.Format(_T("%10.3f "), vecBuffer[i]);
        strLine += strOne;
        // æ¯ 7 ä¸ªå€¼è¾“出一行
        if ((i + 1) % 7 == 0 || i == nReceived - 1) {
            AppendLogLineRichStyled(strLine, LOG_COLOR_NORMAL);
            strLine.Empty();
        }
    }
}
bool CSGMeasurementDlg::ConnectToDevice()
{
    if (m_bConnected) {
        AppendLogLineRichStyled(_T("设备已连接,请先断开连接。"), LOG_COLOR_WARNING);
        return false;
    }
    SGIF_OPENPARAM_ETHERNET stIpAddress = { 0 };
    CIPAddressCtrl* pIPCtrl = (CIPAddressCtrl*)GetDlgItem(IDC_IPADDRESS);
    if (!::IsWindow(pIPCtrl->GetSafeHwnd())) {
        AppendLogLineRichStyled(_T("IP æŽ§ä»¶æ— æ•ˆï¼Œè¿žæŽ¥å¤±è´¥ï¼"), LOG_COLOR_ERROR);
        return false;
    }
    pIPCtrl->GetAddress(
        stIpAddress.IPAddress.S_un.S_un_b.s_b1,
        stIpAddress.IPAddress.S_un.S_un_b.s_b2,
        stIpAddress.IPAddress.S_un.S_un_b.s_b3,
        stIpAddress.IPAddress.S_un.S_un_b.s_b4
    );
    RC nRet = SGIF_OpenDeviceETHER(DeviceID, &stIpAddress);
    if (nRet == RC_OK) {
        AppendLogLineRichStyled(_T("打开连接成功!"), LOG_COLOR_SUCCESS);
        m_bConnected = TRUE;
        UpdateControlStatus(TRUE, FALSE);
        SetTimer(TIMER_ID_OUTPUT_UPDATE, TIMER_INTERVAL_MS, nullptr);
        return true;
    }
    else {
        CString strError;
        strError.Format(_T("打开连接失败,错误码:%#X"), nRet);
        AppendLogLineRichStyled(strError, LOG_COLOR_ERROR);
        m_bConnected = FALSE;
        UpdateControlStatus(FALSE, FALSE);
        return false;
    }
}
bool CSGMeasurementDlg::DisconnectFromDevice()
{
    if (!m_bConnected) {
        AppendLogLineRichStyled(_T("设备未连接,无需断开。"), LOG_COLOR_WARNING);
        return false;
    }
    // åœæ­¢å®šæ—¶å™¨ï¼Œé¿å…åœ¨æ–­å¼€åŽä»å°è¯•更新输出数据
    KillTimer(TIMER_ID_OUTPUT_UPDATE);
    // å…ˆåœæ­¢æ•°æ®å­˜å‚¨ï¼ˆå¦‚果正在进行)
    RC nRet;
    if (m_bConnected && m_bSaving) {
        nRet = SGIF_DataStorageStop(DeviceID);
        if (nRet == RC_OK) {
            m_bSaving = FALSE;
            AppendLogLineRichStyled(_T("数据存储已停止。"), LOG_COLOR_SUCCESS);
        }
        else {
            CString strError;
            strError.Format(_T("停止数据存储失败,错误码:%#X"), nRet);
            AppendLogLineRichStyled(strError, LOG_COLOR_ERROR);
        }
    }
    // æ–­å¼€è®¾å¤‡è¿žæŽ¥
    nRet = SGIF_CloseDevice(DeviceID);
    if (nRet == RC_OK) {
        AppendLogLineRichStyled(_T("断开连接成功!"), LOG_COLOR_SUCCESS);
        m_bConnected = FALSE;
        UpdateControlStatus(FALSE, FALSE);
        return true;
    }
    else {
        CString strError;
        strError.Format(_T("断开连接失败,错误码:%#X"), nRet);
        AppendLogLineRichStyled(strError, LOG_COLOR_ERROR);
        AppendLogLineRichStyled(_T("保持当前状态,断开失败。"), LOG_COLOR_ERROR);
        UpdateControlStatus(m_bConnected, m_bSaving);
        return false;
    }
}
void CSGMeasurementDlg::CleanInvalidValuesInPlace(int nOutNo, std::vector<float>& vecData, float fInvalid/* = -999.0f*/)
{
    MEASURE_FUNC_START();
    // æ‰¾åˆ°ç¬¬ä¸€ä¸ªæœ‰æ•ˆå€¼
    auto itStart = std::find_if(vecData.begin(), vecData.end(), [=](float v) { return v > fInvalid; });
    // æ‰¾åˆ°æœ€åŽä¸€ä¸ªæœ‰æ•ˆå€¼
    auto itEnd = std::find_if(vecData.rbegin(), vecData.rend(), [=](float v) { return v > fInvalid; }).base();
    // æ£€æŸ¥æ˜¯å¦æœ‰æœ‰æ•ˆæ•°æ®
    if (itStart < itEnd) {
        // å…ˆè£è¾¹
        std::vector<float> vecTrimmed(itStart, itEnd);
        // å†ç§»é™¤ä¸­é—´çš„æ— æ•ˆå€¼
        auto itNewEnd = std::remove_if(vecTrimmed.begin(), vecTrimmed.end(), [=](float v) { return v == fInvalid; });
        vecTrimmed.erase(itNewEnd, vecTrimmed.end());
        vecData = std::move(vecTrimmed);
        CString strLog;
        strLog.Format(_T("OUT%d: å·²è£å‰ªæ— æ•ˆè¾¹ç•Œæ•°æ®ï¼Œå‰©ä½™æœ‰æ•ˆæ•°æ® %d ä¸ªã€‚"), nOutNo, static_cast<int>(vecData.size()));
        AppendLogLineRichStyled(strLog, LOG_COLOR_NORMAL);
        if (vecData.size() < 20) {
            AppendLogLineRichStyled(_T("警告:有效数据量过少,可能影响后续处理。"), LOG_COLOR_WARNING);
        }
        else {
            CString strInfo;
            strInfo.Format(_T("OUT%d: æœ‰æ•ˆæ•°æ®èŒƒå›´ [%f, %f]"), nOutNo, *std::min_element(vecData.begin(), vecData.end()), *std::max_element(vecData.begin(), vecData.end()));
            AppendLogLineRichStyled(strInfo, LOG_COLOR_NORMAL);
        }
        PrintSampleData(nOutNo, vecData);
    }
    else {
        vecData.clear();
    }
    MEASURE_FUNC_END();
}
bool CSGMeasurementDlg::SplitGlassSegments(int nOutNo, const std::vector<float>& vecData, std::vector<float>& vecGlass1, std::vector<float>& vecGlass2, float fJumpThreshold /*= 0.2f*/, int nWindow /*= 3*/, int nValleyMargin /*= 0*/, int nMinGlassCount /*= 10*/)
{
    MEASURE_FUNC_START();
    CString strLog;
    const int nTotal = static_cast<int>(vecData.size());
    if (nTotal < 2 * nWindow + 1 + nMinGlassCount) {
        strLog.Format(_T("OUT%d: æ•°æ®é‡ä¸è¶³ï¼Œè‡³å°‘需要 %d ä¸ªç‚¹æ‰èƒ½åˆ‡å‰²ã€‚"), nOutNo, 2 * nWindow + 1 + nMinGlassCount);
        AppendLogLineRichStyled(strLog, LOG_COLOR_WARNING);
        return false;
    }
    // ä»Žä¸­é—´å‘两边查找 valley å€™é€‰ç‚¹
    int nMid = nTotal / 2;
    int nValleyLeft = -1, nValleyRight = -1;
    // å‘左查找 valley
    for (int i = nMid; i >= nWindow; --i) {
        float fDelta = std::fabs(vecData[i] - vecData[i - nWindow]);
        if (fDelta > fJumpThreshold &&
            vecData[i] < vecData[i - 1] &&
            vecData[i] < vecData[i + 1]) {
            nValleyLeft = i;
            break;
        }
    }
    // å‘右查找 valley
    for (int i = nMid; i <= nTotal - nWindow - 2; ++i) {
        float fDelta = std::fabs(vecData[i + nWindow] - vecData[i]);
        if (fDelta > fJumpThreshold &&
            vecData[i] < vecData[i - 1] &&
            vecData[i] < vecData[i + 1]) {
            nValleyRight = i;
            break;
        }
    }
    // é€‰å®š valley ç‚¹
    int nValleyIdx = -1;
    if (nValleyLeft > 0 && nValleyRight > 0) {
        nValleyIdx = (vecData[nValleyLeft] < vecData[nValleyRight]) ? nValleyLeft : nValleyRight;
    }
    else if (nValleyLeft > 0) {
        nValleyIdx = nValleyLeft;
    }
    else if (nValleyRight > 0) {
        nValleyIdx = nValleyRight;
    }
    // fallback: valley æœªæ‰¾åˆ°ï¼Œä½¿ç”¨ä¸­é—´åˆ‡å‰²æ³•
    if (nValleyIdx < 0) {
        AppendLogLineRichStyled(_T("未找到 valley è·³å˜ç‚¹ï¼Œä½¿ç”¨ä¸­é—´ä½ç½®åˆ‡å‰²ã€‚"), LOG_COLOR_WARNING);
        nValleyIdx = nMid;
    }
    // åº”用切割位置,限制边界
    int nCutPos = max(1, min(nTotal - 1, nValleyIdx + nValleyMargin));
    vecGlass1.assign(vecData.begin(), vecData.begin() + nCutPos);
    vecGlass2.assign(vecData.begin() + nCutPos, vecData.end());
    int nGlass1Count = static_cast<int>(vecGlass1.size());
    int nGlass2Count = static_cast<int>(vecGlass2.size());
    // æ—¥å¿—输出
    strLog.Format(_T("OUT%d: åˆ‡å‰²æˆåŠŸï¼Œç¬¬ä¸€ç‰‡çŽ»ç’ƒ %d ç‚¹ï¼Œç¬¬äºŒç‰‡çŽ»ç’ƒ %d ç‚¹ã€‚"), nOutNo, nGlass1Count, nGlass2Count);
    AppendLogLineRichStyled(strLog, LOG_COLOR_SUCCESS);
    if (nGlass1Count < nMinGlassCount) {
        strLog.Format(_T("OUT%d: ç¬¬ä¸€ç‰‡çŽ»ç’ƒæ•°æ®é‡å°‘äºŽ %d ç‚¹ï¼Œå¯èƒ½å½±å“è®¡ç®—。"), nOutNo, nMinGlassCount);
        AppendLogLineRichStyled(strLog, LOG_COLOR_WARNING);
    }
    if (nGlass2Count < nMinGlassCount) {
        strLog.Format(_T("OUT%d: ç¬¬äºŒç‰‡çŽ»ç’ƒæ•°æ®é‡å°‘äºŽ %d ç‚¹ï¼Œå¯èƒ½å½±å“è®¡ç®—。"), nOutNo, nMinGlassCount);
        AppendLogLineRichStyled(strLog, LOG_COLOR_WARNING);
    }
    AppendLogLineRichStyled(_T("第一片玻璃数据:"), LOG_COLOR_NORMAL);
    PrintSampleData(nOutNo, vecGlass1);
    AppendLogLineRichStyled(_T("第二片玻璃数据:"), LOG_COLOR_NORMAL);
    PrintSampleData(nOutNo, vecGlass2);
    MEASURE_FUNC_END();
    return true;
}
bool CSGMeasurementDlg::FilterDominantGroup(int nOutNo, const std::vector<float>& vecInput, std::vector<float>& vecOutput)
{
    MEASURE_FUNC_START();
    if (vecInput.empty()) {
        AppendLogLineRichStyled(_T("输入数据为空,无法进行分组筛选。"), LOG_COLOR_WARNING);
        return false;
    }
    // åˆ†ç»„:map<int整数部分, vector<float>>
    std::map<int, std::vector<float>> mapGroup;
    for (float fVal : vecInput) {
        int nKey = static_cast<int>(fVal);
        mapGroup[nKey].push_back(fVal);
    }
    // æ‰¾å‡ºæ•°é‡æœ€å¤šçš„那组
    size_t nMaxCount = 0;
    auto itMaxGroup = mapGroup.begin();
    for (auto it = mapGroup.begin(); it != mapGroup.end(); ++it) {
        if (it->second.size() > nMaxCount) {
            nMaxCount = it->second.size();
            itMaxGroup = it;
        }
    }
    if (nMaxCount == 0) {
        AppendLogLineRichStyled(_T("所有数据都被过滤或为空,无法筛选出主要分组。"), LOG_COLOR_WARNING);
        return false;
    }
    vecOutput = itMaxGroup->second;
    CString strLog;
    strLog.Format(_T("成功从 %d ä¸ªç»„中筛选出主要分组:值约为 %d,共 %zu ä¸ªç‚¹ã€‚"), static_cast<int>(mapGroup.size()), itMaxGroup->first, nMaxCount);
    AppendLogLineRichStyled(strLog, LOG_COLOR_SUCCESS);
    // æ‰“印筛选后的数据
    AppendLogLineRichStyled(_T("筛选后的主要分组数据:"), LOG_COLOR_NORMAL);
    PrintSampleData(nOutNo, vecOutput);
    MEASURE_FUNC_END();
    return true;
}
bool CSGMeasurementDlg::ExtractStableRegionFixed(int nOutNo, const std::vector<float>& vecIn, std::vector<float>& vecOut, int nFixedCount/* = 5*/, float fMaxDelta/* = 0.04f*/)
{
    MEASURE_FUNC_START();
    const int n = static_cast<int>(vecIn.size());
    if (n < nFixedCount) {
        CString strError;
        strError.Format(_T("OUT%d: æ•°æ®é‡ä¸è¶³ï¼Œè‡³å°‘需要 %d ä¸ªç‚¹æ‰èƒ½æå–稳定区。"), nOutNo, nFixedCount);
        return false;
    }
    int nBestStart = -1;
    float fBestRange = FLT_MAX;
    for (int i = 0; i <= n - nFixedCount; ++i) {
        auto first = vecIn.begin() + i;
        auto last = first + nFixedCount;
        float fMinVal = *std::min_element(first, last);
        float fMaxVal = *std::max_element(first, last);
        float fRange = fMaxVal - fMinVal;
        if (fRange <= fMaxDelta && fRange < fBestRange) {
            fBestRange = fRange;
            nBestStart = i;
        }
    }
    if (nBestStart < 0) {
        return false;
    }
    vecOut.assign(vecIn.begin() + nBestStart, vecIn.begin() + nBestStart + nFixedCount);
    CString strLog;
    strLog.Format(_T("OUT%d: æå–稳定区成功,起始点索引 %d,范围 %.3f。"), nOutNo, nBestStart, fBestRange);
    AppendLogLineRichStyled(strLog, LOG_COLOR_SUCCESS);
    if (vecOut.size() < nFixedCount) {
        CString strWarning;
        strWarning.Format(_T("OUT%d: æå–的稳定区数据量不足,可能影响后续处理。"), nOutNo);
        AppendLogLineRichStyled(strWarning, LOG_COLOR_WARNING);
    }
    // æ‰“印提取的稳定区数据
    AppendLogLineRichStyled(_T("提取的稳定区数据:"), LOG_COLOR_NORMAL);
    PrintSampleData(nOutNo, vecOut);
    MEASURE_FUNC_END();
    return true;
}
bool CSGMeasurementDlg::CalcGlassOffset(const std::vector<float>& vecGlass1, const std::vector<float>& vecGlass2, float& fAvg1, float& fAvg2, float& fOffset)
{
    MEASURE_FUNC_START();
    if (vecGlass1.empty() || vecGlass2.empty()) {
        AppendLogLineRichStyled(_T("稳定区数据为空,无法计算平均值和偏移。"), LOG_COLOR_WARNING);
        return false;
    }
    auto CalcAverage = [](const std::vector<float>& data) -> float {
        float sum = std::accumulate(data.begin(), data.end(), 0.0f);
        return sum / static_cast<float>(data.size());
    };
    fAvg1 = CalcAverage(vecGlass1);
    fAvg2 = CalcAverage(vecGlass2);
    fOffset = std::fabs(fAvg2 - fAvg1);  // ç¬¬äºŒç‰‡ - ç¬¬ä¸€ç‰‡
    CString strLog;
    strLog.Format(_T("第一片玻璃平均值: %.3f,第二片玻璃平均值: %.3f,偏移量: %.3f"), fAvg1, fAvg2, fOffset);
    AppendLogLineRichStyled(strLog, LOG_COLOR_SUCCESS);
    MEASURE_FUNC_END();
    return true;
}
bool CSGMeasurementDlg::InitDataStorage()
{
    if (!m_bConnected) {
        AppendLogLineRichStyled(_T("设备未连接,请先连接设备。"), LOG_COLOR_WARNING);
        return false;
    }
    if (m_bSaving) {
        AppendLogLineRichStyled(_T("数据存储正在进行中,请先停止存储。"), LOG_COLOR_WARNING);
        return false;
    }
    RC nRet = SGIF_DataStorageInit(DeviceID);
    if (nRet == RC_OK) {
        AppendLogLineRichStyled(_T("数据存储已清除。"), LOG_COLOR_SUCCESS);
        return true;
    }
    CString strError;
    strError.Format(_T("清除数据存储失败,错误码:%#X"), nRet);
    AppendLogLineRichStyled(strError, LOG_COLOR_ERROR);
    return false;
}
bool CSGMeasurementDlg::StartDataStorage()
{
    if (m_bSaving) {
        AppendLogLineRichStyled(_T("数据存储已在进行中,请先停止存储。"), LOG_COLOR_WARNING);
        return false;
    }
    RC nRet = SGIF_DataStorageStart(DeviceID);
    if (nRet == RC_OK) {
        m_bSaving = TRUE;
        AppendLogLineRichStyled(_T("数据存储已开始。"), LOG_COLOR_SUCCESS);
        return true;
    }
    CString strError;
    strError.Format(_T("开始数据存储失败,错误码:%#X"), nRet);
    AppendLogLineRichStyled(strError, LOG_COLOR_ERROR);
    return false;
}
bool CSGMeasurementDlg::StopDataStorage()
{
    if (!m_bSaving) {
        AppendLogLineRichStyled(_T("数据存储未在进行中,请先开始存储。"), LOG_COLOR_WARNING);
        return false;
    }
    RC nRet = SGIF_DataStorageStop(DeviceID);
    if (nRet == RC_OK) {
        m_bSaving = FALSE;
        AppendLogLineRichStyled(_T("数据存储已停止。"), LOG_COLOR_SUCCESS);
        return true;
    }
    CString strError;
    strError.Format(_T("停止数据存储失败,错误码:%#X"), nRet);
    AppendLogLineRichStyled(strError, LOG_COLOR_ERROR);
    return false;
}
float CSGMeasurementDlg::AnalyzeStoredData(int nOutNo)
{
    MEASURE_FUNC_START();
    UpdateData(TRUE);
    if (m_nUseTrigger) {
        UpdateControlStatus(m_bConnected, m_bSaving);
        AfxMessageBox(_T("当前是硬触发模式,请检查触发器状态。"), MB_ICONINFORMATION);
        return -1.0f;
    }
    if (!m_bConnected) {
        AppendLogLineRichStyled(_T("设备未连接,请先连接设备。"), LOG_COLOR_WARNING);
        return -1.0f;
    }
    if (m_bSaving) {
        AppendLogLineRichStyled(_T("数据存储正在进行中,请先停止存储。"), LOG_COLOR_WARNING);
        return -1.0f;
    }
    if (nOutNo < 1 || nOutNo > 4) {
        AppendLogLineRichStyled(_T("输出端口编号无效,必须在 1 åˆ° 4 ä¹‹é—´ã€‚"), LOG_COLOR_ERROR);
        return -1.0f;
    }
    if (m_nSavePointCount < 0) {
        AppendLogLineRichStyled(_T("数据点数必须大于 0。"), LOG_COLOR_ERROR);
        return -1.0f;
    }
    std::vector<float> vecBuffer(m_nSavePointCount, 0.0f);
    int nReceived = 0;
    RC nRet = SGIF_DataStorageGetData(DeviceID, nOutNo, m_nSavePointCount, vecBuffer.data(), &nReceived);
    if (nRet != RC_OK) {
        CString strError;
        strError.Format(_T("读取 OUT%d æ•°æ®å¤±è´¥ï¼Œé”™è¯¯ç ï¼š%#X"), nOutNo, nRet);
        AppendLogLineRichStyled(strError, LOG_COLOR_ERROR);
        return -1.0f;
    }
    vecBuffer.resize(nReceived);
    CleanInvalidValuesInPlace(nOutNo, vecBuffer);
    std::vector<float> vecGlass1, vecGlass2;
    if (!SplitGlassSegments(nOutNo, vecBuffer, vecGlass1, vecGlass2, m_fJumpThreshold, m_nJumpWindow, m_nValleyMargin, m_nMinGlass1Count)) {
        AppendLogLineRichStyled(_T("未能识别出两片玻璃的数据。"), LOG_COLOR_WARNING);
        return -1.0f;
    }
    std::vector<float> vecGlass1Filtered, vecGlass2Filtered;
    bool bGlass1Filtered = FilterDominantGroup(nOutNo, vecGlass1, vecGlass1Filtered);
    bool bGlass2Filtered = FilterDominantGroup(nOutNo, vecGlass2, vecGlass2Filtered);
    if (!bGlass1Filtered) {
        AppendLogLineRichStyled(_T("Glass1 åˆ†æ®µä¸­æœªèƒ½è¯†åˆ«å‡ºä¸»æ•°æ®ç»„,使用原始数据。"), LOG_COLOR_WARNING);
        vecGlass1Filtered = vecGlass1;
    }
    else {
        AppendLogLineRichStyled(_T("Glass1 ä¸»æ•°æ®ç»„已提取。"), LOG_COLOR_SUCCESS);
    }
    if (!bGlass2Filtered) {
        AppendLogLineRichStyled(_T("Glass2 åˆ†æ®µä¸­æœªèƒ½è¯†åˆ«å‡ºä¸»æ•°æ®ç»„,使用原始数据。"), LOG_COLOR_WARNING);
        vecGlass2Filtered = vecGlass2;
    }
    else {
        AppendLogLineRichStyled(_T("Glass2 ä¸»æ•°æ®ç»„已提取。"), LOG_COLOR_SUCCESS);
    }
    std::vector<float> vecStable1, vecStable2;
    bool bStable1 = ExtractStableRegionFixed(nOutNo, vecGlass1Filtered, vecStable1, m_nFixedCount, m_fMaxDelta);
    bool bStable2 = ExtractStableRegionFixed(nOutNo, vecGlass2Filtered, vecStable2, m_nFixedCount, m_fMaxDelta);
    float fAvg1 = 0.0f, fAvg2 = 0.0f, fOffset = 0.0f;
    if (bStable1 && bStable2) {
        AppendLogLineRichStyled(_T("成功提取到两片玻璃的稳定区数据。"), LOG_COLOR_SUCCESS);
        CalcGlassOffset(vecStable1, vecStable2, fAvg1, fAvg2, fOffset);
    }
    else {
        AppendLogLineRichStyled(_T("未能提取到稳定区数据,尝试使用原始分段数据计算偏移。"), LOG_COLOR_WARNING);
        CalcGlassOffset(vecGlass1, vecGlass2, fAvg1, fAvg2, fOffset);
    }
    MEASURE_FUNC_END();
    return fOffset;
}
BEGIN_MESSAGE_MAP(CSGMeasurementDlg, CDialogEx)
    ON_WM_SYSCOMMAND()
    ON_WM_PAINT()
    ON_WM_QUERYDRAGICON()
    ON_WM_TIMER()
    ON_WM_MEASUREITEM()
    ON_WM_DRAWITEM()
    ON_WM_CLOSE()
    ON_MESSAGE(WM_TRAY_ICON_NOTIFY, &CSGMeasurementDlg::OnTrayIconClick)
    ON_COMMAND(ID_TRAY_RESTORE, &CSGMeasurementDlg::OnTrayRestore)
    ON_COMMAND(ID_TRAY_EXIT, &CSGMeasurementDlg::OnTrayExit)
    ON_BN_CLICKED(IDC_BUTTON_CONNECT, &CSGMeasurementDlg::OnBnClickedButtonConnect)
    ON_BN_CLICKED(IDC_BUTTON_DISCONNECT, &CSGMeasurementDlg::OnBnClickedButtonDisconnect)
    ON_BN_CLICKED(IDC_BUTTON_RECEIVE_FROM_CTRL, &CSGMeasurementDlg::OnBnClickedButtonReceiveFromCtrl)
    ON_BN_CLICKED(IDC_BUTTON_SEND_TO_CTRL, &CSGMeasurementDlg::OnBnClickedButtonSendToCtrl)
    ON_BN_CLICKED(IDC_BUTTON_CLEAR_STORE, &CSGMeasurementDlg::OnBnClickedButtonClearStore)
    ON_BN_CLICKED(IDC_BUTTON_START_STORE, &CSGMeasurementDlg::OnBnClickedButtonStartStore)
    ON_BN_CLICKED(IDC_BUTTON_STOP_STORE, &CSGMeasurementDlg::OnBnClickedButtonStopStore)
    ON_BN_CLICKED(IDC_BUTTON_CLEAR_LOG, &CSGMeasurementDlg::OnBnClickedButtonClearLog)
END_MESSAGE_MAP()
BOOL CSGMeasurementDlg::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);        // è®¾ç½®å°å›¾æ ‡
    // TODO: åœ¨æ­¤æ·»åŠ é¢å¤–çš„åˆå§‹åŒ–ä»£ç 
    UpdateData(FALSE);
    UpdateControlStatus(FALSE, FALSE);
    // æ‰˜ç›˜å›¾æ ‡åˆå§‹åŒ–
    m_trayIconData.cbSize = sizeof(NOTIFYICONDATA);                  // è®¾ç½®æ‰˜ç›˜å›¾æ ‡æ•°æ®ç»“构的大小
    m_trayIconData.hWnd = m_hWnd;                                    // è®¾ç½®çª—口句柄
    m_trayIconData.uID = m_nTrayIconID;                              // è®¾ç½®æ‰˜ç›˜å›¾æ ‡ ID
    m_trayIconData.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;          // è®¾ç½®æ‰˜ç›˜å›¾æ ‡çš„æ ‡å¿—(图标、消息、提示文本)
    m_trayIconData.uCallbackMessage = WM_TRAY_ICON_NOTIFY;           // è®¾ç½®å›žè°ƒæ¶ˆæ¯ WM_TRAY_ICON_NOTIFY
    m_trayIconData.hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);      // åŠ è½½æ‰˜ç›˜å›¾æ ‡
    lstrcpy(m_trayIconData.szTip, TRAY_ICON_TOOLTIP_TEXT);           // è®¾ç½®æ‰˜ç›˜æç¤ºæ–‡æœ¬
    // æ·»åŠ æ‰˜ç›˜å›¾æ ‡
    Shell_NotifyIcon(NIM_ADD, &m_trayIconData);
    m_bTrayIconCreated = TRUE;
    for (int i = 0; i < 4; i++) {
        CString str;
        str.Format(_T("OUT%d"), i + 1);
        m_comboOutputPort.AddString(str);
    }
    m_comboOutputPort.SetCurSel(0);
    // åˆå§‹åŒ–IP地址控件,设置为默认IP地址
    ((CIPAddressCtrl*)GetDlgItem(IDC_IPADDRESS))->SetAddress(192, 168, 0, 10);
    // åˆå§‹åŒ–日志框
    AppendLogLineRichStyled(_T("准备就绪..."), LOG_COLOR_SUCCESS);
    return TRUE;  // é™¤éžå°†ç„¦ç‚¹è®¾ç½®åˆ°æŽ§ä»¶ï¼Œå¦åˆ™è¿”回 TRUE
}
void CSGMeasurementDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
    if ((nID & 0xFFF0) == IDM_ABOUTBOX)
    {
        CAboutDlg dlgAbout;
        dlgAbout.DoModal();
    }
    else
    {
        CDialogEx::OnSysCommand(nID, lParam);
    }
}
void CSGMeasurementDlg::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 CSGMeasurementDlg::OnQueryDragIcon()
{
    return static_cast<HCURSOR>(m_hIcon);
}
void CSGMeasurementDlg::OnTimer(UINT_PTR nIDEvent)
{
    // TODO: åœ¨æ­¤æ·»åŠ æ¶ˆæ¯å¤„ç†ç¨‹åºä»£ç å’Œ/或调用默认值
    if (nIDEvent == TIMER_ID_OUTPUT_UPDATE) {
        SGIF_FLOATVALUE_OUT value[4] = { 0 };
        RC nRet = SGIF_GetCalcDataALL(DeviceID, value);
        if (nRet == RC_OK) {
            for (int i = 0; i < 4; ++i) {
                m_dOutValues[i] = value[i].Value;
            }
            // æ›´æ–°ç»‘定控件
            UpdateData(FALSE);
        }
        else {
            CString strError;
            strError.Format(_T("获取测量值失败,错误码:%#X"), nRet);
            AppendLogLineRichStyled(strError, LOG_COLOR_ERROR);
            // æ–­å¼€è¿žæŽ¥
            if (m_bConnected) {
                DisconnectFromDevice();
            }
        }
    }
    CDialogEx::OnTimer(nIDEvent);
}
void CSGMeasurementDlg::OnMeasureItem(int nIDCtl, LPMEASUREITEMSTRUCT lpMeasureItemStruct)
{
    if (lpMeasureItemStruct->CtlType == ODT_MENU) {
        lpMeasureItemStruct->itemHeight = 24;
        lpMeasureItemStruct->itemWidth = 140;
    }
}
void CSGMeasurementDlg::OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct)
{
    if (lpDrawItemStruct->CtlType != ODT_MENU) {
        return;
    }
    CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
    CRect rc = lpDrawItemStruct->rcItem;
    UINT id = lpDrawItemStruct->itemID;
    // èƒŒæ™¯
    COLORREF bgColor = (lpDrawItemStruct->itemState & ODS_SELECTED) ? RGB(200, 220, 255) : RGB(255, 255, 255);
    pDC->FillSolidRect(rc, bgColor);
    // å›¾æ ‡
    HICON hIcon = nullptr;
    if (id == ID_TRAY_RESTORE) {
        hIcon = AfxGetApp()->LoadIcon(IDI_ICON_RESTORE);
    }
    if (id == ID_TRAY_EXIT) {
        hIcon = AfxGetApp()->LoadIcon(IDI_ICON_EXIT);
    }
    if (hIcon) {
        DrawIconEx(pDC->GetSafeHdc(), rc.left + 4, rc.top + 4, hIcon, 16, 16, 0, NULL, DI_NORMAL);
    }
    // æ–‡æœ¬
    CString str;
    if (id == ID_TRAY_RESTORE) {
        str = _T("恢复界面");
    }
    if (id == ID_TRAY_EXIT) {
        str = _T("退出程序");
    }
    pDC->SetBkMode(TRANSPARENT);
    pDC->SetTextColor(RGB(0, 0, 0));
    pDC->DrawText(str, CRect(rc.left + 28, rc.top, rc.right, rc.bottom), DT_SINGLELINE | DT_VCENTER | DT_LEFT);
}
void CSGMeasurementDlg::OnClose()
{
    // TODO: åœ¨æ­¤æ·»åŠ æ¶ˆæ¯å¤„ç†ç¨‹åºä»£ç å’Œ/或调用默认值
    if (m_bExitingFromTray) {
        // ä»Žæ‰˜ç›˜é€€å‡ºæµç¨‹
        ExitApplication();
    }
    else {
        // æ­£å¸¸å…³é—­æŒ‰é’®
        int nResult = AfxMessageBox(_T("是否最小化到托盘?"), MB_YESNO | MB_ICONQUESTION);
        if (nResult == IDYES) {
            ShowWindow(SW_HIDE);
        }
        else {
            ExitApplication();
        }
    }
}
LRESULT CSGMeasurementDlg::OnTrayIconClick(WPARAM wParam, LPARAM lParam) {
    if (wParam == m_nTrayIconID) {
        if (LOWORD(lParam) == WM_LBUTTONUP) {
            // å·¦é”®ç‚¹å‡»æ¢å¤çª—口
            ShowWindow(SW_SHOW);
            SetForegroundWindow();
        }
        else if (LOWORD(lParam) == WM_RBUTTONUP) {
            // å³é”®ç‚¹å‡»å¼¹å‡ºèœå•
            CMenu menu;
            menu.CreatePopupMenu();
            menu.AppendMenu(MF_OWNERDRAW, ID_TRAY_RESTORE, (LPCTSTR)ID_TRAY_RESTORE);
            menu.AppendMenu(MF_OWNERDRAW, ID_TRAY_EXIT, (LPCTSTR)ID_TRAY_EXIT);
            // åŠ è½½å›¾æ ‡
            HICON hIconRestore = (HICON)::LoadImage(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDI_ICON_RESTORE), IMAGE_ICON, 16, 16, LR_SHARED);
            HICON hIconExit = (HICON)::LoadImage(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDI_ICON_EXIT), IMAGE_ICON, 16, 16, LR_SHARED);
            // è®¾ç½®å›¾æ ‡åˆ°èœå•项
            MENUITEMINFO mii = { sizeof(MENUITEMINFO) };
            mii.fMask = MIIM_BITMAP;
            // æ¢å¤èœå•项图标
            mii.hbmpItem = HBMMENU_CALLBACK;
            menu.SetMenuItemInfo(ID_TRAY_RESTORE, &mii);
            // é€€å‡ºèœå•项图标
            mii.hbmpItem = HBMMENU_CALLBACK;
            menu.SetMenuItemInfo(ID_TRAY_EXIT, &mii);
            // èŽ·å–é¼ æ ‡å½“å‰ä½ç½®ï¼Œå¹¶æ˜¾ç¤ºèœå•
            POINT pt;
            GetCursorPos(&pt);
            SetForegroundWindow();
            menu.TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, pt.x, pt.y, this);
        }
    }
    return 0;
}
void CSGMeasurementDlg::OnTrayRestore()
{
    ShowWindow(SW_SHOW);      // æ¢å¤çª—口
    SetForegroundWindow();  // å°†çª—口置于前端
}
void CSGMeasurementDlg::OnTrayExit()
{
    // ä»Žæ‰˜ç›˜å›¾æ ‡èœå•选择“退出程序”
    if (AfxMessageBox(_T("确定要退出程序吗?"), MB_YESNO | MB_ICONQUESTION) == IDYES) {
        m_bExitingFromTray = TRUE;
        PostMessage(WM_CLOSE);
    }
}
void CSGMeasurementDlg::OnBnClickedButtonConnect()
{
    // TODO: åœ¨æ­¤æ·»åŠ æŽ§ä»¶é€šçŸ¥å¤„ç†ç¨‹åºä»£ç 
    ConnectToDevice();
}
void CSGMeasurementDlg::OnBnClickedButtonDisconnect()
{
    // TODO: åœ¨æ­¤æ·»åŠ æŽ§ä»¶é€šçŸ¥å¤„ç†ç¨‹åºä»£ç 
    DisconnectFromDevice();
}
void CSGMeasurementDlg::OnBnClickedButtonReceiveFromCtrl()
{
    // TODO: åœ¨æ­¤æ·»åŠ æŽ§ä»¶é€šçŸ¥å¤„ç†ç¨‹åºä»£ç 
    if (!m_bConnected) {
        AppendLogLineRichStyled(_T("设备未连接,请先连接设备。"), LOG_COLOR_WARNING);
        return;
    }
}
void CSGMeasurementDlg::OnBnClickedButtonSendToCtrl()
{
    // TODO: åœ¨æ­¤æ·»åŠ æŽ§ä»¶é€šçŸ¥å¤„ç†ç¨‹åºä»£ç 
    if (!m_bConnected) {
        AppendLogLineRichStyled(_T("设备未连接,请先连接设备。"), LOG_COLOR_WARNING);
        return;
    }
}
void CSGMeasurementDlg::OnBnClickedButtonClearStore()
{
    // TODO: åœ¨æ­¤æ·»åŠ æŽ§ä»¶é€šçŸ¥å¤„ç†ç¨‹åºä»£ç 
    InitDataStorage();
}
void CSGMeasurementDlg::OnBnClickedButtonStartStore()
{
    // TODO: åœ¨æ­¤æ·»åŠ æŽ§ä»¶é€šçŸ¥å¤„ç†ç¨‹åºä»£ç 
    StartDataStorage();
    UpdateControlStatus(m_bConnected, m_bSaving);
}
void CSGMeasurementDlg::OnBnClickedButtonStopStore()
{
    // TODO: åœ¨æ­¤æ·»åŠ æŽ§ä»¶é€šçŸ¥å¤„ç†ç¨‹åºä»£ç 
    StopDataStorage();
    UpdateControlStatus(m_bConnected, m_bSaving);
    int nSel = m_comboOutputPort.GetCurSel();
    if (CB_ERR == nSel) {
        AppendLogLineRichStyled(_T("请选择一个有效的输出端口。"), LOG_COLOR_WARNING);
        return;
    }
    int nOutNo = nSel + 1;
    AnalyzeStoredData(nOutNo);
}
void CSGMeasurementDlg::OnBnClickedButtonClearLog()
{
    // TODO: åœ¨æ­¤æ·»åŠ æŽ§ä»¶é€šçŸ¥å¤„ç†ç¨‹åºä»£ç 
    if (::IsWindow(m_editLog.GetSafeHwnd())) {
        m_editLog.SetWindowText(_T(""));
    }
}
SourceCode/Bond/SGMeasurement/SGMeasurementDlg.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,333 @@

// SGMeasurementDlg.h: å¤´æ–‡ä»¶
//
#pragma once
#include <map>
#include <vector>
#include <numeric>
#include <algorithm>
// CSGMeasurementDlg å¯¹è¯æ¡†
class CSGMeasurementDlg : public CDialogEx
{
// æž„造
public:
    CSGMeasurementDlg(CWnd* pParent = nullptr);    // æ ‡å‡†æž„造函数
// å¯¹è¯æ¡†æ•°æ®
#ifdef AFX_DESIGN_TIME
    enum { IDD = IDD_SGMEASUREMENT_DIALOG };
#endif
    protected:
    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV æ”¯æŒ
// å®žçް
protected:
    HICON m_hIcon;
    // ç”Ÿæˆçš„æ¶ˆæ¯æ˜ å°„函数
    virtual BOOL OnInitDialog();
    afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
    afx_msg void OnPaint();
    afx_msg HCURSOR OnQueryDragIcon();
    afx_msg void OnTimer(UINT_PTR nIDEvent);
    afx_msg void OnMeasureItem(int nIDCtl, LPMEASUREITEMSTRUCT lpMeasureItemStruct);
    afx_msg void OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct);
    afx_msg void OnClose();
    afx_msg LRESULT OnTrayIconClick(WPARAM wParam, LPARAM lParam);
    afx_msg void OnTrayRestore();
    afx_msg void OnTrayExit();
    afx_msg void OnBnClickedButtonConnect();
    afx_msg void OnBnClickedButtonDisconnect();
    afx_msg void OnBnClickedButtonReceiveFromCtrl();
    afx_msg void OnBnClickedButtonSendToCtrl();
    afx_msg void OnBnClickedButtonClearStore();
    afx_msg void OnBnClickedButtonStartStore();
    afx_msg void OnBnClickedButtonStopStore();
    afx_msg void OnBnClickedButtonClearLog();
    DECLARE_MESSAGE_MAP()
private:
    /**
     * @brief é€€å‡ºç¨‹åºæ—¶çš„æ¸…理操作。
     *
     * æ­¤å‡½æ•°åœ¨ç¨‹åºé€€å‡ºå‰è¢«è°ƒç”¨ï¼Œç”¨äºŽæ‰§è¡Œå¿…要的资源释放与状态恢复,
     * åŒ…括断开设备连接、移除托盘图标等。
     * æœ€ç»ˆé”€æ¯ä¸»çª—口并退出应用。
     */
    void ExitApplication();
    /**
     * @brief æ›´æ–°ç•Œé¢æŽ§ä»¶çš„可用状态。
     *
     * æ ¹æ®è®¾å¤‡è¿žæŽ¥çŠ¶æ€ `bConnected` å’Œå­˜å‚¨çŠ¶æ€ `bStoring` åŠ¨æ€æŽ§åˆ¶ç•Œé¢ä¸ŠæŒ‰é’®ã€
     * ç¼–辑框、下拉框等控件的可用/禁用状态。
     *
     * @param bConnected è®¾å¤‡å½“前是否已连接,TRUE è¡¨ç¤ºå·²è¿žæŽ¥ï¼ŒFALSE è¡¨ç¤ºæœªè¿žæŽ¥ã€‚
     * @param bStoring å½“前是否正在进行数据存储,TRUE è¡¨ç¤ºæ­£åœ¨å­˜å‚¨ã€‚
     */
    void UpdateControlStatus(BOOL bConnected, BOOL bStoring = FALSE);
    /**
     * @brief å¯åŠ¨æ‰¹é‡æ—¥å¿—è¿½åŠ ï¼Œæš‚åœè‡ªåŠ¨æ»šåŠ¨ï¼Œæé«˜æ€§èƒ½ã€‚
     */
    void AppendLogLineBatchBegin();
    /**
     * @brief ç»“束批量日志追加,恢复自动滚动并刷新显示。
     */
    void AppendLogLineBatchEnd();
    /**
     * @brief é™åˆ¶å¯Œæ–‡æœ¬æ¡†ä¸­çš„æœ€å¤§è¡Œæ•°ï¼Œé¿å…æ—¥å¿—过多导致性能问题。
     *
     * @param maxLines æœ€å¤§ä¿ç•™çš„行数,默认值为 100。
     */
    void TrimRichEditLineLimit(int maxLines = 100);
    /**
     * @brief å‘日志窗口追加一条带颜色样式的日志行。
     *
     * @param content æ—¥å¿—内容。
     * @param color å­—体颜色,默认为黑色。
     */
    void AppendLogLineRichStyled(const CString& strContent, COLORREF color = RGB(0, 0, 0));
    /**
     * @brief é«˜äº®æ—¥å¿—中所有匹配指定字符串的部分。
     *
     * @param strSearch è¦åŒ¹é…çš„字符串。
     * @param clrHighlight é«˜äº®é¢œè‰²ï¼Œé»˜è®¤ä¸ºæ©™è‰²ï¼ˆRGB(255, 165, 0))。
     */
    void HighlightAllMatches(const CString& strSearch, COLORREF clrHighlight = RGB(255, 165, 0));
    /**
     * @brief ä»¥æ ¼å¼åŒ–方式输出指定通道的测量数据样本到日志。
     *
     * æ¯è¡Œè¾“出固定数量(如 7)个浮点数据,带时间戳、通道编号标识,便于调试查看。
     *
     * @param nOutNo è¾“出端口编号,用于标识日志来源,如 OUT1、OUT2 ç­‰ã€‚
     * @param vecBuffer æµ‹é‡æ•°æ®ç¼“存,将被逐行打印到日志中。
     */
    void PrintSampleData(int nOutNo, const std::vector<float>& vecBuffer);
    /**
     * @brief å°è¯•连接到测量设备。
     *
     * @return true è¡¨ç¤ºè¿žæŽ¥æˆåŠŸï¼Œfalse è¡¨ç¤ºè¿žæŽ¥å¤±è´¥ã€‚
     */
    bool ConnectToDevice();
    /**
     * @brief æ–­å¼€ä¸Žæµ‹é‡è®¾å¤‡çš„连接。
     *
     * @return true è¡¨ç¤ºæ–­å¼€æˆåŠŸï¼Œfalse è¡¨ç¤ºæ–­å¼€å¤±è´¥ã€‚
     */
    bool DisconnectFromDevice();
    /**
     * @brief åŽŸåœ°æ¸…é™¤æ— æ•ˆå€¼ï¼ˆå¦‚ -999.0f)并更新数据。
     *
     * @param nOutNo è¾“出通道编号,用于日志记录。
     * @param vecData è¾“入输出数据容器,内部将被就地裁剪。
     * @param fInvalid æ— æ•ˆå€¼çš„判断阈值,默认值为 -999.0f。
     */
    void CleanInvalidValuesInPlace(int nOutNo, std::vector<float>& vecData, float fInvalid = -999.0f);
    /**
     * @brief å°†æœ‰æ•ˆæ•°æ®åˆ‡å‰²æˆä¸¤æ®µçŽ»ç’ƒæ•°æ®ï¼ˆGlass1 ä¸Ž Glass2)。
     *
     * @param nOutNo è¾“出通道编号,用于日志记录。
     * @param validData è¾“入的有效数据(应已裁剪边界)。
     * @param vecGlass1 è¾“出第一段玻璃数据。
     * @param vecGlass2 è¾“出第二段玻璃数据。
     * @param fJumpThreshold è·³å˜é˜ˆå€¼ï¼Œç”¨äºŽæ£€æµ‹æ•°æ®çš„æ˜Žæ˜¾æ–­ç‚¹ã€‚
     * @param nWindow è·³å˜åˆ¤æ–­çš„前后窗口宽度。
     * @param nValleyMargin valley ç‚¹ä¹‹åŽå¤šå°‘个点作为实际切割点。
     * @param nMinGlass1Count æœ€å°‘有效点数限制。
     *
     * @return true è¡¨ç¤ºåˆ‡å‰²æˆåŠŸï¼Œfalse è¡¨ç¤ºå¤±è´¥ï¼ˆä¾‹å¦‚数据不足或无明显跳变)。
     */
    bool SplitGlassSegments(int nOutNo, const std::vector<float>& validData,
        std::vector<float>& vecGlass1, std::vector<float>& vecGlass2,
        float fJumpThreshold = 0.2f, int nWindow = 3, int nValleyMargin = 0,
        int nMinGlassCount = 10);
    /**
     * @brief å¯¹æ•°æ®æŒ‰æ•´æ•°éƒ¨åˆ†è¿›è¡Œåˆ†ç»„,保留数据量最多的一组(排除异常/干扰)。
     *
     * @param nOutNo è¾“出通道编号,用于日志记录。
     * @param vecInput åŽŸå§‹æµ®ç‚¹æ•°æ®ï¼ˆå·²è£å‰ªæ— æ•ˆå€¼ï¼‰ã€‚
     * @param vecOutput è¾“出被保留的主要分组数据(最多的那组)。
     *
     * @return true è¡¨ç¤ºæˆåŠŸè¿‡æ»¤å‡ºä¸»åˆ†ç»„ï¼Œfalse è¡¨ç¤ºæ‰€æœ‰æ•°æ®éƒ½è¢«è¿‡æ»¤æˆ–为空。
     */
    bool FilterDominantGroup(int nOutNo, const std::vector<float>& vecInput, std::vector<float>& vecOutput);
    /**
     * @brief ä»Žè¾“入数据中提取一个固定长度的稳定区间。
     *
     * @param nOutNo è¾“出通道编号,用于日志记录。
     * @param vecIn è¾“入原始数据。
     * @param vecOut è¾“出提取的稳定区域数据。
     * @param nFixedCount ç¨³å®šåŒºåŸŸçš„点数要求(必须固定数量)。
     * @param fMaxDelta å…è®¸çš„æœ€å¤§æ³¢åŠ¨èŒƒå›´ï¼ˆæœ€å¤§å€¼ - æœ€å°å€¼ï¼‰ã€‚
     *
     * @return true è¡¨ç¤ºæˆåŠŸæ‰¾åˆ°ç¨³å®šåŒºé—´ï¼Œfalse è¡¨ç¤ºæœªæ‰¾åˆ°ã€‚
     */
    bool ExtractStableRegionFixed(int nOutNo,
        const std::vector<float>& vecIn,
        std::vector<float>& vecOut,
        int nFixedCount = 5, float fMaxDelta = 0.05f);
    /**
     * @brief è®¡ç®—两片玻璃稳定区域的平均值和偏移量。
     *
     * @param vecGlass1 ç¬¬ä¸€æ®µç¨³å®šæ•°æ®ã€‚
     * @param vecGlass2 ç¬¬äºŒæ®µç¨³å®šæ•°æ®ã€‚
     * @param fAvg1 è¿”回第一段的平均值。
     * @param fAvg2 è¿”回第二段的平均值。
     * @param fOffset è¿”回两段的偏移值(绝对值差)。
     *
     * @return true è¡¨ç¤ºè®¡ç®—成功,false è¡¨ç¤ºè¾“入无效(如空数据)。
     */
    bool CalcGlassOffset(const std::vector<float>& vecGlass1,
        const std::vector<float>& vecGlass2,
        float& fAvg1, float& fAvg2, float& fOffset);
    /**
     * @brief åˆå§‹åŒ–设备端的数据存储缓冲区。
     *
     * è°ƒç”¨åº•层接口清除当前存储区内容,为新一轮的数据采集做准备。
     * å¿…须在设备连接成功且未进行数据存储时调用。
     *
     * @return true è¡¨ç¤ºåˆå§‹åŒ–成功;false è¡¨ç¤ºå¤±è´¥ï¼ˆå¯èƒ½æ˜¯è®¾å¤‡æœªè¿žæŽ¥æˆ–调用接口错误)。
     */
    bool InitDataStorage();
    /**
     * @brief å¯åŠ¨è®¾å¤‡ç«¯æ•°æ®é‡‡é›†å’Œå­˜å‚¨ã€‚
     *
     * è°ƒç”¨æ­¤å‡½æ•°åŽè®¾å¤‡å¼€å§‹é‡‡é›†å¹¶ç¼“存数据。
     * é€šå¸¸é…åˆè§¦å‘模式进行采集。
     *
     * @return true è¡¨ç¤ºå¯åŠ¨æˆåŠŸï¼›false è¡¨ç¤ºå¯åŠ¨å¤±è´¥ã€‚
     */
    bool StartDataStorage();
    /**
     * @brief åœæ­¢æ•°æ®é‡‡é›†å¹¶ä»Žè®¾å¤‡èŽ·å–å½“å‰å­˜å‚¨æ•°æ®ã€‚
     *
     * è°ƒç”¨åŽè®¾å¤‡åœæ­¢é‡‡é›†ï¼Œå¹¶å°è¯•读取指定端口的数据,供后续分析处理。
     *
     * @return true è¡¨ç¤ºåœæ­¢å¹¶è¯»å–数据成功;false è¡¨ç¤ºå¤±è´¥ï¼ˆå¦‚设备未响应或数据无效)。
     */
    bool StopDataStorage();
    /**
     * @brief åˆ†æžæŒ‡å®šç«¯å£çš„存储数据,并提取两段玻璃数据与稳定区,计算偏移。
     *
     * @param nOutNo     è¾“出端口编号(1~4)
     * @return float     æˆåŠŸè¿”å›žè®¡ç®—å‡ºçš„åç§»é‡ï¼Œå¤±è´¥è¿”å›ž -1.0f
     */
    float AnalyzeStoredData(int nOutNo);
    // === ç³»ç»ŸçŠ¶æ€ä¸Žè¿è¡Œæ•°æ® ===
    /**
     * @brief å½“前是否已连接到传感器控制器
     */
    bool m_bConnected;
    /**
     * @brief å½“前是否正在进行数据存储
     */
    bool m_bSaving;
    /**
     * @brief å››ä¸ªè¾“出端口的当前计算结果(如偏移量或厚度等)
     */
    double m_dOutValues[4];
    // === å­˜å‚¨è®¾ç½®ç›¸å…³ ===
    /**
     * @brief æ˜¯å¦ä½¿ç”¨ç¡¬ä»¶è§¦å‘信号(0=否,1=是)
     */
    int m_nUseTrigger;
    /**
     * @brief æ¯æ¬¡é‡‡é›†çš„æ•°æ®ç‚¹æ•°é‡
     */
    int m_nSavePointCount;
    /**
     * @brief è¾“出端口选择下拉框控件(用于设置采集端口)
     */
    CComboBox m_comboOutputPort;
    // === è·³å˜æ£€æµ‹ä¸ŽçŽ»ç’ƒè¯†åˆ«å‚æ•°ï¼ˆSplitGlassSegments ä½¿ç”¨ï¼‰ ===
    /**
     * @brief è·³å˜é˜ˆå€¼ï¼ˆä¾‹å¦‚ 0.2mm),用于检测两片玻璃之间的高度跳变
     */
    float m_fJumpThreshold;
    /**
     * @brief è·³å˜æ£€æµ‹çª—口半宽度(用于差分计算)
     */
    int m_nJumpWindow;
    /**
     * @brief valley ç‚¹å³ç§»çš„偏移量,用于最终确定分割点
     */
    int m_nValleyMargin;
    /**
     * @brief ç¬¬ä¸€ç‰‡çŽ»ç’ƒæœ€å°‘æ‰€éœ€çš„æ•°æ®ç‚¹æ•°
     */
    int m_nMinGlass1Count;
    // === ç¨³å®šåŒºåŸŸæå–参数(ExtractStableRegionFixed ä½¿ç”¨ï¼‰ ===
    /**
     * @brief æ¯æ®µç¨³å®šåŒºåŸŸè¦æå–的固定数据点数
     */
    int m_nFixedCount;
    /**
     * @brief æœ€å¤§å…è®¸æ³¢åŠ¨èŒƒå›´ï¼ˆä¾‹å¦‚ 0.05mm),判断是否为“稳定”区域
     */
    float m_fMaxDelta;
    // === æ—¥å¿—控件 ===
    /**
     * @brief å¯Œæ–‡æœ¬æŽ§ä»¶ï¼Œç”¨äºŽè¾“出带颜色的日志信息
     */
    CRichEditCtrl m_editLog;
    // === æ‰˜ç›˜å›¾æ ‡ç®¡ç† ===
    /**
     * @brief æ‰˜ç›˜å›¾æ ‡ç›¸å…³æ•°æ®ç»“构(NOTIFYICONDATA)
     */
    NOTIFYICONDATA m_trayIconData;
    /**
     * @brief æ‰˜ç›˜å›¾æ ‡çš„唯一 ID
     */
    UINT m_nTrayIconID;
    /**
     * @brief æ ‡è®°æ‰˜ç›˜å›¾æ ‡æ˜¯å¦å·²æˆåŠŸåˆ›å»º
     */
    BOOL m_bTrayIconCreated;
    /**
     * @brief æ ‡è®°ç¨‹åºæ˜¯å¦é€šè¿‡æ‰˜ç›˜å›¾æ ‡é€€å‡º
     */
    BOOL m_bExitingFromTray;
};
SourceCode/Bond/SGMeasurement/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
SourceCode/Bond/SGMeasurement/pch.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,5 @@
// pch.cpp: ä¸Žé¢„编译标头对应的源文件
#include "pch.h"
// å½“使用预编译的头时,需要使用此源文件,编译才能成功。
SourceCode/Bond/SGMeasurement/pch.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,13 @@
// pch.h: è¿™æ˜¯é¢„编译标头文件。
// ä¸‹æ–¹åˆ—出的文件仅编译一次,提高了将来生成的生成性能。
// è¿™è¿˜å°†å½±å“ IntelliSense æ€§èƒ½ï¼ŒåŒ…括代码完成和许多代码浏览功能。
// ä½†æ˜¯ï¼Œå¦‚果此处列出的文件中的任何一个在生成之间有更新,它们全部都将被重新编译。
// è¯·å‹¿åœ¨æ­¤å¤„添加要频繁更新的文件,这将使得性能优势无效。
#ifndef PCH_H
#define PCH_H
// æ·»åŠ è¦åœ¨æ­¤å¤„é¢„ç¼–è¯‘çš„æ ‡å¤´
#include "framework.h"
#endif //PCH_H
SourceCode/Bond/SGMeasurement/res/SGMeasurement.ico
SourceCode/Bond/SGMeasurement/res/SGMeasurement.rc2
Binary files differ
SourceCode/Bond/SGMeasurement/res/menu_close.ico
SourceCode/Bond/SGMeasurement/res/menu_restore.ico
SourceCode/Bond/SGMeasurement/resource.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,45 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ ç”Ÿæˆçš„包含文件。
// ä¾› SGMeasurement.rc ä½¿ç”¨
//
#define IDM_ABOUTBOX                    0x0010
#define IDD_ABOUTBOX                    100
#define IDS_ABOUTBOX                    101
#define IDD_SGMEASUREMENT_DIALOG        102
#define IDR_MAINFRAME                   128
#define IDI_ICON_RESTORE                130
#define IDI_ICON_EXIT                   131
#define IDC_IPADDRESS                   1000
#define IDC_BUTTON_CONNECT              1001
#define IDC_BUTTON_DISCONNECT           1002
#define IDC_EDIT_OUT1                   1003
#define IDC_EDIT_OUT2                   1004
#define IDC_EDIT_OUT3                   1005
#define IDC_EDIT_OUT4                   1006
#define IDC_CHECK_USE_TRIGGER           1007
#define IDC_EDIT_STORE_COUNT            1008
#define IDC_COMBO_OUTPUT_PORT           1009
#define IDC_BUTTON_START_STORE          1010
#define IDC_BUTTON_STOP_STORE           1011
#define IDC_BUTTON_CLEAR_STORE          1012
#define IDC_BUTTON_RECEIVE_FROM_CTRL    1013
#define IDC_BUTTON_SEND_TO_CTRL         1014
#define IDC_RICHEDIT_LOG                1015
#define IDC_BUTTON_CLEAR_LOG            1016
#define IDC_EDIT_JUMP_THRESHOLD         1017
#define IDC_EDIT_JUMP_WINDOW            1018
#define IDC_EDIT_VALLEY_MARGIN          1019
#define IDC_EDIT_MIN_GLASS_COUNT        1020
#define IDC_EDIT_FIXED_COUNT            1021
#define IDC_EDIT_MAX_DELTA              1022
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE        132
#define _APS_NEXT_COMMAND_VALUE         32771
#define _APS_NEXT_CONTROL_VALUE         1023
#define _APS_NEXT_SYMED_VALUE           101
#endif
#endif
SourceCode/Bond/SGMeasurement/targetver.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,8 @@
#pragma once
// åŒ…括 SDKDDKVer.h å°†å®šä¹‰å¯ç”¨çš„æœ€é«˜ç‰ˆæœ¬çš„ Windows å¹³å°ã€‚
//如果要为以前的 Windows å¹³å°ç”Ÿæˆåº”用程序,请包括 WinSDKVer.h,并
// å°† _WIN32_WINNT å®è®¾ç½®ä¸ºè¦æ”¯æŒçš„平台,然后再包括 SDKDDKVer.h。
#include <SDKDDKVer.h>
SourceCode/Bond/Servo/CBakeCooling.cpp
@@ -188,12 +188,13 @@
            // master recipe list report
            CEqReadStep* pStep = new CEqReadStep(0x12955, 255 * 2,
                [&](void* pFrom, int code, const char* pszData, size_t size) -> int {
                    CEqReadStep* pTmpStep = (CEqReadStep*)pFrom;
                    short ret = MRLRC_OK;
                    if (code == ROK && pszData != nullptr && size > 0) {
                        // æ­¤å¤„解释配方数据
                        short ret = decodeRecipeListReport(pszData, size);
                        pStep->setReturnCode(ret);
                        ret = decodeRecipeListReport(pszData, size);
                    }
                    pStep->setReturnCode(MRLRC_OK);
                    pTmpStep->setReturnCode(ret);
                    return -1;
                });
            pStep->setName(STEP_EQ_MASTER_RECIPE_LIST);
SourceCode/Bond/Servo/CBonder.cpp
@@ -193,12 +193,13 @@
            // master recipe list report
            CEqReadStep* pStep = new CEqReadStep(m_nIndex == 0 ? 0xa955 : 0xe955, 255 * 2,
                [&](void* pFrom, int code, const char* pszData, size_t size) -> int {
                    CEqReadStep* pTmpStep = (CEqReadStep*)pFrom;
                    short ret = MRLRC_OK;
                    if (code == ROK && pszData != nullptr && size > 0) {
                        // æ­¤å¤„解释配方数据
                        short ret = decodeRecipeListReport(pszData, size);
                        pStep->setReturnCode(ret);
                        ret = decodeRecipeListReport(pszData, size);
                    }
                    pStep->setReturnCode(MRLRC_OK);
                    pTmpStep->setReturnCode(ret);
                    return -1;
                });
            pStep->setName(STEP_EQ_MASTER_RECIPE_LIST);
@@ -419,14 +420,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);
            }
        }
        */
    }
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;
    }
}
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;
    };
}
SourceCode/Bond/Servo/CEFEM.cpp
@@ -549,7 +549,6 @@
            // master recipe list report
            CEqReadStep* pStep = new CEqReadStep(0x6955, 255 * 2,
                [&](void* pFrom, int code, const char* pszData, size_t size) -> int {
                    /*CEqReadStep* pTmpStep = dynamic_cast<CEqReadStep*>((CEqReadStep*)pFrom);*/
                    CEqReadStep* pTmpStep = (CEqReadStep*)pFrom;
                    short ret = MRLRC_OK;
                    if (code == ROK && pszData != nullptr && size > 0) {
SourceCode/Bond/Servo/CEquipment.cpp
@@ -1292,6 +1292,21 @@
        return nullptr;
    }
    CSlot* CEquipment::isSlotAvailable(unsigned int slot)
    {
        if (slot >= 8) return nullptr;
        if (!m_slot[slot].isEnable()) return nullptr;
        if (m_slot[slot].isLock()) return nullptr;
        if (!m_slot[slot].isEmpty()) return nullptr;
        int lsPath = m_slot[slot].getLinkSignalPath();
        if (!m_bLinkSignalToDownstream[lsPath][SIGNAL_UPSTREAM_INLINE]
            || m_bLinkSignalToDownstream[lsPath][SIGNAL_UPSTREAM_TROUBLE]
            || !m_bLinkSignalToDownstream[lsPath][SIGNAL_INTERLOCK]
            || !m_bLinkSignalToDownstream[lsPath][SIGNAL_RECEIVE_ABLE]) return nullptr;
        return &m_slot[slot];
    }
    CSlot* CEquipment::getNonEmptySlot(MaterialsType putSlotType)
    {
        for (int i = 0; i < SLOT_MAX; i++) {
@@ -1364,6 +1379,22 @@
        return nullptr;
    }
    CSlot* CEquipment::getProcessedSlotCt(unsigned int slot)
    {
        if (slot >= 8) return nullptr;
        if (!m_slot[slot].isEnable()) return nullptr;
        if (m_slot[slot].isLock()) return nullptr;
        CGlass* pGlass = (CGlass*)m_slot[slot].getContext();
        if (pGlass == nullptr) return nullptr;
        int lsPath = m_slot[slot].getLinkSignalPath();
        if (!m_bLinkSignalToUpstream[lsPath][SIGNAL_UPSTREAM_INLINE]
            || m_bLinkSignalToUpstream[lsPath][SIGNAL_UPSTREAM_TROUBLE]
            || !m_bLinkSignalToUpstream[lsPath][SIGNAL_INTERLOCK]
            || !m_bLinkSignalToUpstream[lsPath][SIGNAL_SEND_ABLE]) return nullptr;
        return &m_slot[slot];
    }
    CSlot* CEquipment::getInspFailSlot()
    {
        for (int i = 0; i < SLOT_MAX; i++) {
SourceCode/Bond/Servo/CEquipment.h
@@ -55,7 +55,7 @@
    typedef std::function<BOOL(void* pEiuipment, int port, CJobDataB* pJobDataB, short& putSlot)> ONPRESTOREDJOB;
    typedef std::function<void(void* pEiuipment, PROCESS_STATE state)> ONPROCESSSTATE;
    typedef std::function<void(void* pEiuipment, short scanMap, short downMap)> ONMAPMISMATCH;
    typedef std::function<void(void* pEiuipment, short scanMap)> ONPORTINUSE;
    typedef std::function<void(void* pEiuipment, short status, __int64 data)> ONPORTSTATUSCHANGED;
    typedef struct _EquipmentListener
    {
        ONALIVE                onAlive;
@@ -67,7 +67,7 @@
        ONPRESTOREDJOB        onPreStoredJob;
        ONPROCESSSTATE        onProcessStateChanged;
        ONMAPMISMATCH        onMapMismatch;
        ONPORTINUSE            onPortInUse;
        ONPORTSTATUSCHANGED    onPortStatusChanged;
    } EquipmentListener;
@@ -176,6 +176,7 @@
        // èŽ·å–ä¸€ä¸ªæŒ‡å®šç‰©æ–™ç±»åž‹(G1,G2,G1&G2)的空槽位
        CSlot* getAvailableSlotForGlass(MaterialsType type);
        CSlot* getAvailableSlotForGlassExcludeSignal(MaterialsType type);
        CSlot* isSlotAvailable(unsigned int slot);
        // åœ¨æŒ‡å®šçš„æ§½åˆ—表中,获取一个指定物料类型(G1,G2,G1&G2)的空槽位
        CSlot* getAvailableSlotForGlass2(MaterialsType type, const std::vector<int>& candidates);
@@ -187,6 +188,7 @@
        CSlot* getProcessedSlot(MaterialsType putSlotType);
        CSlot* getProcessedSlot2(MaterialsType putSlotType, const std::vector<int>& candidates);
        CSlot* getInspFailSlot();
        CSlot* getProcessedSlotCt(unsigned int slot);
        // èŽ·å–çŽ»ç’ƒç‰©æ–™
        CGlass* getGlassFromSlot(int slotNo);
SourceCode/Bond/Servo/CLoadPort.cpp
@@ -9,8 +9,8 @@
    CLoadPort::CLoadPort() : CEquipment()
    {
        m_nIndex = 0;
        m_portType = PortType::Loading;
        m_portMode = PortMode::ReadyToLoad;
        m_portType = PortType::Both;
        m_portMode = PortMode::OutOfService;
        m_cassetteType = CassetteType::G1;
        m_transferMode = TransferMode::AGVMode;
        m_bEnable = FALSE;
@@ -115,6 +115,7 @@
                [&](void* pFrom, int code, const char* pszData, size_t size) -> int {
                    if (code == ROK && pszData != nullptr && size > 0) {
                        m_portMode = (PortMode)CToolUnits::toInt16(pszData);
                        LOGI("<LoadPort-%d>m_portMode:%d", m_nIndex, m_portMode);
                    }
                    return 0;
                });
@@ -355,10 +356,10 @@
            static int ii = 0;
            ii++;
            if (ii == 20) {
                char szBuffer[64];
                char szBuffer[64] = {0};
                CStep* pStep = getStepWithName(STEP_EQ_PORT1_INUSE);
                CPortStatusReport portStatusReport;
                portStatusReport.setPortStatus(PORT_INUSE);
                portStatusReport.setPortStatus(PORT_UNLOAD_READY);
                portStatusReport.setJobExistenceSlot(0xf);
                int nRet = portStatusReport.serialize(szBuffer, 64);
                decodePortStatusReport(pStep, szBuffer, 64);
@@ -373,23 +374,11 @@
        if (ar.IsStoring()) {
            ar << m_nIndex;
            //ar << (int)m_portType;
            //ar << (int)m_portMode;
            //ar << (int)m_cassetteType;
            //ar << (int)m_transferMode;
            //ar << m_bEnable;
            //ar << m_bAutoChangeEnable;
            m_portStatusReport.serialize(ar);
        }
        else {
            int temp;
            ar >> m_nIndex;
            //ar >> temp; m_portType = (PortType)temp;
            //ar >> temp; m_portMode = (PortMode)temp;
            //ar >> temp; m_cassetteType = (CassetteType)temp;
            //ar >> temp; m_transferMode = (TransferMode)temp;
            //ar >> m_bEnable;
            //ar >> m_bAutoChangeEnable;
            m_portStatusReport.serialize(ar);
        }
    }
@@ -924,8 +913,9 @@
            else {
                // æŠ›å‡ºåˆ°åº”用层做选择要加工的片子
                generateGlassList(getScanCassetteMap());
                if (m_listener.onPortInUse != nullptr) {
                    m_listener.onPortInUse(this, getScanCassetteMap());
                if (m_listener.onPortStatusChanged != nullptr) {
                    m_listener.onPortStatusChanged(this, portStatusReport.getPortStatus(),
                        getScanCassetteMap());
                }
            }
        }
SourceCode/Bond/Servo/CMaster.cpp
@@ -52,6 +52,9 @@
        m_pActiveRobotTask = nullptr;
        m_nLastError = 0;
        m_isCompareMapsBeforeProceeding = FALSE;
        m_bEnableEventReport = true;
        m_bEnableAlarmReport = true;
        m_bContinuousTransfer = false;
        InitializeCriticalSection(&m_criticalSection);
    }
@@ -249,6 +252,20 @@
            return -1;
        }
        m_bContinuousTransfer = false;
        setState(MASTERSTATE::STARTING);
        m_ullStartTime = GetTickCount64();
        return 0;
    }
    int CMaster::startContinuousTransfer()
    {
        if (m_state != MASTERSTATE::READY) {
            return -1;
        }
        m_bContinuousTransfer = true;
        setState(MASTERSTATE::STARTING);
        m_ullStartTime = GetTickCount64();
@@ -258,7 +275,7 @@
    int CMaster::stop()
    {
        // è¿è¡Œæ—¶é—´ä¸ºç´¯åŠ ç»“æžœï¼Œæœ¬æ¬¡åœæ­¢æ—¶åˆ·æ–°ï¼›
        if (m_state != MASTERSTATE::RUNNING) {
        if (m_state != MASTERSTATE::RUNNING && m_state != MASTERSTATE::RUNNING_CONTINUOUS_TRANSFER) {
            return -1;
        }
@@ -445,7 +462,11 @@
                unlock();
                setState(MASTERSTATE::RUNNING);
                if(!m_bContinuousTransfer)
                    setState(MASTERSTATE::RUNNING);
                else
                    setState(MASTERSTATE::RUNNING_CONTINUOUS_TRANSFER);
                continue;
            }
@@ -546,15 +567,11 @@
                    LOGI("Arm1 %s, Arm2 %s.", rmd.armState[0] ? _T("不可用") : _T("可用"),
                        rmd.armState[1] ? _T("不可用") : _T("可用"));
                }
                CEquipment* pEqTar[] = { pVacuumBake, pFliper };
                if (primaryType == MaterialsType::G2) {
                    pEqTar[0] = pFliper;
                    pEqTar[1] = pVacuumBake;
                }
                for (int s = 0; s < 4; s++) {
                    PortType pt = pLoadPorts[s]->getPortType();
                    if (!rmd.armState[0] && pLoadPorts[s]->isEnable()
                        && pLoadPorts[s]->getPortType() == PortType::Unloading
                        && pLoadPorts[s]->getPortMode() == PortMode::ReadyToUnload) {
                        && (pt == PortType::Unloading || pt == PortType::Both)
                        && pLoadPorts[s]->getPortStatus() == PORT_INUSE) {
                        m_pActiveRobotTask = createTransferTask(pMeasurement, pLoadPorts[s], primaryType, secondaryType);
                        if (m_pActiveRobotTask != nullptr) {
                            goto PORT_PUT;
@@ -647,9 +664,10 @@
                // LoadPort -> Aligner
                for (int s = 0; s < 4; s++) {
                    PortType pt = pLoadPorts[s]->getPortType();
                    if (!rmd.armState[0] && pLoadPorts[s]->isEnable()
                        && pLoadPorts[s]->getPortType() == PortType::Loading
                        && pLoadPorts[s]->getPortMode() == PortMode::ReadyToLoad) {
                        && (pt == PortType::Loading || pt == PortType::Both)
                        && pLoadPorts[s]->getPortStatus() == PORT_INUSE) {
                        m_pActiveRobotTask = createTransferTask(pLoadPorts[s], pAligner, primaryType, secondaryType);
                        if (m_pActiveRobotTask != nullptr) {
                            pEFEM->setContext(m_pActiveRobotTask->getContext());
@@ -665,6 +683,132 @@
                unlock();
                continue;
            }
            // åƒä¼ æ¨¡å¼è°ƒåº¦é€»è¾‘
            else if (m_state == MASTERSTATE::RUNNING_CONTINUOUS_TRANSFER) {
                // æ£€æµ‹åˆ¤æ–­robot状态
                RMDATA& rmd = pEFEM->getRobotMonitoringData();
                if (rmd.status != ROBOT_STATUS::Idle && rmd.status != ROBOT_STATUS::Run) {
                    unlock();
                    continue;
                }
                if (m_pActiveRobotTask != nullptr) {
                    if (m_pActiveRobotTask->isPicked()) {
                        m_pActiveRobotTask->place();
                    }
                    unlock();
                    // æ£€æµ‹åˆ°å½“前有正在下午的任务,确保当前任务完成或中止后继续
                    // LOGI("检测到当前有正在下午的任务,确保当前任务完成或中止后继续...");
                    continue;
                }
                // Measurement -> LoadPort
                for (int s = 0; s < 4; s++) {
                    PortType pt = pLoadPorts[s]->getPortType();
                    if (!rmd.armState[0] && pLoadPorts[s]->isEnable()
                        && (pt == PortType::Unloading || pt == PortType::Both)
                        && pLoadPorts[s]->getPortStatus() == PORT_INUSE) {
                        for (int slot = 0; slot < SLOT_MAX; slot++) {
                            m_pActiveRobotTask = createTransferTask_continuous_transfer(pMeasurement,
                                0, pLoadPorts[s], slot);
                            if (m_pActiveRobotTask != nullptr) {
                                goto CT_PORT_PUT;
                            }
                        }
                    }
                }
            CT_PORT_PUT:
                CHECK_RUN_ACTIVE_ROBOT_TASK(m_pActiveRobotTask);
                // BakeCooling ->Measurement
                if (!rmd.armState[0]) {
                    m_pActiveRobotTask = createTransferTask_continuous_transfer(pBakeCooling,
                        3, pMeasurement, 0);
                    CHECK_RUN_ACTIVE_ROBOT_TASK(m_pActiveRobotTask);
                }
                // BakeCooling内部
                if (!rmd.armState[0]) {
                    m_pActiveRobotTask = createTransferTask_continuous_transfer(pBakeCooling,
                        2, pBakeCooling, 3);
                    CHECK_RUN_ACTIVE_ROBOT_TASK(m_pActiveRobotTask);
                }
                if (!rmd.armState[0]) {
                    m_pActiveRobotTask = createTransferTask_continuous_transfer(pBakeCooling,
                        1, pBakeCooling, 2);
                    CHECK_RUN_ACTIVE_ROBOT_TASK(m_pActiveRobotTask);
                }
                if (!rmd.armState[0]) {
                    m_pActiveRobotTask = createTransferTask_continuous_transfer(pBakeCooling,
                        0, pBakeCooling, 1);
                    CHECK_RUN_ACTIVE_ROBOT_TASK(m_pActiveRobotTask);
                }
                // Bonder2 -> BakeCooling
                if (!rmd.armState[0]) {
                    m_pActiveRobotTask = createTransferTask_continuous_transfer(pBonder2,
                        0, pBakeCooling, 0);
                    CHECK_RUN_ACTIVE_ROBOT_TASK(m_pActiveRobotTask);
                }
                // Bonder1 -> Bonder2
                if (!rmd.armState[0] && !pBonder2->hasBondClass()) {
                    m_pActiveRobotTask = createTransferTask_continuous_transfer(pBonder1,
                        0, pBonder2, 0);
                    CHECK_RUN_ACTIVE_ROBOT_TASK(m_pActiveRobotTask);
                }
                // VacuumBake(G1) -> Bonder1
                if (!rmd.armState[0] && !pBonder1->hasBondClass()) {
                    m_pActiveRobotTask = createTransferTask_continuous_transfer(pVacuumBake,
                        0, pBonder1, 0);
                    CHECK_RUN_ACTIVE_ROBOT_TASK(m_pActiveRobotTask);
                }
                // Fliper(G2) -> VacuumBake(G1)
                if (!rmd.armState[0]) {
                    m_pActiveRobotTask = createTransferTask_continuous_transfer(pFliper,
                        0, pVacuumBake, 0);
                    CHECK_RUN_ACTIVE_ROBOT_TASK(m_pActiveRobotTask);
                }
                // Aligner -> Fliper(G2)
                if (!rmd.armState[1]) {
                    m_pActiveRobotTask = createTransferTask_continuous_transfer(pAligner,
                        0, pFliper, 0);
                    CHECK_RUN_ACTIVE_ROBOT_TASK(m_pActiveRobotTask);
                }
                // LoadPort -> Aligner
                for (int s = 0; s < 4; s++) {
                    PortType pt = pLoadPorts[s]->getPortType();
                    if (!rmd.armState[0] && pLoadPorts[s]->isEnable()
                        && (pt == PortType::Loading || pt == PortType::Both)
                        && pLoadPorts[s]->getPortStatus() == PORT_INUSE) {
                        for (int slot = 0; slot < SLOT_MAX; slot++) {
                            m_pActiveRobotTask = createTransferTask_continuous_transfer(pLoadPorts[s],
                                slot, pAligner, 0);
                            if (m_pActiveRobotTask != nullptr) {
                                pEFEM->setContext(m_pActiveRobotTask->getContext());
                                goto CT_PORT_GET;
                            }
                        }
                    }
                }
            CT_PORT_GET:
                CHECK_RUN_ACTIVE_ROBOT_TASK(m_pActiveRobotTask);
                unlock();
                continue;
            }
            unlock();
        }
@@ -889,10 +1033,10 @@
            LOGE("<Master-%s>Port InUse, map(%d!=%d)不一致,请检查。",
                ((CEquipment*)pEquipment)->getName().c_str(), scanMap, downMap);
        };
        listener.onPortInUse = [&](void* pEquipment, short scanMap) {
            LOGE("<Master-%s>Port InUse。scanMap=%d", ((CEquipment*)pEquipment)->getName().c_str(), scanMap);
            if (m_listener.onLoadPortInUse != nullptr) {
                m_listener.onLoadPortInUse(this, (CEquipment*)pEquipment, scanMap);
        listener.onPortStatusChanged = [&](void* pEquipment, short status, __int64 data) {
            LOGE("<Master-%s>Port InUse。status=%d, data=%lld", ((CEquipment*)pEquipment)->getName().c_str(), status);
            if (m_listener.onLoadPortStatusChanged != nullptr) {
                m_listener.onLoadPortStatusChanged(this, (CEquipment*)pEquipment, status, data);
            }
        };
        pEquipment->setListener(listener);
@@ -1427,6 +1571,31 @@
        return pTask;
    }
    CRobotTask* CMaster::createTransferTask_continuous_transfer(CEquipment* pSrcEq, int nSrcSlot,
        CEquipment* pTarEq, int nTarSlot, int armNo/* = 1*/)
    {
        if (!pSrcEq->IsEnabled()) {
            return nullptr;
        }
        if (!pTarEq->IsEnabled()) {
            return nullptr;
        }
        CRobotTask* pTask = nullptr;
        CSlot* pTarSlot = pTarEq->isSlotAvailable(nTarSlot);
        CSlot* pSrcSlot = pSrcEq->getProcessedSlotCt(nSrcSlot);
        if (pSrcSlot != nullptr && nullptr != pTarSlot) {
            pTask = new CRobotTask();
            pTask->setContext(pSrcSlot->getContext());
            pTask->setEFEM((CEFEM*)getEquipment(EQ_ID_EFEM));
            taskSeqNo = pTask->setRobotTransferParam(taskSeqNo, armNo, pSrcSlot->getPosition(),
                pTarSlot->getPosition(), pSrcSlot->getNo(), pTarSlot->getNo());
        }
        return pTask;
    }
    int CMaster::abortCurrentTask()
    {
        lock();
@@ -1499,8 +1668,39 @@
        pPort->localSetCessetteType(type);
    }
    void CMaster::setPortEnable(unsigned int index, BOOL bEnable)
    {
        ASSERT(index < 4);
        int eqid[] = { EQ_ID_LOADPORT1, EQ_ID_LOADPORT2, EQ_ID_LOADPORT3, EQ_ID_LOADPORT4 };
        CLoadPort* pPort = (CLoadPort*)getEquipment(eqid[index]);
        pPort->localEanblePort(bEnable);
    }
    void CMaster::setCompareMapsBeforeProceeding(BOOL bCompare)
    {
        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;
    }
}
SourceCode/Bond/Servo/CMaster.h
@@ -20,6 +20,7 @@
        READY = 0,
        STARTING,
        RUNNING,
        RUNNING_CONTINUOUS_TRANSFER,
        STOPPING,
        MSERROR
    };
@@ -31,7 +32,7 @@
    typedef std::function<void(void* pMaster, CEquipment* pEquipment, CVcrEventReport* pReport)> ONEQVCREVENTREPORT;
    typedef std::function<void(void* pMaster, CEquipment* pEquipment, int code)> ONEQDATACHANGED;
    typedef std::function<void(void* pMaster, CRobotTask* pTask, int code)> ONROBOTTASKEVENT;
    typedef std::function<void(void* pMaster, CEquipment* pEquipment, short scanMap)> ONLOADPORTINUSE;
    typedef std::function<void(void* pMaster, CEquipment* pEquipment, short status, __int64 data)> ONLOADPORTSTATUSCHANGED;
    typedef struct _MasterListener
    {
        ONMASTERSTATECHANGED    onMasterStateChanged;
@@ -41,7 +42,7 @@
        ONEQVCREVENTREPORT        onEqVcrEventReport;
        ONEQDATACHANGED         onEqDataChanged;
        ONROBOTTASKEVENT        onRobotTaskEvent;
        ONLOADPORTINUSE            onLoadPortInUse;
        ONLOADPORTSTATUSCHANGED    onLoadPortStatusChanged;
    } MasterListener;
    class CMaster
@@ -57,6 +58,7 @@
        int init();
        int term();
        int start();
        int startContinuousTransfer();
        int stop();
        void clearError();
        ULONGLONG getRunTime();
@@ -73,7 +75,12 @@
        void setPortType(unsigned int index, BOOL enable, int type, int mode,
            int cassetteType, int transferMode, BOOL autoChangeEnable);
        void setPortCassetteType(unsigned int index, SERVO::CassetteType type);
        void setPortEnable(unsigned int index, BOOL bEnable);
        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 +109,9 @@
        CRobotTask* createTransferTask_bake_to_cooling(CEquipment* pSrcEq);
        CRobotTask* createTransferTask_bakecooling_to_measurement(CEquipment* pSrcEq, CEquipment* pTarEq);
        CRobotTask* createTransferTask_restore(CEquipment* pEqSrc, CLoadPort** pPorts);
        CRobotTask* createTransferTask_continuous_transfer(CEquipment* pSrcEq, int nSrcSlot,
            CEquipment* pTarEq, int nTarSlot, int armNo = 1);
    private:
        CRITICAL_SECTION m_criticalSection;
        MasterListener m_listener;
@@ -110,6 +119,7 @@
        std::list<CEquipment*> m_listEquipment;
        std::string m_strFilepath;
        BOOL m_bDataModify;
        bool m_bContinuousTransfer;
    private:
        /* ç›‘控比特位的线程*/
@@ -138,6 +148,9 @@
        // åœ¨å¼€å§‹å·¥è‰ºå‰æ˜¯å¦å…ˆéœ€è¦å…ˆæ¯”较map
        BOOL m_isCompareMapsBeforeProceeding;
    private:
        bool m_bEnableEventReport;
        bool m_bEnableAlarmReport;
    };
}
SourceCode/Bond/Servo/CMeasurement.cpp
@@ -188,12 +188,13 @@
            // master recipe list report
            CEqReadStep* pStep = new CEqReadStep(0x1a955, 255 * 2,
                [&](void* pFrom, int code, const char* pszData, size_t size) -> int {
                    CEqReadStep* pTmpStep = (CEqReadStep*)pFrom;
                    short ret = MRLRC_OK;
                    if (code == ROK && pszData != nullptr && size > 0) {
                        // æ­¤å¤„解释配方数据
                        short ret = decodeRecipeListReport(pszData, size);
                        pStep->setReturnCode(ret);
                        ret = decodeRecipeListReport(pszData, size);
                    }
                    pStep->setReturnCode(MRLRC_OK);
                    pTmpStep->setReturnCode(ret);
                    return -1;
                });
            pStep->setName(STEP_EQ_MASTER_RECIPE_LIST);
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();
}
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
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());
    }
}
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);
};
SourceCode/Bond/Servo/CPageGraph2.cpp
@@ -212,70 +212,14 @@
        // æµ‹è¯•
        else if (nCmd == ID_EQSGRAPHITEM_TEST1) {
        }
        else if (nCmd == ID_EQSGRAPHITEM_TEST2) {
            SERVO::CEquipment* pEquipment = (SERVO::CEquipment*)pItem->pData;
            SERVO::CArm* pArm = (SERVO::CArm*)pEquipment->getArm();
            if (pArm != nullptr) {
                SERVO::CGlass* pGlass = pArm->getAnyGlass();
                if (pGlass != nullptr) {
                    SERVO::CJobDataS* pJobDataS = pGlass->getJobDataS();
                    if (pJobDataS != nullptr) {
                        pEquipment->onReceivedJob(0, pJobDataS);
                        Sleep(600);
                        SERVO::CJobDataB jobDataB;
                        pEquipment->onStoredJob(0, &pJobDataS->getJobDataB(jobDataB));
                    }
                }
            }
        }
        else if (nCmd == ID_EQSGRAPHITEM_TEST3) {
            SERVO::CEquipment* pEquipment = (SERVO::CEquipment*)pItem->pData;
            if (pEquipment != nullptr) {
                SERVO::CGlass* pGlass = pEquipment->getAnyGlass();
                if (pGlass != nullptr) {
                    SERVO::CProcessData pd;
                    pd.setGlassId(pGlass->getID().c_str());
                    pEquipment->onProcessData(&pd);
                }
            }
        }
        else if (nCmd == ID_EQSGRAPHITEM_TEST4) {
            SERVO::CEquipment* pEquipment = (SERVO::CEquipment*)pItem->pData;
            if (pEquipment != nullptr) {
                pEquipment->setLinkSignalUpstream(0, SIGNAL_UPSTREAM_INLINE, TRUE);
                pEquipment->setLinkSignalUpstream(0, SIGNAL_UPSTREAM_TROUBLE, FALSE);
                pEquipment->setLinkSignalUpstream(0, SIGNAL_INTERLOCK, TRUE);
                pEquipment->setLinkSignalUpstream(0, SIGNAL_SEND_ABLE, TRUE);
                pEquipment->setLinkSignalUpstream(1, SIGNAL_UPSTREAM_INLINE, TRUE);
                pEquipment->setLinkSignalUpstream(1, SIGNAL_UPSTREAM_TROUBLE, FALSE);
                pEquipment->setLinkSignalUpstream(1, SIGNAL_INTERLOCK, TRUE);
                pEquipment->setLinkSignalUpstream(1, SIGNAL_SEND_ABLE, TRUE);
            }
            if (pEquipment != nullptr && (pEquipment->getID() == EQ_ID_Bonder1
                || pEquipment->getID() == EQ_ID_Bonder2)) {
                SERVO::CGlass* pGlass = pEquipment->getAnyGlass();
                if (pGlass != nullptr) {
                    SERVO::CProcessData pd;
                    pd.setGlassId(pGlass->getID().c_str());
                    pEquipment->onProcessData(&pd);
                }
            }
        }
        else if (nCmd == ID_EQSGRAPHITEM_TEST5) {
            SERVO::CEquipment* pEquipment = (SERVO::CEquipment*)pItem->pData;
            if (pEquipment != nullptr) {
                pEquipment->setLinkSignalUpstream(0, SIGNAL_UPSTREAM_INLINE, TRUE);
                pEquipment->setLinkSignalUpstream(0, SIGNAL_UPSTREAM_TROUBLE, TRUE);
                pEquipment->setLinkSignalUpstream(0, SIGNAL_INTERLOCK, TRUE);
                pEquipment->setLinkSignalUpstream(0, SIGNAL_SEND_ABLE, FALSE);
                pEquipment->setLinkSignalUpstream(1, SIGNAL_UPSTREAM_INLINE, TRUE);
                pEquipment->setLinkSignalUpstream(1, SIGNAL_UPSTREAM_TROUBLE, TRUE);
                pEquipment->setLinkSignalUpstream(1, SIGNAL_INTERLOCK, TRUE);
                pEquipment->setLinkSignalUpstream(1, SIGNAL_SEND_ABLE, FALSE);
            }
        }
        else if (nCmd == ID_EQSGRAPHITEM_TEST6) {
            SERVO::CEquipment* pEquipment = (SERVO::CEquipment*)pItem->pData;
@@ -312,8 +256,7 @@
            // æµ‹è¯•设置时间
            /*
            if (pEquipment->getID() == EQ_ID_Bonder1
                || pEquipment->getID() == EQ_ID_Bonder2) {
            if (pEquipment->getID() == EQ_ID_EFEM) {
                CTime time = CTime::GetCurrentTime();
                pEquipment->setDateTime((short)time.GetYear(),
                    (short)time.GetMonth(),
@@ -323,7 +266,6 @@
                    (short)time.GetSecond());
            }
            */
            
            // æµ‹è¯•设置cim mode
            /*
@@ -334,32 +276,18 @@
            }
            */
            
            /*
            if (pEquipment->getID() == EQ_ID_Bonder1
                || pEquipment->getID() == EQ_ID_Bonder2) {
                static int ii = 0; ii++;
                pEquipment->setEqMode((ii % 5) + 1);
            }
            /*
            SERVO::CGlass* pGlass = pEquipment->getAnyGlass();
            if (pGlass != nullptr) {
                std::string strDescription;
                SERVO::CPath* pPath = pGlass->getPath();
                while (pPath != nullptr) {
                    pPath->getDescription(strDescription);
                    AfxMessageBox(strDescription.c_str());
                    pPath = pPath->getNext();
                }
            }
            */
            // è¯·æ±‚主配方列表
            if (pEquipment != nullptr) {
                pEquipment->masterRecipeListRequest(0, nullptr);
            }
            static int i = 0;
            i++;
            static char* pszText[] = {"123", "456", "789", "abc", "def"};
            theApp.m_model.m_hsmsPassive.requestAlarmReport(i%3, i, pszText[i%5]);
        }
SourceCode/Bond/Servo/CPagePortProperty.cpp
@@ -139,12 +139,15 @@
    BOOL bCheck = ((CButton*)GetDlgItem(IDC_CHECK_ENABLE))->GetCheck() == BST_CHECKED;
    EnableCtrls(bCheck);
#ifdef _LOCAL
    ASSERT(m_pPort != nullptr);
    theApp.m_model.setPortEnable(m_pPort->getIndex(), bCheck);
#else
    // enable port
    g_nMsgDlgShow = 0;
    CMsgDlg msgDlg("请等待", "正在操作,请等待...");
    ASSERT(m_pPort != nullptr);
    m_pPort->eablePort(bCheck, [&](int code) -> int {
        Sleep(100);
        CString strMsg;
@@ -184,6 +187,7 @@
    msgDlg.DoModal();
    g_nMsgDlgShow = 1;
#endif
}
void CPagePortProperty::OnCbnSelchangeComboPortType()
@@ -433,9 +437,6 @@
void CPagePortProperty::EnableCtrls(BOOL bEnable)
{
    GetDlgItem(IDC_COMBO_PORT_TYPE)->EnableWindow(bEnable);
    GetDlgItem(IDC_COMBO_PORT_MODE)->EnableWindow(bEnable);
    GetDlgItem(IDC_COMBO_PORT_CASSERT_TYPE)->EnableWindow(bEnable);
    GetDlgItem(IDC_COMBO_PORT_TRANSFER_MODE)->EnableWindow(bEnable);
    GetDlgItem(IDC_CHECK_AUTO_CHANGE)->EnableWindow(bEnable);
}
SourceCode/Bond/Servo/CPagePortStatus.cpp
@@ -99,14 +99,15 @@
    // åˆ›å»ºJob Existence Slots控件
    m_ctrlJobSlotGrid.Create(AfxRegisterWndClass(0), _T("JobSlotGrid"),
        WS_CHILD | WS_VISIBLE, CRect(0, 0, 100, 100), this, 1001);
    m_ctrlJobSlotGrid.SetGridSize(12, 16);
        WS_CHILD | WS_VISIBLE, CRect(0, 0, 88, 32), this, 1001);
    m_ctrlJobSlotGrid.SetGridSize(1, 8);
    m_ctrlJobSlotGrid.SetColors(RGB(34, 177, 76), RGB(200, 200, 200));
    m_ctrlJobSlotGrid.SetSlotStatus(0, 1, true);
    m_ctrlJobSlotGrid.SetSlotStatus(1, 9, true);
    m_ctrlJobSlotGrid.SetSlotStatus(4, 9, false);
    m_ctrlJobSlotGrid.SetSlotStatus(4, 10, true, TRUE);
    auto statusMap = m_pPort->getScanCassetteMap();
    for (int i = 0; i < 8; ++i) {
        bool isSet = (statusMap >> i) & 1;
        m_ctrlJobSlotGrid.SetSlotStatus(0, i, isSet);
    }
    return TRUE;  // return TRUE unless you set the focus to a control
                  // å¼‚常: OCX å±žæ€§é¡µåº”返回 FALSE
@@ -144,5 +145,5 @@
    GetClientRect(rcClient);
    m_ctrlJobSlotGrid.MoveWindow(rcComboBox.left, rcLabel.top, 
        rcClient.right - 22 - rcComboBox.left, rcClient.bottom - 12 - rcLabel.top);
        34 * 8, 32);
}
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());
    }
}
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);
};
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());
    }
}
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);
};
SourceCode/Bond/Servo/CPortStatusReport.cpp
@@ -139,9 +139,6 @@
        memcpy(&m_nLoadingCassetteType, &pszBuffer[index], sizeof(short));
        index += sizeof(short);
        memcpy(&m_nLoadingCassetteType, &pszBuffer[index], sizeof(short));
        index += sizeof(short);
        memcpy(&m_nQTimeFlag, &pszBuffer[index], sizeof(short));
        index += sizeof(short);
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;
    }
}
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;
    };
}
SourceCode/Bond/Servo/CVacuumBake.cpp
@@ -188,12 +188,13 @@
            // master recipe list report
            CEqReadStep* pStep = new CEqReadStep(0x16955, 255 * 2,
                [&](void* pFrom, int code, const char* pszData, size_t size) -> int {
                    CEqReadStep* pTmpStep = (CEqReadStep*)pFrom;
                    short ret = MRLRC_OK;
                    if (code == ROK && pszData != nullptr && size > 0) {
                        // æ­¤å¤„解释配方数据
                        short ret = decodeRecipeListReport(pszData, size);
                        pStep->setReturnCode(ret);
                        ret = decodeRecipeListReport(pszData, size);
                    }
                    pStep->setReturnCode(MRLRC_OK);
                    pTmpStep->setReturnCode(ret);
                    return -1;
                });
            pStep->setName(STEP_EQ_MASTER_RECIPE_LIST);
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;
    }
}
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;
    };
}
SourceCode/Bond/Servo/Common.h
@@ -18,7 +18,7 @@
#define RX_CODE_EQ_DATA_CHANGED            1010
#define RX_CODE_MASTER_STATE_CHANGED    1011
#define RX_CODE_EQ_ROBOT_TASK            1012
#define RX_CODE_LOADPORT_INUSE            1013
#define RX_CODE_LOADPORT_STATUS_CHANGED    1014
/* Channel Name */
SourceCode/Bond/Servo/Configuration.cpp
@@ -146,6 +146,15 @@
    return true;
}
BOOL CConfiguration::setPortEnable(unsigned int index, BOOL bEnable)
{
    if (index >= 4) return FALSE;
    static char* pszSection[] = { "Port1", "Port2", "Port3", "Port4" };
    WritePrivateProfileString(pszSection[index], _T("Enable"), std::to_string(bEnable ? 1 : 0).c_str(), m_strFilepath);
    return true;
}
BOOL CConfiguration::isCompareMapsBeforeProceeding()
{
    return GetPrivateProfileInt(_T("Master"), _T("CompareMapsBeforeProceeding"), 0, m_strFilepath);
SourceCode/Bond/Servo/Configuration.h
@@ -25,6 +25,7 @@
    BOOL getPortParms(unsigned int index, BOOL& bEnable, int& type, int& mode,
        int& cassetteType, int& transferMode, BOOL& bAutoChangeEnable);
    BOOL setPortCassetteType(unsigned int index, int cassetteType);
    BOOL setPortEnable(unsigned int index, BOOL bEnable);
    BOOL isCompareMapsBeforeProceeding();
public:
SourceCode/Bond/Servo/HsmsAction.cpp
@@ -104,6 +104,63 @@
BOOL CHsmsAction::incrementAndCheckTimeout()
{
    unsigned int nResponseTime = InterlockedIncrement(&m_nResponseTime);
    return nResponseTime >= m_nTimeout;
    return nResponseTime >= m_nTimeout + 1;
}
int CHsmsAction::serialize(char* pszBuffer, int nBufferSize)
{
    int index = 0;
    if (pszBuffer == nullptr) {
        index += sizeof(int);
        index += sizeof(m_nTimeout);
        index += sizeof(int);
        index += sizeof(BOOL);
        index += m_pSendMessage->serialize(pszBuffer, nBufferSize);
        return index;
    }
    else {
        memcpy(&pszBuffer[index], &m_nAction, sizeof(int));
        index += sizeof(int);
        memcpy(&pszBuffer[index], &m_nTimeout, sizeof(int));
        index += sizeof(int);
        memcpy(&pszBuffer[index], &m_nResponseTime, sizeof(int));
        index += sizeof(int);
        memcpy(&pszBuffer[index], &m_bNeedWaitReply, sizeof(BOOL));
        index += sizeof(BOOL);
        index += m_pSendMessage->serialize(&pszBuffer[index], nBufferSize - index);
        return index;
    }
}
int CHsmsAction::unserialize(const char* pszBuffer, int nBufferSize)
{
    int index = 0;
    if (index + sizeof(int) > nBufferSize) return -1;
    memcpy(&m_nAction, &pszBuffer[index], sizeof(int));
    index += sizeof(int);
    if (index + sizeof(int) > nBufferSize) return -1;
    memcpy(&m_nTimeout, &pszBuffer[index], sizeof(int));
    index += sizeof(int);
    if (index + sizeof(int) > nBufferSize) return -1;
    memcpy(&m_nResponseTime, &pszBuffer[index], sizeof(int));
    index += sizeof(int);
    if (index + sizeof(BOOL) > nBufferSize) return -1;
    memcpy(&m_bNeedWaitReply, &pszBuffer[index], sizeof(BOOL));
    index += sizeof(BOOL);
    HSMS_Create1Message(m_pSendMessage, 1, 1 | REPLY, 1, 1);
    int nRet = m_pSendMessage->unserialize(&pszBuffer[index], nBufferSize - index);
    if (nRet < 0) return nRet;
    return index + nRet;
}
SourceCode/Bond/Servo/HsmsAction.h
@@ -28,6 +28,8 @@
    HANDLE getEvent();
    int responseTimeIncrement();
    BOOL incrementAndCheckTimeout();
    int serialize(char* pszBuffer, int nBufferSize);
    int unserialize(const char* pszBuffer, int nBufferSize);
private:
    int m_nAction;
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)
{
@@ -43,6 +48,7 @@
    m_listener.onCommand = nullptr;
    m_listener.onEQConstantRequest = nullptr;
    m_listener.onEQConstantSend = nullptr;
    m_pActiveAction = nullptr;
    InitializeCriticalSection(&m_criticalSection);
}
@@ -57,6 +63,10 @@
        delete item;
    }
    m_listActionSent.clear();
    for (auto item : m_listActionSpooling) {
        delete item;
    }
    m_listActionSpooling.clear();
    Unlock();
    if (m_hCimWorkEvent != NULL) {
@@ -68,11 +78,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 +103,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++);
        }
@@ -175,11 +156,24 @@
{
    LOGI("onRecvMsg:%s", pMessage->toString());
    Lock();
    if (m_pActiveAction != nullptr &&
        (m_pActiveAction->getSendMessage()->getHeader()->systemBytes == pMessage->getHeader()->systemBytes)) {
        SetEvent(m_pActiveAction->getEvent());
        LOGI("CHsmsPassive::当前等待有回复");
        TRACE("CHsmsPassive::当前等待有回复\n");
        Unlock();
        return 0;
    }
    Unlock();
    Lock();
    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);
            SetEvent(pAction->getEvent());
            m_listActionSent.erase(iter);
            break;
        }
@@ -187,12 +181,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 +464,8 @@
    auto onStatusChanged = [&](void* pFrom, STATE state) -> void {
        m_pModel->notifyInt(RX_CODE_PASSIVE_STATUS_CHANGED, (int)state);
        // è¿žä¸Šä¹‹åŽå‘S1F1
        // ä¿®æ”¹ä¸ºä¸ä¸»åŠ¨å‘é€ï¼Œè€Œæ˜¯å“åº”
        // è¿žä¸Šä¹‹åŽå‘S1F1
        // ä¿®æ”¹ä¸ºä¸ä¸»åŠ¨å‘é€ï¼Œè€Œæ˜¯å“åº”
        /*
        if (STATE::SELECTED == state) {
            m_bAreYouThereRequest = FALSE;
@@ -219,17 +478,17 @@
    };
    auto onRecvSysMessage = [&](void* pFrom, IMessage* pMessage) -> void {
        LOGI("<HSMS>onRecvSysMessage:sessionId:%d, sType:%d systemBytes:%d",
            pMessage->getHeader()->sessionId, pMessage->getHeader()->sType, pMessage->getHeader()->systemBytes);
        pMessage->getHeader()->sessionId, pMessage->getHeader()->sType, pMessage->getHeader()->systemBytes);
        onRecvMsg(pMessage);
        if (MSG_LINKTEST_REQ == pMessage->getHeader()->sType) {
            /*
            Sleep(10);
            if (!m_bAreYouThereRequest) {
                m_bAreYouThereRequest = TRUE;
                requestYouThere();
            }
            */
        /*
        Sleep(10);
        if (!m_bAreYouThereRequest) {
            m_bAreYouThereRequest = TRUE;
            requestYouThere();
        }
        */
}
    };
    auto onError = [&](void* pFrom, int error) -> void {
@@ -245,7 +504,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,8 +539,14 @@
        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);
        }
        else if (nStream == 6 && pHeader->function == 23) {
            replyPurgeSpooledData(pMessage);
        }
        else if (nStream == 7 && pHeader->function == 19) {
            replyQueryPPIDList(pMessage);
@@ -299,7 +564,7 @@
    listener.funError = onError;
    m_pPassive->setListener(listener);
    // å¯åŠ¨å·¥ä½œçº¿ç¨‹
    // å¯åŠ¨å·¥ä½œçº¿ç¨‹
    m_bCimWorking = TRUE;
    m_hCimWorkThreadHandle = (HANDLE)_beginthreadex(NULL, 0, ::CimWorkThreadFunction, this,
        0, &m_nCimWorkThrdaddr);
@@ -310,9 +575,45 @@
    return 0;
}
int CHsmsPassive::loadCacheFromFile(const char* pszFilepath)
{
    m_strCacheFilepath = pszFilepath;
    CFile file;
    if (!file.Open(m_strCacheFilepath.c_str(), CFile::modeRead) ) {
        return -1;
    }
    int nBufSize = file.GetLength();
    char* pszBuffer = new char[nBufSize];
    file.Read(pszBuffer, nBufSize);
    file.Close();
    int nRet = unserialize(pszBuffer, nBufSize);
    delete[] pszBuffer;
    return nRet;
}
int CHsmsPassive::saveCache()
{
    CFile file;
    if (!file.Open(m_strCacheFilepath.c_str(), CFile::modeWrite | CFile::modeCreate)) {
        return -1;
    }
    int nSize = serialize(nullptr, 0);
    char* pszBuffer = new char[nSize];
    int nRet = serialize(pszBuffer, nSize);
    file.Write(pszBuffer, nSize);
    file.Close();
    delete[] pszBuffer;
    return nRet;
}
int CHsmsPassive::term()
{
    // ç»“束线程
    // ç»“束线程
    m_bCimWorking = FALSE;
    SetEvent(m_hCimWorkEvent);
    if (m_hCimWorkThreadHandle != NULL) {
@@ -326,19 +627,70 @@
        m_pPassive = NULL;
    }
    clearAllVariabel();
    clearAllReport();
    clearAllCollectionEvent();
    return 0;
}
int CHsmsPassive::serialize(char* pszBuffer, int nBufferSize)
{
    int index = 0;
    if (pszBuffer == nullptr) {
        index += sizeof(int);
        for (auto item : m_listActionSpooling) {
            index += item->serialize(pszBuffer, nBufferSize);
        }
        return index;
    }
    else {
        int nTemp, nRet;
        nTemp = (int)m_listActionSpooling.size();
        memcpy(&pszBuffer[index], &nTemp, sizeof(int));
        index += sizeof(int);
        for (auto item : m_listActionSpooling) {
            nRet = item->serialize(&pszBuffer[index], nBufferSize);
            if (nRet <= 0) break;
            index += nRet;
        }
        return index;
    }
}
int CHsmsPassive::unserialize(const char* pszBuffer, int nBufferSize)
{
    int index = 0, nTemp, nRet = 0;
    if (index + sizeof(int) > nBufferSize) return -1;
    memcpy(&nTemp, &pszBuffer[index], sizeof(int));
    index += sizeof(int);
    for (int i = 0; i < nTemp; i++) {
        CHsmsAction* pAction = new CHsmsAction();
        nRet = pAction->unserialize(&pszBuffer[index], nBufferSize - index);
        if (nRet <= 0) break;
        index += nRet;
        m_listActionSpooling.push_back(pAction);
    }
    return index + nRet;
}
unsigned CHsmsPassive::OnCimWork()
{
    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);
@@ -347,39 +699,52 @@
        while (!list.empty()) {
            Lock();
            CHsmsAction* pAction = list.front();
            if (m_pPassive == NULL || STATE::SELECTED != m_pPassive->getState()) {
                m_listActionSpooling.push_back(pAction);
                Unlock();
                continue;
            }
            Unlock();
            list.pop_front();
            TRACE("OnCimWork 004.\n");
            IMessage* pMessage = pAction->getSendMessage();
            ASSERT(pMessage);
            m_pPassive->sendMessage(pMessage);
            LOGI("<HSMS> [SEND] SysByte=%u sessionId:%d", pMessage->getHeader()->systemBytes, pMessage->getHeader()->sessionId);
            if (pAction->isNeedWaitReply()) {
                // å¦‚果需要等待回复
                // å¦‚果需要等待回复
                Lock();
                m_pActiveAction = pAction;
                IMessage* pMessage = pAction->getSendMessage();
                Unlock();
                ASSERT(pMessage);
                m_pPassive->sendMessage(pMessage);
                LOGI("<HSMS> [SEND] SysByte=%u sessionId:%d", pMessage->getHeader()->systemBytes, pMessage->getHeader()->sessionId);
                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();
                    }
                }
                delete pAction;
                pAction = NULL;
                TRACE("delete m_pCurrentAction, next...\n");
                Lock();
                delete m_pActiveAction;
                m_pActiveAction = nullptr;
                Unlock();
            }
            else {
                Lock();
                m_listActionSent.push_back(pAction);
                IMessage* pMessage = pAction->getSendMessage();
                Unlock();
                ASSERT(pMessage);
                m_pPassive->sendMessage(pMessage);
                LOGI("<HSMS> [SEND] SysByte=%u sessionId:%d", pMessage->getHeader()->systemBytes, pMessage->getHeader()->sessionId);
            }
        }
        TRACE("OnCimWork \n");
@@ -390,7 +755,7 @@
    return 0;
}
// é€šç”¨çš„reply ack函数
// é€šç”¨çš„reply ack函数
void CHsmsPassive::replyAck(int s, int f, unsigned int systemBytes, BYTE ack, const char* pszAckName)
{
    IMessage* pMessage = NULL;
@@ -420,6 +785,7 @@
    SetEvent(m_hCimWorkEvent);
    Unlock();
    return ER_NOERROR;
}
@@ -453,13 +819,13 @@
    }
    // äº¤ç”±ä¸Šå±‚应用来获取机器常量值
    // äº¤ç”±ä¸Šå±‚应用来获取机器常量值
    if (m_listener.onEQOffLine != nullptr) {
        m_listener.onEQOffLine(this);
    }
    // å›žå¤
    // å›žå¤
    replyAck(1, 16, pRecv->getHeader()->systemBytes, BYTE(0), "OFLACK");
    return 0;
}
@@ -472,17 +838,18 @@
    }
    // äº¤ç”±ä¸Šå±‚应用来获取机器常量值
    // äº¤ç”±ä¸Šå±‚应用来获取机器常量值
    if (m_listener.onEQOnLine != nullptr) {
        m_listener.onEQOnLine(this);
    }
    // å›žå¤
    // å›žå¤
    replyAck(1, 18, pRecv->getHeader()->systemBytes, BYTE(0), "ONLACK");
    return 0;
}
// S1F13
int CHsmsPassive::replyEstablishCommunications(IMessage* pRecv)
{
    if (m_pPassive == NULL || STATE::SELECTED != m_pPassive->getState()) {
@@ -494,12 +861,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 +880,7 @@
    }
    // è¦èŽ·å–çš„å¸¸é‡è¡¨è¡¨
    // è¦èŽ·å–çš„å¸¸é‡è¡¨è¡¨
    BOOL bCheckData = FALSE;
    std::vector<EQConstant> eqcs;
    {
@@ -530,13 +897,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 +927,7 @@
    }
    // è¦è®¾ç½®çš„常量表表
    // è¦è®¾ç½®çš„常量表表
    BOOL bCheckData = FALSE;
    std::vector<EQConstant> eqcs;
    {
@@ -583,14 +950,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 +972,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 +990,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 +1010,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 +1082,7 @@
            else {
                for (int k = 0; k < prtCount; k++) {
                    if (rptListItem->getSubItemU4(k, rptid)) {
                        linkEventReport(rptid, ceid);
                        linkEventReport(ceid, rptid);
                    }
                }
            }
@@ -713,11 +1090,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 +1128,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 +1177,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,41 +1256,55 @@
        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);
        }
    }
MYREPLY:
    replyAck(5, 4, pRecv->getHeader()->systemBytes, BYTE(0), "ACKC5");
    return 0;
}
// S6F23
int CHsmsPassive::replyPurgeSpooledData(IMessage* pRecv)
{
    if (m_pPassive == NULL || STATE::SELECTED != m_pPassive->getState()) {
        return ER_NOTSELECT;
    }
    ISECS2Item* pBody = pRecv->getBody();
    if (pBody == nullptr || pBody->getType() != SITYPE::U1) ER_PARAM_ERROR;
    unsigned char RSDC;        // 0 - transmit; 1 - purge;
    pBody->getU1(RSDC);
    if (RSDC != 0 && RSDC != 1) ER_PARAM_ERROR;
    BYTE ACK = 0;        // 0 - ok;    1 - retryable busy;    2 - no spool data;
    if (m_listActionSpooling.empty()) {
        ACK = 2;
    }
    replyAck(6, 24, pRecv->getHeader()->systemBytes, ACK, "RSDA");
    // ä¸¢å¼ƒ
    if (RSDC == 1) {
        Lock();
        for (auto item : m_listActionSpooling) {
            delete item;
        }
        m_listActionSpooling.clear();
        Unlock();
    }
    else {
        Lock();
        for (auto item : m_listActionSpooling) {
            m_listAction.push_back(item);
        }
        m_listActionSpooling.clear();
        Unlock();
        SetEvent(m_hCimWorkEvent);
    }
    return 0;
}
@@ -932,54 +1368,66 @@
// S5F1
int CHsmsPassive::requestAlarmReport(int ALCD, int ALID, const char* ALTX)
{
    if (m_pPassive == NULL || STATE::SELECTED != m_pPassive->getState()) {
        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);
    IMessage* pMessage = NULL;
    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);
    SetEvent(m_hCimWorkEvent);
    if (m_pPassive == NULL || STATE::SELECTED != m_pPassive->getState()) {
        m_listActionSpooling.push_back(pAction);
    }
    else {
        m_listAction.push_back(pAction);
        SetEvent(m_hCimWorkEvent);
    }
    Unlock();
    return ER_NOERROR;
}
// 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();
    CHsmsAction* pAction = new CHsmsAction(ACTION_EVENT_REPORT, TRUE, m_nActionTimeout);
    m_listAction.push_back(pAction);
    IMessage* pMessage = NULL;
    HSMS_Create1Message(pMessage, m_nSessionId, 6 | REPLY, 11, ++m_nSystemByte);
    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");
    }
    pAction->setSendMessage(pMessage);
    SetEvent(m_hCimWorkEvent);
    if (m_pPassive == NULL || STATE::SELECTED != m_pPassive->getState()) {
        m_listActionSpooling.push_back(pAction);
    }
    else {
        m_listAction.push_back(pAction);
        SetEvent(m_hCimWorkEvent);
    }
    Unlock();
    
    return ER_NOERROR;
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,38 +94,65 @@
    /* è®¾ç½®è½¯ä»¶ç‰ˆæœ¬å· æœ€å¤§é•¿åº¦ 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();
    void OnTimer(UINT nTimerid);
    void setActionTimeout(int nSecond);
    int init(CModel* pModel, const char* pszName, unsigned int port);
    int loadCacheFromFile(const char* pszFilepath);
    int saveCache();
    int term();
    int serialize(char* pszBuffer, int nBufferSize);
    int unserialize(const char* pszBuffer, int nBufferSize);
public:
    /* 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,7 +169,9 @@
    int replyLinkEventReport(IMessage* pRecv);
    int replyEanbleDisableEventReport(IMessage* pRecv);
    int replyCommand(IMessage* pRecv);
    int replyConfigureSpooling(IMessage* pRecv);
    int replyEanbleDisableAlarmReport(IMessage* pRecv);
    int replyPurgeSpooledData(IMessage* pRecv);
    int replyQueryPPIDList(IMessage* pRecv);
    int replyTerminalDisplay(IMessage* pRecv);
@@ -140,6 +179,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;
@@ -153,6 +194,7 @@
    CRITICAL_SECTION m_criticalSection;
    std::list<CHsmsAction*> m_listAction;
    std::list<CHsmsAction*> m_listActionSent;
    std::list<CHsmsAction*> m_listActionSpooling;
private:
    SECSListener m_listener;
@@ -160,18 +202,20 @@
    HANDLE m_hCimWorkEvent;
    HANDLE m_hCimWorkThreadHandle;
    unsigned m_nCimWorkThrdaddr;
    std::string m_strCacheFilepath;
    CHsmsAction* m_pActiveAction;
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;
};
SourceCode/Bond/Servo/Model.cpp
@@ -58,6 +58,12 @@
    m_configuration.setPortCassetteType(index, (int)type);
}
void CModel::setPortEnable(unsigned int index, BOOL bEnable)
{
    m_master.setPortEnable(index, bEnable);
    m_configuration.setPortEnable(index, bEnable);
}
int CModel::init()
{
    CString strIniFile;
@@ -114,11 +120,36 @@
            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);
    strVarialbleFile.Format(_T("%s\\HsmsPassive.cache"), (LPTSTR)(LPCTSTR)m_strWorkDir);
    m_hsmsPassive.loadCacheFromFile(strVarialbleFile);
    SERVO::MasterListener masterListener;
@@ -178,9 +209,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.");
@@ -280,9 +313,9 @@
        notifyPtrAndInt(RX_CODE_EQ_ROBOT_TASK, pTask, nullptr, code);
    };
    masterListener.onLoadPortInUse = [&] (void* pMaster, SERVO::CEquipment* pEquipment, short scanMap) {
        LOGE("<CModel>onLoadPortInUse. scanMap = %d", scanMap);
        notifyPtr(RX_CODE_LOADPORT_INUSE, pEquipment);
    masterListener.onLoadPortStatusChanged = [&] (void* pMaster, SERVO::CEquipment* pEquipment, short status, __int64 data) {
        LOGE("<CModel>onLoadPortStatusChanged. status = %d", status);
        notifyPtr(RX_CODE_LOADPORT_STATUS_CHANGED, pEquipment);
    };
    m_master.setListener(masterListener);
@@ -306,6 +339,7 @@
int CModel::term()
{
    m_hsmsPassive.saveCache();
    m_hsmsPassive.term();
    CLog::GetLog()->SetOnLogCallback(nullptr);
    m_master.term();
SourceCode/Bond/Servo/Model.h
@@ -16,6 +16,7 @@
    void setWorkDir(const char* pszWorkDir);
    void loadPortParams();
    void setPortCassetteType(unsigned int index, SERVO::CassetteType type);
    void setPortEnable(unsigned int index, BOOL bEnable);
    int init();
    int term();
SourceCode/Bond/Servo/PageRecipe.cpp
@@ -440,7 +440,7 @@
    else {
        // enable port
        CMsgDlg msgDlg("请等待", "正在获取配方...");
        pEq->masterRecipeListRequest(0, [&](int status) -> void {
        pEq->masterRecipeListRequest(0, [&, pEq](int status) -> void {
            if (status == SS_FAILED || status == SS_TIMEOUT) {
                CString strMsg;
                strMsg.Format(status == SS_FAILED ? _T("获取配方失败!") : _T("获取配方超时!"));
@@ -460,6 +460,8 @@
                msgDlg.SetMessage((LPTSTR)(LPCTSTR)strMsg);
                msgDlg.SetMarquee(FALSE, 0);
                msgDlg.SetCompleteCode(0);
                SERVO::CRecipeList* pRecipeList = pEq->getRecipeList(0);
                FillRecipeListToListCtrl(pRecipeList);
            }
        });
        msgDlg.DoModal();
SourceCode/Bond/Servo/Servo.rc
Binary files differ
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" />
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" />
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>
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)
@@ -183,6 +189,7 @@
                SERVO::MASTERSTATE state = theApp.m_model.getMaster().getState();
                if (state == SERVO::MASTERSTATE::READY) {
                    m_pTopToolbar->GetBtn(IDC_BUTTON_RUN)->EnableWindow(TRUE);
                    m_pTopToolbar->GetBtn(IDC_BUTTON_RUN_CT)->EnableWindow(TRUE);
                    m_pTopToolbar->GetBtn(IDC_BUTTON_STOP)->EnableWindow(FALSE);
                    m_pMyStatusbar->setBackgroundColor(STATUSBAR_BK_NORMAL);
                    m_pMyStatusbar->setForegroundColor(RGB(0, 0, 0));
@@ -198,13 +205,15 @@
                }
                else if (state == SERVO::MASTERSTATE::MSERROR) {
                    m_pTopToolbar->GetBtn(IDC_BUTTON_RUN)->EnableWindow(TRUE);
                    m_pTopToolbar->GetBtn(IDC_BUTTON_RUN_CT)->EnableWindow(TRUE);
                    m_pTopToolbar->GetBtn(IDC_BUTTON_STOP)->EnableWindow(FALSE);
                    m_pMyStatusbar->setBackgroundColor(STATUSBAR_BK_ALARM);
                    m_pMyStatusbar->setForegroundColor(RGB(0, 0, 0));
                    m_pMyStatusbar->setRunTimeText("启动失败.");
                }
                else if (state == SERVO::MASTERSTATE::RUNNING) {
                else if (state == SERVO::MASTERSTATE::RUNNING || state == SERVO::MASTERSTATE::RUNNING_CONTINUOUS_TRANSFER) {
                    m_pTopToolbar->GetBtn(IDC_BUTTON_RUN)->EnableWindow(FALSE);
                    m_pTopToolbar->GetBtn(IDC_BUTTON_RUN_CT)->EnableWindow(FALSE);
                    m_pTopToolbar->GetBtn(IDC_BUTTON_STOP)->EnableWindow(TRUE);
                    m_pMyStatusbar->setBackgroundColor(STATUSBAR_BK_RUNNING);
                    m_pMyStatusbar->setForegroundColor(RGB(255, 255, 255));
@@ -241,7 +250,7 @@
                    }
                }
            }
            else if (RX_CODE_LOADPORT_INUSE == code) {
            else if (RX_CODE_LOADPORT_STATUS_CHANGED == code) {
                SERVO::CLoadPort* pLoadPort = nullptr;
                if (pAny->getPtrValue("ptr", (void*&)pLoadPort)) {
                    //CPortConfigurationDlg dlg;
@@ -250,6 +259,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 +566,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);
}
@@ -887,6 +940,18 @@
        else {
            if (theApp.m_model.getMaster().start() == 0) {
                m_pTopToolbar->GetBtn(IDC_BUTTON_RUN)->EnableWindow(FALSE);
                m_pTopToolbar->GetBtn(IDC_BUTTON_RUN_CT)->EnableWindow(FALSE);
            }
        }
    }
    else if (id == IDC_BUTTON_RUN_CT) {
        if (theApp.m_model.getMaster().getState() == SERVO::MASTERSTATE::MSERROR) {
            AfxMessageBox("当前有机台发生错误,不能启动,请确认解决问题后再尝试重新启动!");
        }
        else {
            if (theApp.m_model.getMaster().startContinuousTransfer() == 0) {
                m_pTopToolbar->GetBtn(IDC_BUTTON_RUN)->EnableWindow(FALSE);
                m_pTopToolbar->GetBtn(IDC_BUTTON_RUN_CT)->EnableWindow(FALSE);
            }
        }
    }
@@ -989,6 +1054,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;
}
@@ -1004,6 +1072,9 @@
    if (state == SERVO::MASTERSTATE::RUNNING) {
        strText.Format(_T("正在运行:%02d:%02d:%02d   %s"), h, m, s, pszSuffix);
    }
    else if (state == SERVO::MASTERSTATE::RUNNING_CONTINUOUS_TRANSFER) {
        strText.Format(_T("千传模式:%02d:%02d:%02d   %s"), h, m, s, pszSuffix);
    }
    else {
        strText.Format(_T("已运行:%02d:%02d:%02d   %s"), h, m, s, pszSuffix);
    }
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();
SourceCode/Bond/Servo/TopToolbar.cpp
@@ -27,6 +27,7 @@
{
    CDialogEx::DoDataExchange(pDX);
    DDX_Control(pDX, IDC_BUTTON_RUN, m_btnRun);
    DDX_Control(pDX, IDC_BUTTON_RUN_CT, m_btnRunCt);
    DDX_Control(pDX, IDC_BUTTON_STOP, m_btnStop);
    DDX_Control(pDX, IDC_BUTTON_ALARM, m_btnAlarm);
    DDX_Control(pDX, IDC_BUTTON_SETTINGS, m_btnSettings);
@@ -52,6 +53,7 @@
    CDialogEx::OnInitDialog();
    InitBtn(m_btnRun, "Run_High_32.ico", "Run_Gray_32.ico");
    InitBtn(m_btnRunCt, "RunCt_High_32.ico", "RunCt_Gray_32.ico");
    InitBtn(m_btnStop, "Stop_High_32.ico", "Stop_Gray_32.ico");
    InitBtn(m_btnAlarm, "Alarm_o_32.ico", "Alarm_gray_32.ico");
    InitBtn(m_btnSettings, "Settings_High_32.ico", "Settings_Gray_32.ico");
@@ -112,6 +114,11 @@
    int x = 2, y = 3;
    pItem = GetDlgItem(IDC_BUTTON_RUN);
    pItem->MoveWindow(x, y, BTN_WIDTH, nBthHeight);
    x += BTN_WIDTH;
    x += 2;
    pItem = GetDlgItem(IDC_BUTTON_RUN_CT);
    pItem->MoveWindow(x, y, BTN_WIDTH, nBthHeight);
    x += BTN_WIDTH;
    x += 2;
@@ -190,6 +197,7 @@
{
    switch (LOWORD(wParam)) {
    case IDC_BUTTON_RUN:
    case IDC_BUTTON_RUN_CT:
    case IDC_BUTTON_STOP:
    case IDC_BUTTON_ALARM:
    case IDC_BUTTON_SETTINGS:
SourceCode/Bond/Servo/TopToolbar.h
@@ -31,6 +31,7 @@
private:
    CBlButton m_btnRun;
    CBlButton m_btnRunCt;
    CBlButton m_btnStop;
    CBlButton m_btnAlarm;
    CBlButton m_btnSettings;
SourceCode/Bond/Servo/resource.h
Binary files differ
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)
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)
SourceCode/Bond/x64/Debug/Res/RunCt_Gray_32.ico
SourceCode/Bond/x64/Debug/Res/RunCt_High_32.ico
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设定值