ded981a2ac5dbb456bafce5468d7289bc45e313b..155cb7fe0dcb564729c6aecdb65815f3f0ed24e2
2026-01-13 chenluhua1980
1.ECID, DVID的查询和实现;
155cb7 对比 | 目录
2026-01-13 chenluhua1980
1.实现DVID的加载,获取等;
1cc801 对比 | 目录
已添加2个文件
已修改13个文件
1049 ■■■■ 文件已修改
SourceCode/Bond/EAPSimulator/CHsmsActive.cpp 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/EAPSimulator/CHsmsActive.h 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/EAPSimulator/EAPSimulator.rc 26 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/EAPSimulator/EAPSimulatorDlg.cpp 77 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/EAPSimulator/EAPSimulatorDlg.h 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/EAPSimulator/Resource.h 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CDataVariable.h 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CMaster.cpp 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CPageGlassList.cpp 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/ClientListDlg.cpp 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/HsmsPassive.cpp 513 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/HsmsPassive.h 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/Model.cpp 16 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/x64/Debug/DataVariableList.txt 98 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/x64/Debug/VariableList.txt 191 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/EAPSimulator/CHsmsActive.cpp
@@ -373,6 +373,17 @@
    return 0;
}
int CHsmsActive::hsmsQueryAllDataVariables()
{
    IMessage* pMessage = nullptr;
    int nRet = HSMS_Create1Message(pMessage, m_nSessionId, 1 | REPLY, 21, ++m_nSystemByte);
    // Host sends L:0 (empty list) to request all DVIDs.
    pMessage->getBody()->addItem(); // empty list
    m_pActive->sendMessage(pMessage);
    HSMS_Destroy1Message(pMessage);
    return 0;
}
int CHsmsActive::hsmsQueryAllCollectionEvents()
{
    IMessage* pMessage = nullptr;
@@ -384,6 +395,33 @@
    return 0;
}
int CHsmsActive::hsmsEquipmentConstantRequest(const std::vector<unsigned short>& ecids)
{
    IMessage* pMessage = nullptr;
    int nRet = HSMS_Create1Message(pMessage, m_nSessionId, 2 | REPLY, 13, ++m_nSystemByte);
    for (auto id : ecids) {
        pMessage->getBody()->addU2Item(id, "ECID");
    }
    m_pActive->sendMessage(pMessage);
    HSMS_Destroy1Message(pMessage);
    return 0;
}
int CHsmsActive::hsmsEquipmentConstantSend(const std::vector<std::pair<unsigned short, std::string>>& ecidValues)
{
    IMessage* pMessage = nullptr;
    int nRet = HSMS_Create1Message(pMessage, m_nSessionId, 2 | REPLY, 15, ++m_nSystemByte);
    ISECS2Item* pBody = pMessage->getBody();
    for (const auto& kv : ecidValues) {
        ISECS2Item* pEntry = pBody->addItem();
        pEntry->addU2Item(kv.first, "ECID");
        pEntry->addItem(kv.second.c_str(), "ECV");
    }
    m_pActive->sendMessage(pMessage);
    HSMS_Destroy1Message(pMessage);
    return 0;
}
int CHsmsActive::hsmsQueryPPIDList()
{
    IMessage* pMessage = nullptr;
SourceCode/Bond/EAPSimulator/CHsmsActive.h
@@ -87,7 +87,10 @@
    // æŸ¥è¯¢å˜é‡
    int hsmsSelectedEquipmentStatusRequest(unsigned int SVID);
    int hsmsQueryAllStatusVariables();      // S1F11
    int hsmsQueryAllDataVariables();        // S1F21
    int hsmsQueryAllCollectionEvents();     // S1F23
    int hsmsEquipmentConstantRequest(const std::vector<unsigned short>& ecids); // S2F13
    int hsmsEquipmentConstantSend(const std::vector<std::pair<unsigned short, std::string>>& ecidValues); // S2F15
    // æŸ¥è¯¢PPID List
    int hsmsQueryPPIDList();
SourceCode/Bond/EAPSimulator/EAPSimulator.rc
@@ -54,10 +54,10 @@
    "\r\n"
    "#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)\r\n"
    "LANGUAGE 4, 2\r\n"
    "#include ""res\\EAPSimulator.rc2""  // é—‚?Microsoft Visual C++ ç¼‚傛牞绶惃鍕カ濠?\n"
    "#include ""l.CHS\\afxres.rc""      // é–ºå¶…洤鍣紒鍕\r\n"
    "#include ""res\\EAPSimulator.rc2""  // é—‚?Microsoft Visual C++ ç¼‚傚倹鐗炵欢顐︽儍閸曨喚銈繝?\n"
    "#include ""l.CHS\\afxres.rc""      // é—å“„秴娲ら崳顖滅磼閸曨亝顐?\n"
    "#if !defined(_AFXDLL)\r\n"
    "#include ""l.CHS\\afxribbon.rc""   // MFC é–¸æ—‚喕鍏橀崠鍝勬嫲閹貉冨煑閺壜ょカ濠?\n"
    "#include ""l.CHS\\afxribbon.rc""   // MFC é—å‘Šæ¢»é æ›¢å´—姗€宕犻崫鍕闁硅矇鍐ㄧ厬闁哄銈囥偒婵?\n"
    "#endif\r\n"
    "#endif\r\n"
    "\0"
@@ -92,17 +92,17 @@
    DEFPUSHBUTTON   "确定",IDOK,113,41,50,14,WS_GROUP
END
IDD_EAPSIMULATOR_DIALOG DIALOGEX 0, 0, 469, 292
IDD_EAPSIMULATOR_DIALOG DIALOGEX 0, 0, 469, 319
STYLE DS_SETFONT | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME
EXSTYLE WS_EX_APPWINDOW
CAPTION "EAPSimulator"
FONT 9, "MS Shell Dlg", 0, 0, 0x1
BEGIN
    DEFPUSHBUTTON   "确定",IDOK,246,271,50,14,NOT WS_VISIBLE
    PUSHBUTTON      "取消",IDCANCEL,412,271,50,14,NOT WS_VISIBLE
    EDITTEXT        IDC_EDIT_LOG,7,218,455,67,ES_MULTILINE | ES_AUTOHSCROLL | ES_READONLY | WS_VSCROLL
    LTEXT           "日志:",IDC_STATIC,7,203,24,8
    GROUPBOX        "功能",IDC_STATIC,7,7,455,190
    DEFPUSHBUTTON   "确定",IDOK,246,298,50,14,NOT WS_VISIBLE
    PUSHBUTTON      "取消",IDCANCEL,412,298,50,14,NOT WS_VISIBLE
    EDITTEXT        IDC_EDIT_LOG,7,245,455,67,ES_MULTILINE | ES_AUTOHSCROLL | ES_READONLY | WS_VSCROLL
    LTEXT           "日志:",IDC_STATIC,7,234,24,8
    GROUPBOX        "功能",IDC_STATIC,7,7,455,223
    LTEXT           "IP:",IDC_STATIC,24,20,11,8
    EDITTEXT        IDC_EDIT_IP,39,17,94,14,ES_AUTOHSCROLL
    LTEXT           "Port:",IDC_STATIC,141,20,17,8
@@ -299,7 +299,7 @@
        LEFTMARGIN, 7
        RIGHTMARGIN, 462
        TOPMARGIN, 7
        BOTTOMMARGIN, 285
        BOTTOMMARGIN, 312
    END
    IDD_DIALOG_TERMINAL_DISPLAY, DIALOG
@@ -442,10 +442,10 @@
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)
LANGUAGE 4, 2
#include "res\EAPSimulator.rc2"  // éž Microsoft Visual C++ ç¼–辑的资源
#include "l.CHS\afxres.rc"      // æ ‡å‡†ç»„ä»¶
#include "res\EAPSimulator.rc2"  // é—‚?Microsoft Visual C++ ç¼‚傛牞绶惃鍕カ濠?
#include "l.CHS\afxres.rc"      // é–ºå¶…洤鍣紒鍕
#if !defined(_AFXDLL)
#include "l.CHS\afxribbon.rc"   // MFC åŠŸèƒ½åŒºå’ŒæŽ§åˆ¶æ¡èµ„æº
#include "l.CHS\afxribbon.rc"   // MFC é–¸æ—‚喕鍏橀崠鍝勬嫲閹貉冨煑閺壜ょカ濠?
#endif
#endif
SourceCode/Bond/EAPSimulator/EAPSimulatorDlg.cpp
@@ -105,7 +105,10 @@
    ON_BN_CLICKED(IDC_BUTTON_QUERY_CONTROL_STATE, &CEAPSimulatorDlg::OnBnClickedButtonQueryControlState)
    ON_BN_CLICKED(IDC_BUTTON_QUERY_PROCESS_STATE, &CEAPSimulatorDlg::OnBnClickedButtonQueryProcessState)
    ON_BN_CLICKED(IDC_BUTTON_QUERY_ALL_SVID, &CEAPSimulatorDlg::OnBnClickedButtonQueryAllSvid)
    ON_BN_CLICKED(IDC_BUTTON_QUERY_ALL_DVID, &CEAPSimulatorDlg::OnBnClickedButtonQueryAllDvid)
    ON_BN_CLICKED(IDC_BUTTON_QUERY_ALL_CEID, &CEAPSimulatorDlg::OnBnClickedButtonQueryAllCeid)
    ON_BN_CLICKED(IDC_BUTTON_QUERY_ALL_ECID, &CEAPSimulatorDlg::OnBnClickedButtonQueryAllEcid)
    ON_BN_CLICKED(IDC_BUTTON_SET_ECID, &CEAPSimulatorDlg::OnBnClickedButtonSetEcid)
    ON_BN_CLICKED(IDC_BUTTON_QUERY_CURRENT_RECIPE, &CEAPSimulatorDlg::OnBnClickedButtonQueryCurrentRecipe)
    ON_BN_CLICKED(IDC_BUTTON_PP_REQUEST, &CEAPSimulatorDlg::OnBnClickedButtonPpRequest)
END_MESSAGE_MAP()
@@ -277,6 +280,53 @@
        if (hBtn != nullptr) {
            ::SendMessage(hBtn, WM_SETFONT, (WPARAM)GetFont()->GetSafeHandle(), TRUE);
        }
    }
    // S1F21 QueryAllDVID
    {
        CRect rc(14 + 140 + 5, 152, 14 + 140 + 5 + 140, 152 + 14);
        MapDialogRect(&rc);
        HWND hBtn = ::CreateWindow(_T("BUTTON"), _T("S1F21_QueryAllDVID"),
            WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
            rc.left, rc.top, rc.Width(), rc.Height(),
            m_hWnd, (HMENU)IDC_BUTTON_QUERY_ALL_DVID, AfxGetInstanceHandle(), nullptr);
        if (hBtn != nullptr) {
            ::SendMessage(hBtn, WM_SETFONT, (WPARAM)GetFont()->GetSafeHandle(), TRUE);
        }
    }
    // S2F13 QueryAllECID
    {
        CRect rc(14 + 2 * (140 + 5), 192, 14 + 2 * (140 + 5) + 140, 192 + 14);
        MapDialogRect(&rc);
        HWND hBtn = ::CreateWindow(_T("BUTTON"), _T("S2F13_QueryAllECID"),
            WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
            rc.left, rc.top, rc.Width(), rc.Height(),
            m_hWnd, (HMENU)IDC_BUTTON_QUERY_ALL_ECID, AfxGetInstanceHandle(), nullptr);
        if (hBtn != nullptr) {
            ::SendMessage(hBtn, WM_SETFONT, (WPARAM)GetFont()->GetSafeHandle(), TRUE);
        }
    }
    // ECID edit + send (S2F15)
    {
        CRect rcEcid(14, 192, 14 + 60, 192 + 14);
        CRect rcEcv(14 + 60 + 4, 192, 14 + 60 + 4 + 60, 192 + 14);
        MapDialogRect(&rcEcid);
        MapDialogRect(&rcEcv);
        HWND hEditEcid = ::CreateWindow(_T("EDIT"), _T(""), WS_CHILD | WS_VISIBLE | WS_BORDER,
            rcEcid.left, rcEcid.top, rcEcid.Width(), rcEcid.Height(),
            m_hWnd, (HMENU)IDC_EDIT_ECID, AfxGetInstanceHandle(), nullptr);
        HWND hEditEcv = ::CreateWindow(_T("EDIT"), _T(""), WS_CHILD | WS_VISIBLE | WS_BORDER,
            rcEcv.left, rcEcv.top, rcEcv.Width(), rcEcv.Height(),
            m_hWnd, (HMENU)IDC_EDIT_ECV, AfxGetInstanceHandle(), nullptr);
        if (hEditEcid) ::SendMessage(hEditEcid, WM_SETFONT, (WPARAM)GetFont()->GetSafeHandle(), TRUE);
        if (hEditEcv) ::SendMessage(hEditEcv, WM_SETFONT, (WPARAM)GetFont()->GetSafeHandle(), TRUE);
        CRect rcBtn(14 + 60 + 4 + 60 + 4, 192, 14 + 60 + 4 + 60 + 4 + 90, 192 + 14);
        MapDialogRect(&rcBtn);
        HWND hBtn = ::CreateWindow(_T("BUTTON"), _T("S2F15_SetECID"),
            WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
            rcBtn.left, rcBtn.top, rcBtn.Width(), rcBtn.Height(),
            m_hWnd, (HMENU)IDC_BUTTON_SET_ECID, AfxGetInstanceHandle(), nullptr);
        if (hBtn) ::SendMessage(hBtn, WM_SETFONT, (WPARAM)GetFont()->GetSafeHandle(), TRUE);
    }
    // S1F3 CurrentRecipe (EQ specific) combo + button
    {
@@ -652,11 +702,38 @@
    theApp.m_model.m_pHsmsActive->hsmsQueryAllStatusVariables();
}
void CEAPSimulatorDlg::OnBnClickedButtonQueryAllDvid()
{
    theApp.m_model.m_pHsmsActive->hsmsQueryAllDataVariables();
}
void CEAPSimulatorDlg::OnBnClickedButtonQueryAllCeid()
{
    theApp.m_model.m_pHsmsActive->hsmsQueryAllCollectionEvents();
}
void CEAPSimulatorDlg::OnBnClickedButtonQueryAllEcid()
{
    // empty list => all ECID
    std::vector<unsigned short> ecids;
    ecids.push_back(2000);
    theApp.m_model.m_pHsmsActive->hsmsEquipmentConstantRequest(ecids);
}
void CEAPSimulatorDlg::OnBnClickedButtonSetEcid()
{
    // simple demo: read ECID and value from edit boxes (reuse PPID edit)
    CString sEcid, sVal;
    GetDlgItemText(IDC_EDIT_ECID, sEcid);
    GetDlgItemText(IDC_EDIT_ECV, sVal);
    unsigned short id = static_cast<unsigned short>(_ttoi(sEcid));
    std::string val = CT2A(sVal);
    std::vector<std::pair<unsigned short, std::string>> kvs;
    if (id != 0) {
        kvs.push_back({ id, val });
        theApp.m_model.m_pHsmsActive->hsmsEquipmentConstantSend(kvs);
    }
}
void CEAPSimulatorDlg::OnBnClickedButtonQueryCurrentRecipe()
{
    CString sel;
SourceCode/Bond/EAPSimulator/EAPSimulatorDlg.h
@@ -71,7 +71,10 @@
    afx_msg void OnBnClickedButtonQueryControlState();
    afx_msg void OnBnClickedButtonQueryProcessState();
    afx_msg void OnBnClickedButtonQueryAllSvid();
    afx_msg void OnBnClickedButtonQueryAllDvid();
    afx_msg void OnBnClickedButtonQueryAllCeid();
    afx_msg void OnBnClickedButtonQueryAllEcid();
    afx_msg void OnBnClickedButtonSetEcid();
    afx_msg void OnBnClickedButtonQueryCurrentRecipe();
    afx_msg void OnBnClickedButtonPpRequest();
};
SourceCode/Bond/EAPSimulator/Resource.h
@@ -71,6 +71,11 @@
#define IDC_BUTTON_QUERY_CURRENT_RECIPE 1053
#define IDC_EDIT_PPID_REQ               1054
#define IDC_BUTTON_PP_REQUEST           1055
#define IDC_BUTTON_QUERY_ALL_DVID       1056
#define IDC_BUTTON_QUERY_ALL_ECID       1057
#define IDC_EDIT_ECID                   1058
#define IDC_EDIT_ECV                    1059
#define IDC_BUTTON_SET_ECID             1060
// Next default values for new objects
// 
@@ -78,7 +83,7 @@
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE        146
#define _APS_NEXT_COMMAND_VALUE         32771
#define _APS_NEXT_CONTROL_VALUE         1056
#define _APS_NEXT_CONTROL_VALUE         1057
#define _APS_NEXT_SYMED_VALUE           101
#endif
#endif
SourceCode/Bond/Servo/CDataVariable.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,13 @@
#pragma once
#include "CVariable.h"
namespace SERVO {
    // Data Variable:语义同 CVariable,但用于 DVID(数据变量)集合。
    class CDataVariable : public CVariable
    {
    public:
        using CVariable::CVariable; // å¤ç”¨åŸºç±»æž„造
        ~CDataVariable() = default;
    };
}
SourceCode/Bond/Servo/CMaster.cpp
@@ -2214,6 +2214,34 @@
                    fireLoadPortStatus(PORT_LOAD_READY);
                    fireLoadPortStatus(PORT_EMPTY); // will also raise LoadPortNotAssoc via Model
                    break;
                case 24: { // æ¨¡æ‹Ÿ SV Data(示例:Bonder1)
                    SERVO::CEquipment* pEq = getEquipment(EQ_ID_Bonder1);
                    if (pEq != nullptr && m_listener.onSVDataReport != nullptr) {
                        static int counter = 0;
                        ++counter;
                        std::vector<CParam> params;
                        params.emplace_back("MockSV_Temp", "1", "C", 25 + (counter % 5));
                        params.emplace_back("MockSV_Pressure", "2", "kPa", 100 + (counter % 3));
                        params.emplace_back("MockSV_Speed", "3", "mm/s", 50 + (counter % 7));
                        m_listener.onSVDataReport(this, pEq, params);
                        LOGI("<Master>SIM_EAP step24: mock SVData (Bonder1), params=%zu", params.size());
                    }
                    break;
                }
                case 25: { // æ¨¡æ‹Ÿ Process Data(示例:Bonder1)
                    SERVO::CEquipment* pEq = getEquipment(EQ_ID_Bonder1);
                    if (pEq != nullptr && m_listener.onProcessDataReport != nullptr) {
                        static int counter = 0;
                        ++counter;
                        std::vector<CParam> params;
                        params.emplace_back("MockProc_CycleTime", "1", "s", 30 + (counter % 4));
                        params.emplace_back("MockProc_MaxTemp", "2", "C", 200 + (counter % 6));
                        params.emplace_back("MockProc_Result", "3", "", (counter % 2) ? 1 : 0);
                        m_listener.onProcessDataReport(this, pEq, params);
                        LOGI("<Master>SIM_EAP step25: mock ProcessData (Bonder1), params=%zu", params.size());
                    }
                    break;
                }
                default:
                    break;
                }
SourceCode/Bond/Servo/CPageGlassList.cpp
@@ -1364,7 +1364,7 @@
    if (!row.pretty.empty()) {
        CFile file;
        if (file.Open(filePath, CFile::modeCreate | CFile::modeWrite)) {
            file.Write(row.pretty.c_str(), row.pretty.length());
            file.Write(row.pretty.c_str(), (UINT)row.pretty.length());
            file.Close();
            CString strSuccess;
SourceCode/Bond/Servo/ClientListDlg.cpp
@@ -132,7 +132,7 @@
    {
        const ClientInfo& client = clients[i];
        
        int nItem = m_listClients.InsertItem(i, CString(client.ip.c_str()));
        int nItem = m_listClients.InsertItem((int)i, CString(client.ip.c_str()));
        m_listClients.SetItemText(nItem, 1, CString(std::to_string(client.port).c_str()));
        m_listClients.SetItemText(nItem, 2, client.versionOk ? _T("正常") : _T("异常"));
        m_listClients.SetItemText(nItem, 3, CString(client.status.c_str()));
SourceCode/Bond/Servo/HsmsPassive.cpp
@@ -14,6 +14,47 @@
#include <regex>
#include <sstream>
// ---- Encoding helpers ----
static bool hasUtf8Bom(const std::string& s)
{
    return s.size() >= 3 &&
        static_cast<unsigned char>(s[0]) == 0xEF &&
        static_cast<unsigned char>(s[1]) == 0xBB &&
        static_cast<unsigned char>(s[2]) == 0xBF;
}
static bool isLikelyUtf8(const std::string& s)
{
    // Simple heuristic: try to convert; if success without errors, treat as UTF-8.
    int wlen = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, s.c_str(), (int)s.size(), nullptr, 0);
    return wlen > 0;
}
static CStringW Utf8ToWide(const char* psz)
{
    if (psz == nullptr) return L"";
    int wlen = MultiByteToWideChar(CP_UTF8, 0, psz, -1, nullptr, 0);
    if (wlen <= 0) return L"";
    CStringW ws;
    LPWSTR buf = ws.GetBufferSetLength(wlen - 1);
    MultiByteToWideChar(CP_UTF8, 0, psz, -1, buf, wlen);
    ws.ReleaseBuffer();
    return ws;
}
static CStringW AnsiToWide(const char* psz)
{
    if (psz == nullptr) return L"";
    int wlen = MultiByteToWideChar(CP_ACP, 0, psz, -1, nullptr, 0);
    if (wlen <= 0) return L"";
    CStringW ws;
    LPWSTR buf = ws.GetBufferSetLength(wlen - 1);
    MultiByteToWideChar(CP_ACP, 0, psz, -1, buf, wlen);
    ws.ReleaseBuffer();
    return ws;
}
// ---- End helpers ----
// ControlState values (keep in sync with Model::ControlState / VariableList.txt)
static constexpr uint8_t kControlStateOnlineRemote = 5;
@@ -66,8 +107,6 @@
    m_listener.onEQOffLine = nullptr;
    m_listener.onEQOnLine = nullptr;
    m_listener.onCommand = nullptr;
    m_listener.onEQConstantRequest = nullptr;
    m_listener.onEQConstantSend = nullptr;
    m_pActiveAction = nullptr;
    InitializeCriticalSection(&m_criticalSection);
}
@@ -217,6 +256,9 @@
    SERVO::CReport* pReport = new SERVO::CReport(RPTID, vids);
    for (auto vid : vids) {
        SERVO::CVariable* pVariable = getVariable(vid);
        if (pVariable == nullptr) {
            pVariable = getDataVariable(vid);
        }
        if (pVariable != nullptr) {
            pReport->addVariable(pVariable);
            LOGI("<CHsmsPassive>defineReport RPTID=%d", RPTID);
@@ -424,9 +466,195 @@
    return 0;
}
int CHsmsPassive::loadDataVarialbles(const char* pszFilepath)
{
    if (pszFilepath == NULL) {
        return -1;
    }
    m_strDataVariableFilepath = pszFilepath;
    m_bDataVariableUtf8 = false;
    m_bDataVariableUtf8Bom = false;
    CFile file;
    if (!file.Open(pszFilepath, CFile::modeRead | CFile::shareDenyNone)) {
        return -1;
    }
    const ULONGLONG nLen = file.GetLength();
    if (nLen == 0) {
        return -1;
    }
    std::string buffer;
    buffer.resize(static_cast<size_t>(nLen));
    file.Read(buffer.data(), static_cast<UINT>(nLen));
    file.Close();
    if (hasUtf8Bom(buffer)) {
        m_bDataVariableUtf8 = true;
        m_bDataVariableUtf8Bom = true;
        buffer = buffer.substr(3);
    }
    else if (isLikelyUtf8(buffer)) {
        m_bDataVariableUtf8 = true;
    }
    CStringW content = m_bDataVariableUtf8 ? Utf8ToWide(buffer.c_str()) : AnsiToWide(buffer.c_str());
    // Regex: DVID,DV Name,DV Format,DV Remark
    std::wregex pattern(L"^\\d+,[^,]*,[^,]*,.*");
    std::vector<SERVO::CDataVariable*> dataVars;
    int index;
    CStringW strLine, strId, strName, strFormat, strRemark;
    std::wstringstream ss(content.GetString());
    auto narrowFromW = [](const CStringW& s) -> std::string {
        int need = WideCharToMultiByte(CP_ACP, 0, s, -1, nullptr, 0, nullptr, nullptr);
        if (need <= 0) return {};
        std::string out(static_cast<size_t>(need - 1), '\0');
        WideCharToMultiByte(CP_ACP, 0, s, -1, out.data(), need, nullptr, nullptr);
        return out;
    };
    std::wstring line;
    while (std::getline(ss, line, L'\n')) {
        strLine = line.c_str();
        strLine.Trim();
        if (strLine.IsEmpty()) continue;
        if (!std::regex_match(static_cast<LPCWSTR>(strLine), pattern)) {
            continue;
        }
        index = strLine.Find(L",", 0);
        if (index < 0) continue;
        strId = strLine.Left(index);
        strLine = strLine.Right(strLine.GetLength() - index - 1);
        index = strLine.Find(L",", 0);
        if (index < 0) continue;
        strName = strLine.Left(index);
        strLine = strLine.Right(strLine.GetLength() - index - 1);
        index = strLine.Find(L",", 0);
        if (index < 0) continue;
        strFormat = strLine.Left(index);
        strRemark = strLine.Right(strLine.GetLength() - index - 1);
        strRemark.Replace(L"\\r\\n", L"\r\n");
        std::string sId = narrowFromW(strId);
        std::string sName = narrowFromW(strName);
        std::string sFormat = narrowFromW(strFormat);
        std::string sRemark = narrowFromW(strRemark);
        SERVO::CDataVariable* pVarialble = new SERVO::CDataVariable(
            sId.c_str(),
            sName.c_str(),
            sFormat.c_str(),
            sRemark.c_str());
        dataVars.push_back(pVarialble);
    }
    if (!dataVars.empty()) {
        clearAllDataVariabel();
        for (auto item : dataVars) {
            m_dataVariabels.push_back(item);
        }
    }
    return 0;
}
int CHsmsPassive::loadEquipmentConstants(const char* pszFilepath)
{
    if (pszFilepath == NULL) return -1;
    m_strEquipmentConstantFilepath = pszFilepath;
    m_bEquipmentConstantUtf8 = false;
    m_bEquipmentConstantUtf8Bom = false;
    CFile file;
    if (!file.Open(pszFilepath, CFile::modeRead | CFile::shareDenyNone)) {
        return -1;
    }
    const ULONGLONG nLen = file.GetLength();
    if (nLen == 0) {
        return -1;
    }
    std::string buffer;
    buffer.resize(static_cast<size_t>(nLen));
    file.Read(buffer.data(), static_cast<UINT>(nLen));
    file.Close();
    if (hasUtf8Bom(buffer)) {
        m_bEquipmentConstantUtf8 = true;
        m_bEquipmentConstantUtf8Bom = true;
        buffer = buffer.substr(3);
    }
    else if (isLikelyUtf8(buffer)) {
        m_bEquipmentConstantUtf8 = true;
    }
    CStringW content = m_bEquipmentConstantUtf8 ? Utf8ToWide(buffer.c_str()) : AnsiToWide(buffer.c_str());
    if (content.IsEmpty()) return -1;
    std::wregex pattern(L"^\\d+,[^,]*,[^,]*,([^,]*),.*");
    std::vector<EquipmentConstantEntry> constants;
    CStringW strLine, strId, strName, strFormat, strRemark, strDefault;
    std::wstringstream ss(content.GetString());
    auto narrowFromW = [](const CStringW& s) -> std::string {
        int need = WideCharToMultiByte(CP_ACP, 0, s, -1, nullptr, 0, nullptr, nullptr);
        if (need <= 0) return {};
        std::string out(static_cast<size_t>(need - 1), '\0');
        WideCharToMultiByte(CP_ACP, 0, s, -1, out.data(), need, nullptr, nullptr);
        return out;
    };
    std::wstring line;
    while (std::getline(ss, line, L'\n')) {
        strLine = line.c_str();
        strLine.Trim();
        if (strLine.IsEmpty()) continue;
        if (strLine.Find(L"ECID") == 0) continue; // skip header
        if (!std::regex_match(static_cast<LPCWSTR>(strLine), pattern)) {
            continue;
        }
        int last = 0;
        int idx = strLine.Find(L",", last);
        if (idx < 0) continue;
        strId = strLine.Left(idx);
        last = idx + 1;
        idx = strLine.Find(L",", last);
        if (idx < 0) continue;
        strName = strLine.Mid(last, idx - last);
        last = idx + 1;
        idx = strLine.Find(L",", last);
        if (idx < 0) continue;
        strFormat = strLine.Mid(last, idx - last);
        last = idx + 1;
        idx = strLine.Find(L",", last);
        if (idx < 0) continue;
        strRemark = strLine.Mid(last, idx - last);
        last = idx + 1;
        strDefault = strLine.Right(strLine.GetLength() - last);
        EquipmentConstantEntry entry;
        entry.id = _wtoi(strId);
        entry.name = narrowFromW(strName);
        entry.format = narrowFromW(strFormat);
        entry.remark = narrowFromW(strRemark);
        entry.value = narrowFromW(strDefault);
        constants.push_back(entry);
    }
    if (!constants.empty()) {
        m_equipmentConstants = std::move(constants);
    }
    return 0;
}
std::vector<SERVO::CVariable*>& CHsmsPassive::getVariables()
{
    return m_variabels;
}
std::vector<SERVO::CDataVariable*>& CHsmsPassive::getDataVariables()
{
    return m_dataVariabels;
}
unsigned int CHsmsPassive::getMaxVariableId() const
@@ -458,7 +686,30 @@
            return item;
        }
    }
    // try numeric id string
    if (pszName != nullptr && *pszName) {
        const int id = atoi(pszName);
        if (id > 0) {
            return getVariable(id);
        }
    }
    return nullptr;
}
SERVO::CDataVariable* CHsmsPassive::getDataVariable(int dvid)
{
    for (auto item : m_dataVariabels) {
        if (item->getVarialbleId() == (unsigned int)dvid) return item;
    }
    return nullptr;
}
SERVO::CDataVariable* CHsmsPassive::getDataVariable(const char* pszName)
{
    for (auto item : m_dataVariabels) {
        if (item->getName().compare(pszName) == 0) return item;
    }
    return nullptr;
}
@@ -483,6 +734,14 @@
        delete item;
    }
    m_variabels.clear();
}
void CHsmsPassive::clearAllDataVariabel()
{
    for (auto item : m_dataVariabels) {
        delete item;
    }
    m_dataVariabels.clear();
}
CStringA WideToUtf8(const CStringW& ws)
@@ -545,6 +804,9 @@
    if (auto v = getVariable(pszName)) {
        v->setValue(value);
    }
    else if (auto dv = getDataVariable(pszName)) {
        dv->setValue(value);
    }
    Unlock();
}
@@ -554,6 +816,9 @@
    if (auto v = getVariable(pszName)) {
        v->setValue(value);
    }
    else if (auto dv = getDataVariable(pszName)) {
        dv->setValue(value);
    }
    Unlock();
}
@@ -562,6 +827,9 @@
    Lock();
    if (auto v = getVariable(pszName)) {
        v->setValue(vars);
    }
    else if (auto dv = getDataVariable(pszName)) {
        dv->setValue(vars);
    }
    Unlock();
}
@@ -678,6 +946,53 @@
    return 0;
}
int CHsmsPassive::writeDataVariablesToFile(const std::string& filepath)
{
    if (filepath.empty()) return -3;
    CFile file;
    if (!file.Open(filepath.c_str(), CFile::modeCreate | CFile::modeWrite | CFile::shareDenyNone)) {
        return -3;
    }
    const std::string headerAnsi = "DVID,DV Name,DV Format,DV Remark\r\n";
    if (m_bDataVariableUtf8) {
        if (m_bDataVariableUtf8Bom) {
            const BYTE bom[3] = { 0xEF, 0xBB, 0xBF };
            file.Write(bom, 3);
        }
        CStringA header = AnsiToUtf8(headerAnsi);
        file.Write(header.GetString(), header.GetLength());
    }
    else {
        file.Write(headerAnsi.data(), (UINT)headerAnsi.size());
    }
    for (auto v : m_dataVariabels) {
        if (v == nullptr) continue;
        std::string lineAnsi;
        lineAnsi.reserve(256);
        lineAnsi += std::to_string(v->getVarialbleId());
        lineAnsi.push_back(',');
        lineAnsi += v->getName();
        lineAnsi.push_back(',');
        lineAnsi += SERVO::CVariable::formatToString(v->getFormat());
        lineAnsi.push_back(',');
        lineAnsi += v->getRemark();
        lineAnsi.append("\r\n");
        if (m_bDataVariableUtf8) {
            CStringA outLine = AnsiToUtf8(lineAnsi);
            file.Write(outLine.GetString(), outLine.GetLength());
        }
        else {
            file.Write(lineAnsi.data(), (UINT)lineAnsi.size());
        }
    }
    file.Close();
    return 0;
}
int CHsmsPassive::loadReports(const char* pszFilepath)
{
    m_strReportFilepath = pszFilepath;
@@ -790,6 +1105,9 @@
        SERVO::CReport* pReport = new SERVO::CReport(_wtoi(strId), vids);
        for (auto vid : vids) {
            SERVO::CVariable* pVariable = getVariable(vid);
            if (pVariable == nullptr) {
                pVariable = getDataVariable(vid);
            }
            if (pVariable != nullptr) {
                pReport->addVariable(pVariable);
            }
@@ -868,6 +1186,9 @@
    SERVO::CReport* pReport = new SERVO::CReport(rptid, vids);
    for (auto vid : vids) {
        SERVO::CVariable* pVariable = getVariable((int)vid);
        if (pVariable == nullptr) {
            pVariable = getDataVariable((int)vid);
        }
        if (pVariable != nullptr) {
            pReport->addVariable(pVariable);
        }
@@ -884,6 +1205,9 @@
            SERVO::CReport* pReport = new SERVO::CReport(rptid, vids);
            for (auto vid : vids) {
                SERVO::CVariable* pVariable = getVariable((int)vid);
                if (pVariable == nullptr) {
                    pVariable = getDataVariable((int)vid);
                }
                if (pVariable != nullptr) {
                    pReport->addVariable(pVariable);
                }
@@ -1323,6 +1647,9 @@
        }
        else if (nStream == 1 && pHeader->function == 11) {
            replyStatusVariableNamelistRequest(pMessage);
        }
        else if (nStream == 1 && pHeader->function == 21) {
            replyDataVariableNamelistRequest(pMessage);
        }
        else if (nStream == 1 && pHeader->function == 23) {
            replyCollectionEventNamelistRequest(pMessage);
@@ -1941,6 +2268,109 @@
    return ER_NOERROR;
}
int CHsmsPassive::writeEquipmentConstantsToFile(const std::string& filepath)
{
    if (filepath.empty()) return -1;
    CFile file;
    if (!file.Open(filepath.c_str(), CFile::modeCreate | CFile::modeWrite | CFile::shareDenyNone)) {
        return -1;
    }
    const std::string headerAnsi = "ECID,EC Name,EC Format,EC Remark,Default Value\r\n";
    if (m_bEquipmentConstantUtf8) {
        if (m_bEquipmentConstantUtf8Bom) {
            const BYTE bom[3] = { 0xEF, 0xBB, 0xBF };
            file.Write(bom, 3);
        }
        CStringA header = AnsiToUtf8(headerAnsi);
        file.Write(header.GetString(), header.GetLength());
    }
    else {
        file.Write(headerAnsi.data(), (UINT)headerAnsi.size());
    }
    for (const auto& e : m_equipmentConstants) {
        std::string line;
        line.reserve(128);
        line += std::to_string(e.id);
        line.push_back(',');
        line += e.name;
        line.push_back(',');
        line += e.format;
        line.push_back(',');
        line += e.remark;
        line.push_back(',');
        line += e.value;
        line.append("\r\n");
        if (m_bEquipmentConstantUtf8) {
            CStringA out = AnsiToUtf8(line);
            file.Write(out.GetString(), out.GetLength());
        }
        else {
            file.Write(line.data(), (UINT)line.size());
        }
    }
    file.Close();
    return 0;
}
// S1F21/S1F22 - Data Variable Namelist
int CHsmsPassive::replyDataVariableNamelistRequest(IMessage* pRecv)
{
    if (m_pPassive == NULL || STATE::SELECTED != m_pPassive->getState()) {
        return ER_NOTSELECT;
    }
    std::vector<unsigned short> reqIds;
    ISECS2Item* pBody = pRecv->getBody();
    if (pBody != nullptr && pBody->getType() == SITYPE::L) {
        const int sz = pBody->getSubItemSize();
        for (int i = 0; i < sz; ++i) {
            unsigned short id = 0;
            if (pBody->getSubItemU2(i, id)) {
                reqIds.push_back(id);
            }
        }
    }
    std::vector<unsigned short> dvids;
    std::set<unsigned short> requested(reqIds.begin(), reqIds.end());
    Lock();
    if (reqIds.empty()) {
        for (auto v : m_dataVariabels) {
            if (v) dvids.push_back(static_cast<unsigned short>(v->getVarialbleId()));
        }
    }
    else {
        for (auto id : requested) dvids.push_back(id);
    }
    Unlock();
    IMessage* pMessage = NULL;
    HSMS_Create1Message(pMessage, m_nSessionId, 1, 22, pRecv->getHeader()->systemBytes);
    ASSERT(pMessage);
    ISECS2Item* pList = pMessage->getBody(); // L[n] of {DVID, DVNAME, UNITS}
    for (auto id : dvids) {
        ISECS2Item* pEntry = pList->addItem();
        pEntry->addU2Item(id, "DVID");
        SERVO::CDataVariable* v = getDataVariable((int)id);
        if (v != nullptr) {
            pEntry->addItem(v->getName().c_str(), "DVNAME");
            pEntry->addItem(v->getRemark().c_str(), "UNITS");
        }
        else {
            pEntry->addItem("", "DVNAME");
            pEntry->addItem("", "UNITS");
        }
    }
    m_pPassive->sendMessage(pMessage);
    LOGI("<HSMS>[SEND]sessionId:%d, sType:%d systemBytes:%d",
        pMessage->getHeader()->sessionId, pMessage->getHeader()->sType, pMessage->getHeader()->systemBytes);
    LogSecsMessageBrief("<HSMS>[SEND]", pMessage);
    HSMS_Destroy1Message(pMessage);
    return ER_NOERROR;
}
// S1F23
int CHsmsPassive::replyCollectionEventNamelistRequest(IMessage* pRecv)
{
@@ -2039,32 +2469,42 @@
    }
    // è¦èŽ·å–çš„å¸¸é‡è¡¨è¡¨
    BOOL bCheckData = FALSE;
    std::vector<EQConstant> eqcs;
    {
        ISECS2Item* pItem = pRecv->getBody();
        int ecidSize = pItem->getSubItemSize();
        const int ecidSize = pItem ? pItem->getSubItemSize() : 0;
        for (int i = 0; i < ecidSize; i++) {
            EQConstant eqc;
            unsigned short id;
            if (pItem->getSubItemU2(i, id)) {
            EQConstant eqc{};
            unsigned short id = 0;
            if (pItem && pItem->getSubItemU2(i, id)) {
                eqc.id = id;
                eqcs.push_back(eqc);
            }
        }
    }
    // äº¤ç”±ä¸Šå±‚应用来获取机器常量值
    if (m_listener.onEQConstantRequest != nullptr) {
        m_listener.onEQConstantRequest(this, eqcs);
    // ç©ºåˆ—表表示请求全部 ECID
    if (eqcs.empty()) {
        for (const auto& e : m_equipmentConstants) {
            EQConstant eqc{};
            eqc.id = e.id;
            strcpy_s(eqc.szValue, EQCONSTANT_VALUE_MAX, e.value.c_str());
            eqcs.push_back(eqc);
        }
    } else {
        for (auto& item : eqcs) {
            auto it = std::find_if(m_equipmentConstants.begin(), m_equipmentConstants.end(),
                [&](const EquipmentConstantEntry& e) { return e.id == item.id; });
            if (it != m_equipmentConstants.end()) {
                strcpy_s(item.szValue, EQCONSTANT_VALUE_MAX, it->value.c_str());
            } else {
                item.szValue[0] = '\0'; // unknown -> empty
            }
        }
    }
    // å›žå¤
    IMessage* pMessage = NULL;
    HSMS_Create1Message(pMessage, m_nSessionId, 1, 14, pRecv->getHeader()->systemBytes);
    HSMS_Create1Message(pMessage, m_nSessionId, 2, 14, pRecv->getHeader()->systemBytes);
    ASSERT(pMessage);
    ISECS2Item* pItem = pMessage->getBody();
    for (auto& item : eqcs) {
@@ -2088,33 +2528,38 @@
    }
    // è¦è®¾ç½®çš„常量表表
    BOOL bCheckData = FALSE;
    // è¦è®¾ç½®çš„常量表
    std::vector<EQConstant> eqcs;
    {
        ISECS2Item* pItem = pRecv->getBody();
        int ecidSize = pItem->getSubItemSize();
        int ecidSize = pItem ? pItem->getSubItemSize() : 0;
        for (int i = 0; i < ecidSize; i++) {
            ISECS2Item* pItemEqc = pItem->getSubItem(i);
            if (pItemEqc != nullptr) {
                EQConstant eqc;
                unsigned short eqcid;
                const char* pszValue;
                if (pItemEqc->getSubItemU2(0, eqcid)
                    && pItemEqc->getSubItemString(1, pszValue)) {
                    eqc.id = eqcid;
                    strcpy_s(eqc.szValue, EQCONSTANT_VALUE_MAX, pszValue);
                    eqcs.push_back(eqc);
                }
            ISECS2Item* pItemEqc = pItem ? pItem->getSubItem(i) : nullptr;
            if (pItemEqc == nullptr) continue;
            EQConstant eqc{};
            unsigned short eqcid = 0;
            const char* pszValue = nullptr;
            if (pItemEqc->getSubItemU2(0, eqcid)
                && pItemEqc->getSubItemString(1, pszValue)) {
                eqc.id = eqcid;
                strcpy_s(eqc.szValue, EQCONSTANT_VALUE_MAX, pszValue);
                eqcs.push_back(eqc);
            }
        }
    }
    // äº¤ç”±ä¸Šå±‚应用来保存和设置机器常量值
    std::vector<unsigned int> ecvs;
    if (m_listener.onEQConstantSend != nullptr) {
        m_listener.onEQConstantSend(this, eqcs);
    // æ›´æ–°å†…存表并落盘
    bool changed = false;
    for (auto& item : eqcs) {
        auto it = std::find_if(m_equipmentConstants.begin(), m_equipmentConstants.end(),
            [&](const EquipmentConstantEntry& e) { return e.id == item.id; });
        if (it != m_equipmentConstants.end()) {
            it->value = item.szValue;
            changed = true;
        }
    }
    if (changed && !m_strEquipmentConstantFilepath.empty()) {
        writeEquipmentConstantsToFile(m_strEquipmentConstantFilepath);
    }
SourceCode/Bond/Servo/HsmsPassive.h
@@ -9,6 +9,7 @@
#include "CCollectionEvent.h"
#include "ProcessJob.h"
#include "CControlJob.h"
#include "CDataVariable.h"
#define EQCONSTANT_VALUE_MAX    64
@@ -78,7 +79,6 @@
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;
@@ -97,8 +97,6 @@
{
    SECSEQOFFLINE                onEQOffLine;
    SECSEQOFFLINE                onEQOnLine;
    SECSEQCONSTANTREQUEST        onEQConstantRequest;
    SECSEQCONSTANTREQUEST        onEQConstantSend;
    SECSCommand                    onCommand;
    DATETIMESYNC                onDatetimeSync;
    EDEVENTREPORT                onEnableDisableEventReport;
@@ -146,14 +144,21 @@
    // ä»Žæ–‡ä»¶ä¸­åŠ è½½CVariable列表
    int loadVarialbles(const char* pszFilepath);
    // ä»Žæ–‡ä»¶ä¸­åŠ è½½CDataVariable列表
    int loadDataVarialbles(const char* pszFilepath);
    // ä»Žæ–‡ä»¶ä¸­åŠ è½½Equipment Constant列表
    int loadEquipmentConstants(const char* pszFilepath);
    // å–å¾—CVariable列表
    std::vector<SERVO::CVariable*>& getVariables();
    unsigned int getMaxVariableId() const;
    std::vector<SERVO::CDataVariable*>& getDataVariables();
    // å–得指定Variable
    SERVO::CVariable* getVariable(int variableId);
    SERVO::CVariable* getVariable(const char* pszName);
    SERVO::CDataVariable* getDataVariable(int dvid);
    SERVO::CDataVariable* getDataVariable(const char* pszName);
    int getCurrentControlState();
    bool isHostCommandAllowed();
    int deleteVariable(int variableId);
@@ -239,6 +244,7 @@
    int replyEstablishCommunications(IMessage* pRecv);
    int replySelectedEquipmentStatusData(IMessage* pRecv);
    int replyStatusVariableNamelistRequest(IMessage* pRecv);  // S1F11/S1F12
    int replyDataVariableNamelistRequest(IMessage* pRecv);    // S1F21/S1F22
    int replyCollectionEventNamelistRequest(IMessage* pRecv); // S1F23/S1F24
    int replyOnLine(IMessage* pRecv);
    int replyOffLine(IMessage* pRecv);
@@ -265,8 +271,11 @@
    inline void Unlock() { LeaveCriticalSection(&m_criticalSection); }
    int onRecvMsg(IMessage* pMessage);
    void clearAllVariabel();
    void clearAllDataVariabel();
    std::vector<unsigned int> parseVidList(CString& strNums);
    int writeVariablesToFile(const std::string& filepath);
    int writeDataVariablesToFile(const std::string& filepath);
    int writeEquipmentConstantsToFile(const std::string& filepath);
    int writeReportsToFile(const std::string& filepath);
    int writeCollectionEventsToFile(const std::string& filepath);
@@ -289,12 +298,18 @@
    std::string m_strVariableFilepath;
    bool m_bVariableUtf8{ false };
    bool m_bVariableUtf8Bom{ false };
    std::string m_strDataVariableFilepath;
    bool m_bDataVariableUtf8{ false };
    bool m_bDataVariableUtf8Bom{ false };
    std::string m_strReportFilepath;
    bool m_bReportUtf8{ false };
    bool m_bReportUtf8Bom{ false };
    std::string m_strCollectionEventFilepath;
    bool m_bCollectionUtf8{ false };
    bool m_bCollectionUtf8Bom{ false };
    std::string m_strEquipmentConstantFilepath;
    bool m_bEquipmentConstantUtf8{ false };
    bool m_bEquipmentConstantUtf8Bom{ false };
    BOOL m_bCimWorking;
    HANDLE m_hCimWorkEvent;
    HANDLE m_hCimWorkThreadHandle;
@@ -305,6 +320,17 @@
private:
    // CVariable vector
    std::vector<SERVO::CVariable*> m_variabels;
    // CDataVariable vector
    std::vector<SERVO::CDataVariable*> m_dataVariabels;
    // Equipment constants
    struct EquipmentConstantEntry {
        unsigned int id{ 0 };
        std::string name;
        std::string format;
        std::string remark;
        std::string value;
    };
    std::vector<EquipmentConstantEntry> m_equipmentConstants;
    // CReport vector
    std::vector<SERVO::CReport*> m_reports;
SourceCode/Bond/Servo/Model.cpp
@@ -168,18 +168,6 @@
            setControlState(ControlState::OnlineRemote);
        }
    };
    listener.onEQConstantRequest = [&](void* pFrom, std::vector<EQConstant>& eqcs) -> void {
        // åœ¨æ­¤å¡«å……常量值,目前仅是加1后返回
        for (auto& item : eqcs) {
            sprintf_s(item.szValue, EQCONSTANT_VALUE_MAX, "Test%d", item.id + 1);
        }
    };
    listener.onEQConstantSend = [&](void* pFrom, std::vector<EQConstant>& eqcs) -> void {
        // åœ¨æ­¤ä¿å­˜å’Œè®¾ç½®æœºå™¨å¸¸é‡å€¼
        for (auto& item : eqcs) {
            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);
@@ -311,6 +299,10 @@
    CString strVarialbleFile;
    strVarialbleFile.Format(_T("%s\\VariableList.txt"), (LPTSTR)(LPCTSTR)m_strWorkDir);
    m_hsmsPassive.loadVarialbles((LPTSTR)(LPCTSTR)strVarialbleFile);
    strVarialbleFile.Format(_T("%s\\DataVariableList.txt"), (LPTSTR)(LPCTSTR)m_strWorkDir);
    m_hsmsPassive.loadDataVarialbles((LPTSTR)(LPCTSTR)strVarialbleFile);
    strVarialbleFile.Format(_T("%s\\EquipmentConstantList.txt"), (LPTSTR)(LPCTSTR)m_strWorkDir);
    m_hsmsPassive.loadEquipmentConstants((LPTSTR)(LPCTSTR)strVarialbleFile);
    setControlState(m_currentControlState);
    refreshDerivedSVs();
    m_hsmsPassive.init(this, "APP", 7000);
SourceCode/Bond/x64/Debug/DataVariableList.txt
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,98 @@
DVID,DV Name,DV Format,DV Remark
6000,Bonder_SV_ProcessStep,A20,Bonder SV: å·¥è‰ºè¿è¡Œæ­¥éª¤
6001,Bonder_SV_BladderPressure,A20,Bonder SV: æ°”囊压力当前
6002,Bonder_SV_UpperChamberPressure,A20,Bonder SV: ä¸Šè…”压力合计
6003,Bonder_SV_PipeVacuumGauge,A20,Bonder SV: ç®¡é“真空表
6004,Bonder_SV_ChamberVacuumGauge,A20,Bonder SV: è…”体真空表
6005,Bonder_SV_UpperTemp1,A20,Bonder SV: ä¸Šè…”温度1
6006,Bonder_SV_UpperTemp2,A20,Bonder SV: ä¸Šè…”温度2
6007,Bonder_SV_UpperTemp3,A20,Bonder SV: ä¸Šè…”温度3
6008,Bonder_SV_UpperTemp4,A20,Bonder SV: ä¸Šè…”温度4
6009,Bonder_SV_UpperTemp5,A20,Bonder SV: ä¸Šè…”温度5
6010,Bonder_SV_UpperTemp6,A20,Bonder SV: ä¸Šè…”温度6
6011,Bonder_SV_LowerTemp1,A20,Bonder SV: ä¸‹è…”温度1
6012,Bonder_SV_LowerTemp2,A20,Bonder SV: ä¸‹è…”温度2
6013,Bonder_SV_LowerTemp3,A20,Bonder SV: ä¸‹è…”温度3
6014,Bonder_SV_LowerTemp4,A20,Bonder SV: ä¸‹è…”温度4
6015,Bonder_SV_LowerTemp5,A20,Bonder SV: ä¸‹è…”温度5
6016,Bonder_SV_LowerTemp6,A20,Bonder SV: ä¸‹è…”温度6
6017,Bonder_SV_HeatingRemaining,A20,Bonder SV: åŠ çƒ­å‰©ä½™æ—¶é—´
6018,Bonder_SV_PressingRemaining,A20,Bonder SV: åŽ‹åˆå‰©ä½™æ—¶é—´
6100,Bonder_PD_AlignDelay,A20,Bonder PD: å¯¹ä½å»¶æ—¶
6101,Bonder_PD_DwellTime,A20,Bonder PD: ä¿åŽ‹æ—¶é—´
6102,Bonder_PD_BreakVacuumDelay,A20,Bonder PD: ç ´çœŸç©ºå»¶æ—¶
6103,Bonder_PD_TurboPumpStartDelay,A20,Bonder PD: åˆ†å­æ³µå¯åŠ¨å»¶æ—¶
6104,Bonder_PD_AttachVacuumDelay,A20,Bonder PD: æŠ½çœŸç©ºå»¶æ—¶
6105,Bonder_PD_HeatingWaitDelay,A20,Bonder PD: ç­‰å¾…加热延时
6106,Bonder_PD_BladderPressureSet,A20,Bonder PD: æ°”囊压力设定
6107,Bonder_PD_BladderPressurizeRate,A20,Bonder PD: æ°”囊加压速率
6108,Bonder_PD_BladderDepressurizeRate,A20,Bonder PD: æ°”囊泄压速率
6109,Bonder_PD_AttachPressureLimit,A20,Bonder PD: è´´åˆåŽ‹åŠ›ä¸Šé™
6110,Bonder_PD_UpperZTorqueSpeed,A20,Bonder PD: ä¸Šè…”Z预贴合速度
6111,Bonder_PD_UpperTempSet,A20,Bonder PD: ä¸Šè…”温度设定
6112,Bonder_PD_LowerTempSet,A20,Bonder PD: ä¸‹è…”温度设定
6113,Bonder_PD_PreAttachSpeed,A20,Bonder PD: é¢„贴合速度
6114,Bonder_PD_AttachSpeed,A20,Bonder PD: è´´åˆé€Ÿåº¦
6115,Bonder_PD_UpperHeatDistance,A20,Bonder PD: ä¸Šè…”加热距离
6116,Bonder_PD_AttachPressIn,A20,Bonder PD: è´´åˆåŽ‹å…¥åŠ›
6117,Bonder_PD_UpperBreakVacuumDist,A20,Bonder PD: ä¸Šè…”破真空距离
6118,Bonder_PD_LowerPinBreakVacuumDist,A20,Bonder PD: ä¸‹é¡¶é’ˆç ´çœŸç©ºè·ç¦»
6119,Bonder_PD_LowerPinHeatDistance,A20,Bonder PD: ä¸‹é¡¶é’ˆåŠ çƒ­è·ç¦»
6120,Bonder_PD_PumpGaugeSet,A20,Bonder PD: çœŸç©ºæ³µçœŸç©ºè®¾å®š
6121,Bonder_PD_TurboReachSet,A20,Bonder PD: åˆ†å­æ³µåˆ°è¾¾è®¾å®š
6200,VacuumBake_SV_A_ProcessStep,A20,VacuumBake SV A: å·¥è‰ºè¿è¡Œæ­¥éª¤
6201,VacuumBake_SV_A_ChamberVacuum,A20,VacuumBake SV A: è…”体真空
6202,VacuumBake_SV_A_Temp1,A20,VacuumBake SV A: æ¸©åº¦1
6203,VacuumBake_SV_A_Temp2,A20,VacuumBake SV A: æ¸©åº¦2
6204,VacuumBake_SV_A_Temp4,A20,VacuumBake SV A: æ¸©åº¦4
6205,VacuumBake_SV_A_Temp5,A20,VacuumBake SV A: æ¸©åº¦5
6206,VacuumBake_SV_A_Temp6,A20,VacuumBake SV A: æ¸©åº¦6
6207,VacuumBake_SV_A_Temp7,A20,VacuumBake SV A: æ¸©åº¦7
6208,VacuumBake_SV_A_BakeRemaining,A20,VacuumBake SV A: çƒ˜çƒ¤å‰©ä½™æ—¶é—´
6209,VacuumBake_SV_B_ProcessStep,A20,VacuumBake SV B: å·¥è‰ºè¿è¡Œæ­¥éª¤
6210,VacuumBake_SV_B_ChamberVacuum,A20,VacuumBake SV B: è…”体真空
6211,VacuumBake_SV_B_Temp1,A20,VacuumBake SV B: æ¸©åº¦1
6212,VacuumBake_SV_B_Temp2,A20,VacuumBake SV B: æ¸©åº¦2
6213,VacuumBake_SV_B_Temp4,A20,VacuumBake SV B: æ¸©åº¦4
6214,VacuumBake_SV_B_Temp5,A20,VacuumBake SV B: æ¸©åº¦5
6215,VacuumBake_SV_B_Temp6,A20,VacuumBake SV B: æ¸©åº¦6
6216,VacuumBake_SV_B_Temp7,A20,VacuumBake SV B: æ¸©åº¦7
6217,VacuumBake_SV_B_BakeRemaining,A20,VacuumBake SV B: çƒ˜çƒ¤å‰©ä½™æ—¶é—´
6300,VacuumBake_PD_ParamIndex,A20,VacuumBake PD: å‚数序号
6301,VacuumBake_PD_HeatTime,A20,VacuumBake PD: åŠ çƒ­æ—¶é—´
6302,VacuumBake_PD_BreakVacuumTime,A20,VacuumBake PD: ç ´çœŸç©ºæ—¶é—´
6303,VacuumBake_PD_VacuumReach,A20,VacuumBake PD: çœŸç©ºè¾¾åˆ°å€¼
6304,VacuumBake_PD_TempSet,A20,VacuumBake PD: ä¸»æŽ§æ¸©åº¦è®¾å®š
6400,BakeCooling_SV_A_BakeStep,A20,BakeCooling SV A: çƒ˜çƒ¤æ­¥éª¤
6401,BakeCooling_SV_A_Temp1,A20,BakeCooling SV A: æ¸©åº¦1
6402,BakeCooling_SV_A_Temp2,A20,BakeCooling SV A: æ¸©åº¦2
6403,BakeCooling_SV_A_Temp4,A20,BakeCooling SV A: æ¸©åº¦4
6404,BakeCooling_SV_A_Temp5,A20,BakeCooling SV A: æ¸©åº¦5
6405,BakeCooling_SV_A_Temp6,A20,BakeCooling SV A: æ¸©åº¦6
6406,BakeCooling_SV_A_Temp7,A20,BakeCooling SV A: æ¸©åº¦7
6407,BakeCooling_SV_A_BakeRemaining,A20,BakeCooling SV A: çƒ˜çƒ¤å‰©ä½™æ—¶é—´
6408,BakeCooling_SV_A_CoolStep,A20,BakeCooling SV A: å†·å´æ­¥éª¤
6409,BakeCooling_SV_A_CoolRemaining,A20,BakeCooling SV A: å†·å´å‰©ä½™æ—¶é—´
6410,BakeCooling_SV_B_BakeStep,A20,BakeCooling SV B: çƒ˜çƒ¤æ­¥éª¤
6411,BakeCooling_SV_B_Temp1,A20,BakeCooling SV B: æ¸©åº¦1
6412,BakeCooling_SV_B_Temp2,A20,BakeCooling SV B: æ¸©åº¦2
6413,BakeCooling_SV_B_Temp4,A20,BakeCooling SV B: æ¸©åº¦4
6414,BakeCooling_SV_B_Temp5,A20,BakeCooling SV B: æ¸©åº¦5
6415,BakeCooling_SV_B_Temp6,A20,BakeCooling SV B: æ¸©åº¦6
6416,BakeCooling_SV_B_Temp7,A20,BakeCooling SV B: æ¸©åº¦7
6417,BakeCooling_SV_B_BakeRemaining,A20,BakeCooling SV B: çƒ˜çƒ¤å‰©ä½™æ—¶é—´
6418,BakeCooling_SV_B_CoolStep,A20,BakeCooling SV B: å†·å´æ­¥éª¤
6419,BakeCooling_SV_B_CoolRemaining,A20,BakeCooling SV B: å†·å´å‰©ä½™æ—¶é—´
6500,BakeCooling_PD_ParamIndex,A20,BakeCooling PD: å‚数序号
6501,BakeCooling_PD_TimeOrTemp1,A20,BakeCooling PD: æ—¶é—´/温度1
6502,BakeCooling_PD_TimeOrTemp2,A20,BakeCooling PD: æ—¶é—´/温度2
6503,BakeCooling_PD_Reserved,A20,BakeCooling PD: é¢„ç•™
6600,Measurement_SV_ProcessStep,A20,Measurement SV: å·¥è‰ºè¿è¡Œæ­¥éª¤
6601,Measurement_SV_AOIScore,A20,Measurement SV: AOI分数
6700,Measurement_PD_ParamIndex,A20,Measurement PD: å‚数序号
6701,Measurement_PD_Time,A20,Measurement PD: æ—¶é—´
6702,Measurement_PD_Value1,A20,Measurement PD: æµ‹é‡å€¼1
6703,Measurement_PD_Value2,A20,Measurement PD: æµ‹é‡å€¼2
10200,SlotMap,U2,SlotMap(Scan)
10201,SlotMapScan,U2,SlotMap(Scan)
10202,SlotMapDownload,U2,SlotMap(Download)
SourceCode/Bond/x64/Debug/VariableList.txt
@@ -1,161 +1,36 @@
SVID,SV Name,SV Format,SV Remark
100,PortTransferState,U1,0=OutOfService
300,AccessMode,U1,1=Manual
500,Clock,A50,
600,CurrentControlState,U1,0:Offline:equipment
601,PreviousControlState,U1,
700,CurrentProcessState,U1,0:DOWN
701,PreviousProcessState,U1,
800,EFEMPPExecName,A20,
801,EQPPExecName,A20,
8100,Bonder1CurrentRecipe,A50,
8101,Bonder2CurrentRecipe,A50,
8102,VacuumBakeCurrentRecipe,A50,
8103,BakeCoolingCurrentRecipe,A50,
8104,MeasurementCurrentRecipe,A50,
8105,EFEMCurrentRecipe,A50,
2000,RbRAxisTorque,I2,机器人R轴扭矩
2001,RbLAxisTorque,U1,机器人L轴扭矩
2002,RbZAxisTorque,U1,机器人Z轴扭矩
2003,RbTHAxisTorque,U1,机器人TH轴扭矩
2004,RbXAxisTorque,U1,机器人X轴扭矩
2005,AxisX111,U1,X111相机前移栽电机扭矩
2006,AxisX112,U1,X112相机后移栽电机扭矩
2007,AxisU113,U1,U113产品旋转电机扭矩
2008,AxisX114,U1,X114产品左整列电机扭矩
2009,AxisY121,U1,Y121产品右整列电机扭矩
2010,AxisY122,U1,Y122产品前整列电机扭矩
2011,AxisY123,U1,Y123产品后阵列电机扭矩
2012,MainAir,U1,总进气压力值
2013,MainVacuum,U1,总真空压力值
2014,RbMainVacuum,U1,机器人真空值
2015,LPMainVacuum,U1,LP真空值#D265
2016,LPMainAir,U1,LP压空值
2017,ALVacuum,U1,Aligner真空值
2018,FFU1RPM,U1,FFU1转速
2019,FFU2RPM,U1,FFU2转速
2020,FFU3RPM,U1,FFU3转速
2021,FFU4RPM,U1,FFU4转速
2022,ESDValue,I2,静电检测值
2023,OCREnable,U1,"OCR使能:O:开启 1:屏蔽"
2024,CCDEnable,U1,"CCD使能:O:开启 1:屏蔽"
2025,FFUParameter,U1,FFU设定值
5000,CarrierID,A20,卡匣ID
100,PortTransferState,U1,0=OutOfService;1=ReadyToLoad/LoadRequest;2=Loaded;3=InUse/LoadComplete;4=ReadyToUnload/UnloadRequest;5=Empty/UnloadComplete;6=TransferBlocked
300,AccessMode,U1,0=Auto;1=Manual
500,Clock,A50,Current timestamp string
600,CurrentControlState,U1,0=OfflineEquipment;1=OfflineAttempt;2=Online;3=OfflineHost;4=OnlineLocal;5=OnlineRemote
601,PreviousControlState,U1,Previous control state (same code set as CurrentControlState)
700,CurrentProcessState,U1,0=Ready;1=Processing;2=Complete;3=Error
701,PreviousProcessState,U1,Previous process state (0=Ready;1=Processing;2=Complete;3=Error)
800,EFEMPPExecName,A20,Current PPExec name from EFEM
801,EQPPExecName,A20,Current PPExec name from equipment
8100,Bonder1CurrentRecipe,A50,Current recipe for Bonder1
8101,Bonder2CurrentRecipe,A50,Current recipe for Bonder2
8102,VacuumBakeCurrentRecipe,A50,Current recipe for VacuumBake
8103,BakeCoolingCurrentRecipe,A50,Current recipe for BakeCooling
8104,MeasurementCurrentRecipe,A50,Current recipe for Measurement
8105,EFEMCurrentRecipe,A50,Current recipe for EFEM
5001,CJobSpace,U1,CJ Space
5002,PJobSpace,U1,PJ Space
5003,PJQueued,L,PJ Queued
5004,PJStartID,A20,PJStartID
5005,PJEndID,A20,PJEndID
5006,PanelStartID,A20,PanelStartID
5007,PanelEndID,A20,PanelEndID
5008,CJStartID,A20,CJStartID
5009,CJEndID,A20,CJEndID
5010,UnloadReadyPortId,U1,"Port ID"
5011,LoadReadyPortId,U1,"Port ID"
5012,BlockedPortId,U1,"Port ID"
5013,TestVID,U1,测试添加变量55
5014,VCRPanelID,A20,Panel id,来自读码器
5015,ReadyToReleasePortId,U1,"Port ID"
5016,LoadPortNotAssocPortId,U1,"Port ID"
5017,ProcessDataReportText,A50,EV_PROCESS_DATA_REPORT payload string (placeholder)
5018,SubEqpName,A20,Equipment name for EV_SubEqpStart/EV_SubEqpEnd
5019,SubEqpSlot,U1,Slot number for EV_SubEqpStart/EV_SubEqpEnd
5020,PortStateChangePortId,U1,"Port ID for PortStateChange"
5021,PortState,U1,"Port transfer/state code for PortStateChange"
6000,Bonder_SV_ProcessStep,A20,Bonder SV
6001,Bonder_SV_BladderPressure,A20,Bonder SV
6002,Bonder_SV_UpperChamberPressure,A20,Bonder SV
6003,Bonder_SV_PipeVacuumGauge,A20,Bonder SV
6004,Bonder_SV_ChamberVacuumGauge,A20,Bonder SV
6005,Bonder_SV_UpperTemp1,A20,Bonder SV
6006,Bonder_SV_UpperTemp2,A20,Bonder SV
6007,Bonder_SV_UpperTemp3,A20,Bonder SV
6008,Bonder_SV_UpperTemp4,A20,Bonder SV
6009,Bonder_SV_UpperTemp5,A20,Bonder SV
6010,Bonder_SV_UpperTemp6,A20,Bonder SV
6011,Bonder_SV_LowerTemp1,A20,Bonder SV
6012,Bonder_SV_LowerTemp2,A20,Bonder SV
6013,Bonder_SV_LowerTemp3,A20,Bonder SV
6014,Bonder_SV_LowerTemp4,A20,Bonder SV
6015,Bonder_SV_LowerTemp5,A20,Bonder SV
6016,Bonder_SV_LowerTemp6,A20,Bonder SV
6017,Bonder_SV_HeatingRemaining,A20,Bonder SV
6018,Bonder_SV_PressingRemaining,A20,Bonder SV
6100,Bonder_PD_AlignDelay,A20,Bonder ProcessData
6101,Bonder_PD_DwellTime,A20,Bonder ProcessData
6102,Bonder_PD_BreakVacuumDelay,A20,Bonder ProcessData
6103,Bonder_PD_TurboPumpStartDelay,A20,Bonder ProcessData
6104,Bonder_PD_AttachVacuumDelay,A20,Bonder ProcessData
6105,Bonder_PD_HeatingWaitDelay,A20,Bonder ProcessData
6106,Bonder_PD_BladderPressureSet,A20,Bonder ProcessData
6107,Bonder_PD_BladderPressurizeRate,A20,Bonder ProcessData
6108,Bonder_PD_BladderDepressurizeRate,A20,Bonder ProcessData
6109,Bonder_PD_AttachPressureLimit,A20,Bonder ProcessData
6110,Bonder_PD_UpperZTorqueSpeed,A20,Bonder ProcessData
6111,Bonder_PD_UpperTempSet,A20,Bonder ProcessData
6112,Bonder_PD_LowerTempSet,A20,Bonder ProcessData
6113,Bonder_PD_PreAttachSpeed,A20,Bonder ProcessData
6114,Bonder_PD_AttachSpeed,A20,Bonder ProcessData
6115,Bonder_PD_UpperHeatDistance,A20,Bonder ProcessData
6116,Bonder_PD_AttachPressIn,A20,Bonder ProcessData
6117,Bonder_PD_UpperBreakVacuumDist,A20,Bonder ProcessData
6118,Bonder_PD_LowerPinBreakVacuumDist,A20,Bonder ProcessData
6119,Bonder_PD_LowerPinHeatDistance,A20,Bonder ProcessData
6120,Bonder_PD_PumpGaugeSet,A20,Bonder ProcessData
6121,Bonder_PD_TurboReachSet,A20,Bonder ProcessData
6200,VacuumBake_SV_A_ProcessStep,A20,VacuumBake SV
6201,VacuumBake_SV_A_ChamberVacuum,A20,VacuumBake SV
6202,VacuumBake_SV_A_Temp1,A20,VacuumBake SV
6203,VacuumBake_SV_A_Temp2,A20,VacuumBake SV
6204,VacuumBake_SV_A_Temp4,A20,VacuumBake SV
6205,VacuumBake_SV_A_Temp5,A20,VacuumBake SV
6206,VacuumBake_SV_A_Temp6,A20,VacuumBake SV
6207,VacuumBake_SV_A_Temp7,A20,VacuumBake SV
6208,VacuumBake_SV_A_BakeRemaining,A20,VacuumBake SV
6209,VacuumBake_SV_B_ProcessStep,A20,VacuumBake SV
6210,VacuumBake_SV_B_ChamberVacuum,A20,VacuumBake SV
6211,VacuumBake_SV_B_Temp1,A20,VacuumBake SV
6212,VacuumBake_SV_B_Temp2,A20,VacuumBake SV
6213,VacuumBake_SV_B_Temp4,A20,VacuumBake SV
6214,VacuumBake_SV_B_Temp5,A20,VacuumBake SV
6215,VacuumBake_SV_B_Temp6,A20,VacuumBake SV
6216,VacuumBake_SV_B_Temp7,A20,VacuumBake SV
6217,VacuumBake_SV_B_BakeRemaining,A20,VacuumBake SV
6300,VacuumBake_PD_ParamIndex,A20,VacuumBake ProcessData
6301,VacuumBake_PD_HeatTime,A20,VacuumBake ProcessData
6302,VacuumBake_PD_BreakVacuumTime,A20,VacuumBake ProcessData
6303,VacuumBake_PD_VacuumReach,A20,VacuumBake ProcessData
6304,VacuumBake_PD_TempSet,A20,VacuumBake ProcessData
6400,BakeCooling_SV_A_BakeStep,A20,BakeCooling SV
6401,BakeCooling_SV_A_Temp1,A20,BakeCooling SV
6402,BakeCooling_SV_A_Temp2,A20,BakeCooling SV
6403,BakeCooling_SV_A_Temp4,A20,BakeCooling SV
6404,BakeCooling_SV_A_Temp5,A20,BakeCooling SV
6405,BakeCooling_SV_A_Temp6,A20,BakeCooling SV
6406,BakeCooling_SV_A_Temp7,A20,BakeCooling SV
6407,BakeCooling_SV_A_BakeRemaining,A20,BakeCooling SV
6408,BakeCooling_SV_A_CoolStep,A20,BakeCooling SV
6409,BakeCooling_SV_A_CoolRemaining,A20,BakeCooling SV
6410,BakeCooling_SV_B_BakeStep,A20,BakeCooling SV
6411,BakeCooling_SV_B_Temp1,A20,BakeCooling SV
6412,BakeCooling_SV_B_Temp2,A20,BakeCooling SV
6413,BakeCooling_SV_B_Temp4,A20,BakeCooling SV
6414,BakeCooling_SV_B_Temp5,A20,BakeCooling SV
6415,BakeCooling_SV_B_Temp6,A20,BakeCooling SV
6416,BakeCooling_SV_B_Temp7,A20,BakeCooling SV
6417,BakeCooling_SV_B_BakeRemaining,A20,BakeCooling SV
6418,BakeCooling_SV_B_CoolStep,A20,BakeCooling SV
6419,BakeCooling_SV_B_CoolRemaining,A20,BakeCooling SV
6500,BakeCooling_PD_ParamIndex,A20,BakeCooling ProcessData
6501,BakeCooling_PD_TimeOrTemp1,A20,BakeCooling ProcessData
6502,BakeCooling_PD_TimeOrTemp2,A20,BakeCooling ProcessData
6503,BakeCooling_PD_Reserved,A20,BakeCooling ProcessData
6600,Measurement_SV_ProcessStep,A20,Measurement SV
6601,Measurement_SV_AOIScore,A20,Measurement SV
6700,Measurement_PD_ParamIndex,A20,Measurement ProcessData
6701,Measurement_PD_Time,A20,Measurement ProcessData
6702,Measurement_PD_Value1,A20,Measurement ProcessData
6703,Measurement_PD_Value2,A20,Measurement ProcessData
10200,SlotMap,U2,SlotMap(Scan)
10201,SlotMapScan,U2,SlotMap(Scan)
10202,SlotMapDownload,U2,SlotMap(Download)
5003,PJQueued,L,PJ queued list (IDs)
5004,PJStartID,A20,PJ start ID
5005,PJEndID,A20,PJ end ID
5006,PanelStartID,A20,Panel start ID
5007,PanelEndID,A20,Panel end ID
5008,CJStartID,A20,CJ start ID
5009,CJEndID,A20,CJ end ID
5010,UnloadReadyPortId,U1,Port ID (ReadyToUnload)
5011,LoadReadyPortId,U1,Port ID (ReadyToLoad)
5012,BlockedPortId,U1,Port ID (TransferBlocked)
5014,VCRPanelID,A20,Panel ID from reader
5015,ReadyToReleasePortId,U1,Port ID (ReadyToRelease)
5016,LoadPortNotAssocPortId,U1,Port ID (LoadPortNotAssoc)
5017,ProcessDataReportText,A50,EV_PROCESS_DATA_REPORT payload (placeholder)
5018,SubEqpName,A20,Sub equipment name for SubEqp events
5019,SubEqpSlot,U1,Slot number for SubEqp events
5020,PortStateChangePortId,U1,Port ID for PortStateChange
5021,PortState,U1,Port transfer/state code for PortStateChange