已修改19个文件
1262 ■■■■ 文件已修改
SourceCode/Bond/EAPSimulator/CHsmsActive.cpp 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/EAPSimulator/CHsmsActive.h 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/EAPSimulator/EAPSimulatorDlg.cpp 63 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/EAPSimulator/EAPSimulatorDlg.h 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/EAPSimulator/Resource.h 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CBonder.cpp 236 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CBonder.h 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CEquipment.cpp 149 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CEquipment.h 53 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CMaster.cpp 18 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CMaster.h 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CParam.cpp 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CParam.h 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/HsmsPassive.cpp 224 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/HsmsPassive.h 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/Model.cpp 306 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/x64/Debug/CollectionEventList.txt 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/x64/Debug/ReportList.txt 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/x64/Debug/VariableList.txt 96 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/EAPSimulator/CHsmsActive.cpp
@@ -5,6 +5,19 @@
static unsigned short DATAID = 1;
// Truncated SECS message logging to avoid overly long strings crashing UI/log
static void LogSecsMessageBrief(const char* tag, IMessage* pMessage, size_t maxLen = 1024)
{
    if (pMessage == nullptr) return;
    const char* msgStr = pMessage->toString();
    if (msgStr == nullptr) return;
    std::string buf(msgStr);
    if (buf.size() > maxLen) {
        buf = buf.substr(0, maxLen) + "...<truncated>";
    }
    LOGI("%s%s", tag, buf.c_str());
}
CHsmsActive::CHsmsActive()
{
    m_listener = {};
@@ -65,8 +78,8 @@
        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());
        LogSecsMessageBrief("Body:", pMessage);
        LogSecsMessageBrief("onRecvDataMessage:", pMessage);
        if (nStream == 5 && pHeader->function == 1) {
            // S5F1
@@ -349,6 +362,28 @@
    return 0;
}
int CHsmsActive::hsmsQueryAllStatusVariables()
{
    IMessage* pMessage = nullptr;
    int nRet = HSMS_Create1Message(pMessage, m_nSessionId, 1 | REPLY, 11, ++m_nSystemByte);
    // Host sends L:0 (empty list) to request all SVIDs.
    pMessage->getBody()->addItem(); // empty list
    m_pActive->sendMessage(pMessage);
    HSMS_Destroy1Message(pMessage);
    return 0;
}
int CHsmsActive::hsmsQueryAllCollectionEvents()
{
    IMessage* pMessage = nullptr;
    int nRet = HSMS_Create1Message(pMessage, m_nSessionId, 1 | REPLY, 23, ++m_nSystemByte);
    // Host sends L:0 (empty list) to request all CEIDs.
    pMessage->getBody()->addItem(); // empty list
    m_pActive->sendMessage(pMessage);
    HSMS_Destroy1Message(pMessage);
    return 0;
}
int CHsmsActive::hsmsQueryPPIDList()
{
    IMessage* pMessage = nullptr;
SourceCode/Bond/EAPSimulator/CHsmsActive.h
@@ -1,4 +1,4 @@
#pragma once
#pragma once
#include <string>
#include <vector>
#include <map>
@@ -8,6 +8,7 @@
#define SVID_ControlState           600
#define SVID_CurrentProcessState    700
#define SVID_CJobSpace            5001
#define SVID_PJobSpace                5002
#define SVID_PJobQueued                5003
@@ -37,7 +38,7 @@
    // Deselect Request
    int hsmsDeselectRequest();
    // 建立通讯(S1F13)
    // 建立通讯(S1F13)
    int hsmsEstablishCommunications();
    // Are You There
@@ -72,18 +73,20 @@
    // Configure Spooling
    int hsmsConfigureSpooling(std::map<unsigned int, std::set<unsigned int>>& spoolingConfig);
    // 发送或清空缓存的消息
    // 发送或清空缓存的消息
    int hsmsTransmitSpooledData();
    int hsmsPurgeSpooledData();
    // 查询变量
    // 查询变量
    int hsmsSelectedEquipmentStatusRequest(unsigned int SVID);
    int hsmsQueryAllStatusVariables();      // S1F11
    int hsmsQueryAllCollectionEvents();     // S1F23
    // 查询PPID List
    // 查询PPID List
    int hsmsQueryPPIDList();
    // S3F17
    // 卡匣动作请求
    // 卡匣动作请求
    int hsmsCarrierActionRequest(unsigned int DATAID, 
        const char* pszCarrierAction,
        const char* pszCarrierId,
@@ -107,7 +110,7 @@
    // S14F9
    int hsmsCreateControlJob(const char* pszControlJobId, std::vector<std::string>& processJobIds);
    // 通过的reply函数
    // 通过的reply函数
    void replyAck(int s, int f, unsigned int systemBytes, BYTE ack, const char* pszAckName);
    // reply ack0
SourceCode/Bond/EAPSimulator/EAPSimulatorDlg.cpp
@@ -102,6 +102,9 @@
    ON_BN_CLICKED(IDC_BUTTON_CTRL_ONLINE_LOCAL, &CEAPSimulatorDlg::OnBnClickedButtonCtrlOnlineLocal)
    ON_BN_CLICKED(IDC_BUTTON_CTRL_ONLINE_REMOTE, &CEAPSimulatorDlg::OnBnClickedButtonCtrlOnlineRemote)
    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_CEID, &CEAPSimulatorDlg::OnBnClickedButtonQueryAllCeid)
END_MESSAGE_MAP()
@@ -236,6 +239,42 @@
            ::SendMessage(hBtn, WM_SETFONT, (WPARAM)GetFont()->GetSafeHandle(), TRUE);
        }
    }
    // S1F3 Query ProcessState (SVID=700) button
    {
        CRect rc(14 + 140 + 5, 136, 14 + 140 + 5 + 140, 136 + 14); // dialog units, same row offset
        MapDialogRect(&rc);
        HWND hBtn = ::CreateWindow(_T("BUTTON"), _T("S1F3_QueryProcessState"),
            WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
            rc.left, rc.top, rc.Width(), rc.Height(),
            m_hWnd, (HMENU)IDC_BUTTON_QUERY_PROCESS_STATE, AfxGetInstanceHandle(), nullptr);
        if (hBtn != nullptr) {
            ::SendMessage(hBtn, WM_SETFONT, (WPARAM)GetFont()->GetSafeHandle(), TRUE);
        }
    }
    // S1F11 QueryAllSVID
    {
        CRect rc(14 + 140 + 5 + 140 + 5, 136, 14 + 140 + 5 + 140 + 5 + 140, 136 + 14); // dialog units, next row
        MapDialogRect(&rc);
        HWND hBtn = ::CreateWindow(_T("BUTTON"), _T("S1F11_QueryAllSVID"),
            WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
            rc.left, rc.top, rc.Width(), rc.Height(),
            m_hWnd, (HMENU)IDC_BUTTON_QUERY_ALL_SVID, AfxGetInstanceHandle(), nullptr);
        if (hBtn != nullptr) {
            ::SendMessage(hBtn, WM_SETFONT, (WPARAM)GetFont()->GetSafeHandle(), TRUE);
        }
    }
    // S1F23 QueryAllCEID
    {
        CRect rc(14, 152, 14 + 140, 152 + 14); // dialog units, next row
        MapDialogRect(&rc);
        HWND hBtn = ::CreateWindow(_T("BUTTON"), _T("S1F23_QueryAllCEID"),
            WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
            rc.left, rc.top, rc.Width(), rc.Height(),
            m_hWnd, (HMENU)IDC_BUTTON_QUERY_ALL_CEID, AfxGetInstanceHandle(), nullptr);
        if (hBtn != nullptr) {
            ::SendMessage(hBtn, WM_SETFONT, (WPARAM)GetFont()->GetSafeHandle(), TRUE);
        }
    }
    SetDlgItemText(IDC_EDIT_IP, _T("127.0.0.1"));
    SetDlgItemInt(IDC_EDIT_PORT, 7000);
@@ -361,6 +400,15 @@
    }
    if (GetDlgItem(IDC_BUTTON_QUERY_CONTROL_STATE) != nullptr) {
        GetDlgItem(IDC_BUTTON_QUERY_CONTROL_STATE)->EnableWindow(enabled);
    }
    if (GetDlgItem(IDC_BUTTON_QUERY_PROCESS_STATE) != nullptr) {
        GetDlgItem(IDC_BUTTON_QUERY_PROCESS_STATE)->EnableWindow(enabled);
    }
    if (GetDlgItem(IDC_BUTTON_QUERY_ALL_SVID) != nullptr) {
        GetDlgItem(IDC_BUTTON_QUERY_ALL_SVID)->EnableWindow(enabled);
    }
    if (GetDlgItem(IDC_BUTTON_QUERY_ALL_CEID) != nullptr) {
        GetDlgItem(IDC_BUTTON_QUERY_ALL_CEID)->EnableWindow(enabled);
    }
}
@@ -531,3 +579,18 @@
{
    theApp.m_model.m_pHsmsActive->hsmsSelectedEquipmentStatusRequest(SVID_ControlState);
}
void CEAPSimulatorDlg::OnBnClickedButtonQueryProcessState()
{
    theApp.m_model.m_pHsmsActive->hsmsSelectedEquipmentStatusRequest(SVID_CurrentProcessState);
}
void CEAPSimulatorDlg::OnBnClickedButtonQueryAllSvid()
{
    theApp.m_model.m_pHsmsActive->hsmsQueryAllStatusVariables();
}
void CEAPSimulatorDlg::OnBnClickedButtonQueryAllCeid()
{
    theApp.m_model.m_pHsmsActive->hsmsQueryAllCollectionEvents();
}
SourceCode/Bond/EAPSimulator/EAPSimulatorDlg.h
@@ -68,4 +68,7 @@
    afx_msg void OnBnClickedButtonCtrlOnlineLocal();
    afx_msg void OnBnClickedButtonCtrlOnlineRemote();
    afx_msg void OnBnClickedButtonQueryControlState();
    afx_msg void OnBnClickedButtonQueryProcessState();
    afx_msg void OnBnClickedButtonQueryAllSvid();
    afx_msg void OnBnClickedButtonQueryAllCeid();
};
SourceCode/Bond/EAPSimulator/Resource.h
@@ -62,6 +62,9 @@
#define IDC_BUTTON_CTRL_ONLINE_LOCAL    1044
#define IDC_BUTTON_CTRL_ONLINE_REMOTE   1045
#define IDC_BUTTON_QUERY_CONTROL_STATE  1046
#define IDC_BUTTON_QUERY_PROCESS_STATE  1047
#define IDC_BUTTON_QUERY_ALL_SVID       1048
#define IDC_BUTTON_QUERY_ALL_CEID       1049
// Next default values for new objects
// 
@@ -69,7 +72,7 @@
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE        143
#define _APS_NEXT_COMMAND_VALUE         32771
#define _APS_NEXT_CONTROL_VALUE         1047
#define _APS_NEXT_CONTROL_VALUE         1050
#define _APS_NEXT_SYMED_VALUE           101
#endif
#endif
SourceCode/Bond/Servo/CBonder.cpp
@@ -1,4 +1,4 @@
#include "stdafx.h"
#include "stdafx.h"
#include "CBonder.h"
@@ -29,10 +29,10 @@
        CEquipment::term();
    }
    // 必须要实现的虚函数,在此初始化Pin列表
    // 必须要实现的虚函数,在此初始化Pin列表
    void CBonder::initPins()
    {
        // 加入Pin初始化代码
        // 加入Pin初始化代码
        LOGI("<CBonder>initPins");
        addPin(SERVO::PinType::INPUT, _T("In1"));
        addPin(SERVO::PinType::INPUT, _T("In2"));
@@ -137,8 +137,8 @@
        {
            // CIM Message Confirm
            // 要将int32的值拆分为两个short, 分别为msg id和panel id
            // 65538, 2Ϊmsg id, 1Ϊpanel id
            // 要将int32的值拆分为两个short, 分别为msg id和panel id
            // 65538, 2为msg id, 1为panel id
            CEqReadIntStep* pStep = new CEqReadIntStep(__INT32, m_nIndex == 0 ? 0x9d80 : 0xdd80);
            pStep->setName(STEP_EQ_CIM_MESSAGE_CONFIRM);
            pStep->setWriteSignalDev(m_nIndex == 0 ? 0x349 : 0x649);
@@ -178,7 +178,7 @@
        }
        {
            // 请求主配方列表的step
            // 请求主配方列表的step
            CEqWriteStep* pStep = new CEqWriteStep();
            pStep->setName(STEP_EQ_MASTER_RECIPE_LIST_REQ);
            pStep->setWriteSignalDev(m_nIndex == 0 ? 0x366 : 0x666);
@@ -195,7 +195,7 @@
                    CEqReadStep* pTmpStep = (CEqReadStep*)pFrom;
                    short ret = MRLRC_OK;
                    if (code == ROK && pszData != nullptr && size > 0) {
                        // 此处解释配方数据
                        // 此处解释配方数据
                        ret = decodeRecipeListReport(pszData, size);
                    }
                    pTmpStep->setReturnCode(ret);
@@ -210,7 +210,7 @@
        }
        {
            // 请求配方参数
            // 请求配方参数
            CEqWriteStep* pStep = new CEqWriteStep();
            pStep->setName(STEP_EQ_RECIPE_PARAMETER_REQ);
            pStep->setWriteSignalDev(m_nIndex == 0 ? 0x367 : 0x667);
@@ -227,7 +227,7 @@
                    CEqReadStep* pTmpStep = (CEqReadStep*)pFrom;
                    short ret = MRLRC_OK;
                    if (code == ROK && pszData != nullptr && size > 0) {
                        // 此处解释配方数据
                        // 此处解释配方数据
                        ret = decodeRecipeParameterReport(pszData, size);
                    }
                    pTmpStep->setReturnCode(ret);
@@ -241,7 +241,7 @@
            }
        }
        // 使用CEqReadStep替换CEqJobEventStep
        // 使用CEqReadStep替换CEqJobEventStep
        {
            // Received Job Report Upstream #1~9
            char szBuffer[256];
@@ -404,7 +404,7 @@
        }
    }
    // 必须要实现的虚函数,在此初始化Slot信息
    // 必须要实现的虚函数,在此初始化Slot信息
    void CBonder::initSlots()
    {
        m_slot[0].enable();
@@ -487,35 +487,35 @@
        return 0;
    }
    int CBonder::onProcessStateChanged(int slotNo, PROCESS_STATE state)
    int CBonder::onProcessStateChanged(int slotNo, PROCESS_STATE prevState, PROCESS_STATE state)
    {
        CEquipment::onProcessStateChanged(slotNo, state);
        CEquipment::onProcessStateChanged(slotNo, prevState, state);
        if (state == PROCESS_STATE::Complete) {
            // 检查数据,当前两片玻璃,一片为G1, 一片为G2, 且pProcessData中的id能匹配G1或G2
            // 检查数据,当前两片玻璃,一片为G1, 一片为G2, 且pProcessData中的id能匹配G1或G2
            Lock();
            CGlass* pGlass2 = getGlassFromSlot(1);
            CGlass* pGlass1 = getGlassFromSlot(2);
            if (pGlass1 == nullptr || pGlass2 == nullptr) {
                LOGE("<CBonder-%s>onProcessData,错误!不满足两片玻璃且分别为G1与G2的条件,请检查数据是否正确!", m_strName.c_str());
                LOGE("<CBonder-%s>onProcessData,错误!不满足两片玻璃且分别为G1与G2的条件,请检查数据是否正确!", m_strName.c_str());
                Unlock();
                return -1;
            }
            if (pGlass1->getBuddy() != nullptr) {
                LOGE("<CBonder-%s>onProcessData,错误!玻璃较早前已被绑定,请检查数据是否正确!", m_strName.c_str());
                LOGE("<CBonder-%s>onProcessData,错误!玻璃较早前已被绑定,请检查数据是否正确!", m_strName.c_str());
                Unlock();
                return -1;
            }
            if (pGlass1->getType() != MaterialsType::G1 || pGlass2->getType() != MaterialsType::G2) {
                LOGE("<CBonder-%s>onProcessData,错误!两片玻璃未匹配,必须分别为G1和G2类型,请检查数据是否正确!", m_strName.c_str());
                LOGE("<CBonder-%s>onProcessData,错误!两片玻璃未匹配,必须分别为G1和G2类型,请检查数据是否正确!", m_strName.c_str());
                Unlock();
                return -1;
            }
            pGlass1->setBuddy(pGlass2);
            getSlot(0)->setContext(nullptr);
            LOGE("<CBonder-%s>onProcessStateChanged,%s和%s已贴合!", m_strName.c_str(),
            LOGE("<CBonder-%s>onProcessStateChanged,%s和%s已贴合!", m_strName.c_str(),
                pGlass1->getID().c_str(), pGlass2->getID().c_str());
            Unlock();
        }
@@ -535,112 +535,112 @@
        int i = 0, v;
        // 1.校正对位延时
        // 1.校正对位延时
        v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8;
        params.push_back(CParam("校正对位延时", "", this->getName().c_str(), v * 0.01f));
        params.push_back(CParam("校正对位延时", "", this->getName().c_str(), v * 0.01f));
        i += 2;
        // 2.保压时间
        // 2.保压时间
        v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8;
        params.push_back(CParam("保压时间", "", this->getName().c_str(), v * 0.01f));
        params.push_back(CParam("保压时间", "", this->getName().c_str(), v * 0.01f));
        i += 2;
        // 3.腔体破真空延时
        // 3.腔体破真空延时
        v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8;
        params.push_back(CParam("腔体破真空延时", "", this->getName().c_str(), v * 0.01f));
        params.push_back(CParam("腔体破真空延时", "", this->getName().c_str(), v * 0.01f));
        i += 2;
        // 4.腔体分子泵启动延时
        // 4.腔体分子泵启动延时
        v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8;
        params.push_back(CParam("腔体分子泵启动延时", "", this->getName().c_str(), v * 0.1f));
        params.push_back(CParam("腔体分子泵启动延时", "", this->getName().c_str(), v * 0.1f));
        i += 2;
        // 5.腔体贴附抽真空延时
        // 5.腔体贴附抽真空延时
        v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8;
        params.push_back(CParam("腔体贴附抽真空延时", "", this->getName().c_str(), v * 0.1f));
        params.push_back(CParam("腔体贴附抽真空延时", "", this->getName().c_str(), v * 0.1f));
        i += 2;
        // 6.加热等待延时
        // 6.加热等待延时
        v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8;
        params.push_back(CParam("加热等待延时", "", this->getName().c_str(), v * 0.1f));
        params.push_back(CParam("加热等待延时", "", this->getName().c_str(), v * 0.1f));
        i += 2;
        // 7.气囊压力设定
        // 7.气囊压力设定
        v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8 | (pszData[i + 2] & 0xff) << 16 | (pszData[i + 3] & 0xff) << 24;
        params.push_back(CParam("气囊压力设定", "", this->getName().c_str(), v * 0.001f));
        params.push_back(CParam("气囊压力设定", "", this->getName().c_str(), v * 0.001f));
        i += 4;
        // 8.气囊加压速率
        // 8.气囊加压速率
        v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8 | (pszData[i + 2] & 0xff) << 16 | (pszData[i + 3] & 0xff) << 24;
        params.push_back(CParam("气囊加压速率", "", this->getName().c_str(), v * 0.001f));
        params.push_back(CParam("气囊加压速率", "", this->getName().c_str(), v * 0.001f));
        i += 4;
        // 9.气囊泄压速率
        // 9.气囊泄压速率
        v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8 | (pszData[i + 2] & 0xff) << 16 | (pszData[i + 3] & 0xff) << 24;
        params.push_back(CParam("气囊泄压速率", "", this->getName().c_str(), v * 0.001f));
        params.push_back(CParam("气囊泄压速率", "", this->getName().c_str(), v * 0.001f));
        i += 4;
        // 10.贴附压力上限
        // 10.贴附压力上限
        v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8 | (pszData[i + 2] & 0xff) << 16 | (pszData[i + 3] & 0xff) << 24;
        params.push_back(CParam("贴附压力上限", "", this->getName().c_str(), v * 0.1f));
        params.push_back(CParam("贴附压力上限", "", this->getName().c_str(), v * 0.1f));
        i += 4;
        // 11.Z轴转矩速度设定
        // 11.Z轴转矩速度设定
        v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8 | (pszData[i + 2] & 0xff) << 16 | (pszData[i + 3] & 0xff) << 24;
        params.push_back(CParam("上腔Z轴转矩速度设定", "", this->getName().c_str(), v * 0.001f));
        params.push_back(CParam("上腔Z轴转矩速度设定", "", this->getName().c_str(), v * 0.001f));
        i += 4;
        // 12.上腔温度设定
        // 12.上腔温度设定
        v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8;
        params.push_back(CParam("上腔温度设定", "", this->getName().c_str(), v * 0.1f));
        params.push_back(CParam("上腔温度设定", "", this->getName().c_str(), v * 0.1f));
        i += 2;
        // 13.下腔温度设定
        // 13.下腔温度设定
        v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8;
        params.push_back(CParam("下腔温度设定", "", this->getName().c_str(), v * 0.1f));
        params.push_back(CParam("下腔温度设定", "", this->getName().c_str(), v * 0.1f));
        i += 2;
        // 14.上腔Z轴预贴合位速度
        // 14.上腔Z轴预贴合位速度
        v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8 | (pszData[i + 2] & 0xff) << 16 | (pszData[i + 3] & 0xff) << 24;
        params.push_back(CParam("上腔Z轴预贴合位速度", "", this->getName().c_str(), v * 0.001f));
        params.push_back(CParam("上腔Z轴预贴合位速度", "", this->getName().c_str(), v * 0.001f));
        i += 4;
        // 15.上腔Z轴贴附位速度
        // 15.上腔Z轴贴附位速度
        v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8 | (pszData[i + 2] & 0xff) << 16 | (pszData[i + 3] & 0xff) << 24;
        params.push_back(CParam("上腔Z轴贴附位速度", "", this->getName().c_str(), v * 0.001f));
        params.push_back(CParam("上腔Z轴贴附位速度", "", this->getName().c_str(), v * 0.001f));
        i += 4;
        // 16.上腔Z上腔加热位间距
        // 16.上腔Z上腔加热位间距
        v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8 | (pszData[i + 2] & 0xff) << 16 | (pszData[i + 3] & 0xff) << 24;
        params.push_back(CParam("上腔Z上腔加热位间距", "", this->getName().c_str(), v * 0.001f));
        params.push_back(CParam("上腔Z上腔加热位间距", "", this->getName().c_str(), v * 0.001f));
        i += 4;
        // 17.上腔贴附位压入量
        // 17.上腔贴附位压入量
        v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8 | (pszData[i + 2] & 0xff) << 16 | (pszData[i + 3] & 0xff) << 24;
        params.push_back(CParam("上腔贴附位压入量", "", this->getName().c_str(), v * 0.001f));
        params.push_back(CParam("上腔贴附位压入量", "", this->getName().c_str(), v * 0.001f));
        i += 4;
        // 18.上腔Z轴破真空距离
        // 18.上腔Z轴破真空距离
        v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8 | (pszData[i + 2] & 0xff) << 16 | (pszData[i + 3] & 0xff) << 24;
        params.push_back(CParam("上腔Z轴破真空距离", "", this->getName().c_str(), v * 0.001f));
        params.push_back(CParam("上腔Z轴破真空距离", "", this->getName().c_str(), v * 0.001f));
        i += 4;
        // 19.下顶Pin破真空距离
        // 19.下顶Pin破真空距离
        v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8 | (pszData[i + 2] & 0xff) << 16 | (pszData[i + 3] & 0xff) << 24;
        params.push_back(CParam("下顶Pin破真空距离", "", this->getName().c_str(), v * 0.001f));
        params.push_back(CParam("下顶Pin破真空距离", "", this->getName().c_str(), v * 0.001f));
        i += 4;
        // 20.下顶Pin加热位间距
        // 20.下顶Pin加热位间距
        v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8 | (pszData[i + 2] & 0xff) << 16 | (pszData[i + 3] & 0xff) << 24;
        params.push_back(CParam("下顶Pin加热位间距", "", this->getName().c_str(), v * 0.001f));
        params.push_back(CParam("下顶Pin加热位间距", "", this->getName().c_str(), v * 0.001f));
        i += 4;
        // 21.腔体真空泵真空规设定值
        params.push_back(CParam("腔体真空泵真空规设定值", "", this->getName().c_str(), (double)toFloat(&pszData[i])));
        // 21.腔体真空泵真空规设定值
        params.push_back(CParam("腔体真空泵真空规设定值", "", this->getName().c_str(), (double)toFloat(&pszData[i])));
        i += 4;
        // 22.腔体分子泵到达设定值
        params.push_back(CParam("腔体分子泵到达设定值", "", this->getName().c_str(), (double)toFloat(&pszData[i])));
        // 22.腔体分子泵到达设定值
        params.push_back(CParam("腔体分子泵到达设定值", "", this->getName().c_str(), (double)toFloat(&pszData[i])));
        i += 4;
@@ -655,24 +655,24 @@
    int CBonder::parsingSVData(const char* pszData, size_t size, std::vector<CParam>& params)
    {
        /*
        1    工艺运行步骤    1Word    123456
            2    气囊压力当前    2Word    12345.6
            3    上腔压力合计    1Word    1234.56
            4    管道真空规值    FLOAT    123.456
            5    腔体真空规值    FLOAT    123.456
            6    上腔温度1    1Word    12345.6
            7    上腔温度2    1Word    12345.6
            8    上腔温度3    1Word    12345.6
            9    上腔温度4    1Word    12345.6
            10    上腔温度5    1Word    12345.6
            11    上腔温度6    1Word    12345.6
            12    下腔温度1    1Word    12345.6
            13    下腔温度2    1Word    12345.6
            14    下腔温度3    1Word    12345.6
            15    下腔温度4    1Word    12345.6
            16    下腔温度5    1Word    12345.6
            17    下腔温度6    1Word    12345.6
            18    压合剩余时间    1Word    1234.56
        1    工艺运行步骤    1Word    123456
            2    气囊压力当前    2Word    12345.6
            3    上腔压力合计    1Word    1234.56
            4    管道真空规值    FLOAT    123.456
            5    腔体真空规值    FLOAT    123.456
            6    上腔温度1    1Word    12345.6
            7    上腔温度2    1Word    12345.6
            8    上腔温度3    1Word    12345.6
            9    上腔温度4    1Word    12345.6
            10    上腔温度5    1Word    12345.6
            11    上腔温度6    1Word    12345.6
            12    下腔温度1    1Word    12345.6
            13    下腔温度2    1Word    12345.6
            14    下腔温度3    1Word    12345.6
            15    下腔温度4    1Word    12345.6
            16    下腔温度5    1Word    12345.6
            17    下腔温度6    1Word    12345.6
            18    压合剩余时间    1Word    1234.56
*/
        ASSERT(pszData);
@@ -680,97 +680,97 @@
        int i = 0, v;
        // 1.工艺运行步骤
        // 1.工艺运行步骤
        v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8;
        params.push_back(CParam("工艺运行步骤", "", this->getName().c_str(), v));
        params.push_back(CParam("工艺运行步骤", "", this->getName().c_str(), v));
        i += 2;
        // 2.气囊压力当前
        // 2.气囊压力当前
        v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8 | (pszData[i + 2] & 0xff) << 16 | (pszData[i + 3] & 0xff) << 24;
        params.push_back(CParam("气囊压力当前", "", this->getName().c_str(), v * 0.1f));
        params.push_back(CParam("气囊压力当前", "", this->getName().c_str(), v * 0.1f));
        i += 4;
        // 3.上腔压力合计
        // 3.上腔压力合计
        v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8;
        params.push_back(CParam("上腔压力合计", "", this->getName().c_str(), ((short)v) * 0.01f));
        params.push_back(CParam("上腔压力合计", "", this->getName().c_str(), ((short)v) * 0.01f));
        i += 2;
        // 4.管道真空规值
        params.push_back(CParam("管道真空规值", "", this->getName().c_str(), (double)toFloat(&pszData[i])));
        // 4.管道真空规值
        params.push_back(CParam("管道真空规值", "", this->getName().c_str(), (double)toFloat(&pszData[i])));
        i += 4;
        // 5.腔体真空规值
        params.push_back(CParam("腔体真空规值", "", this->getName().c_str(), (double)toFloat(&pszData[i])));
        // 5.腔体真空规值
        params.push_back(CParam("腔体真空规值", "", this->getName().c_str(), (double)toFloat(&pszData[i])));
        i += 4;
        // 6.上腔温度1
        // 6.上腔温度1
        v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8;
        params.push_back(CParam("上腔温度1", "", this->getName().c_str(), v * 0.1f));
        params.push_back(CParam("上腔温度1", "", this->getName().c_str(), v * 0.1f));
        i += 2;
        // 7.上腔温度2
        // 7.上腔温度2
        v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8;
        params.push_back(CParam("上腔温度2", "", this->getName().c_str(), v * 0.1f));
        params.push_back(CParam("上腔温度2", "", this->getName().c_str(), v * 0.1f));
        i += 2;
        // 8.上腔温度3
        // 8.上腔温度3
        v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8;
        params.push_back(CParam("上腔温度3", "", this->getName().c_str(), v * 0.1f));
        params.push_back(CParam("上腔温度3", "", this->getName().c_str(), v * 0.1f));
        i += 2;
        // 9.上腔温度4
        // 9.上腔温度4
        v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8;
        params.push_back(CParam("上腔温度4", "", this->getName().c_str(), v * 0.1f));
        params.push_back(CParam("上腔温度4", "", this->getName().c_str(), v * 0.1f));
        i += 2;
        // 10.上腔温度5
        // 10.上腔温度5
        v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8;
        params.push_back(CParam("上腔温度5", "", this->getName().c_str(), v * 0.1f));
        params.push_back(CParam("上腔温度5", "", this->getName().c_str(), v * 0.1f));
        i += 2;
        // 11.上腔温度6
        // 11.上腔温度6
        v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8;
        params.push_back(CParam("上腔温度6", "", this->getName().c_str(), v * 0.1f));
        params.push_back(CParam("上腔温度6", "", this->getName().c_str(), v * 0.1f));
        i += 2;
        // 12.下腔温度1
        // 12.下腔温度1
        v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8;
        params.push_back(CParam("下腔温度1", "", this->getName().c_str(), v * 0.1f));
        params.push_back(CParam("下腔温度1", "", this->getName().c_str(), v * 0.1f));
        i += 2;
        // 13.下腔温度2
        // 13.下腔温度2
        v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8;
        params.push_back(CParam("下腔温度2", "", this->getName().c_str(), v * 0.1f));
        params.push_back(CParam("下腔温度2", "", this->getName().c_str(), v * 0.1f));
        i += 2;
        // 14.下腔温度3
        // 14.下腔温度3
        v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8;
        params.push_back(CParam("下腔温度3", "", this->getName().c_str(), v * 0.1f));
        params.push_back(CParam("下腔温度3", "", this->getName().c_str(), v * 0.1f));
        i += 2;
        // 15.下腔温度4
        // 15.下腔温度4
        v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8;
        params.push_back(CParam("下腔温度4", "", this->getName().c_str(), v * 0.1f));
        params.push_back(CParam("下腔温度4", "", this->getName().c_str(), v * 0.1f));
        i += 2;
        // 16.下腔温度5
        // 16.下腔温度5
        v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8;
        params.push_back(CParam("下腔温度5", "", this->getName().c_str(), v * 0.1f));
        params.push_back(CParam("下腔温度5", "", this->getName().c_str(), v * 0.1f));
        i += 2;
        // 17.下腔温度6
        // 17.下腔温度6
        v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8;
        params.push_back(CParam("下腔温度6", "", this->getName().c_str(), v * 0.1f));
        params.push_back(CParam("下腔温度6", "", this->getName().c_str(), v * 0.1f));
        i += 2;
        // 18.加热剩余时间
        // 18.加热剩余时间
        v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8;
        params.push_back(CParam("加热剩余时间", "", this->getName().c_str(), v * 0.01f));
        params.push_back(CParam("加热剩余时间", "", this->getName().c_str(), v * 0.01f));
        i += 2;
        // 19.压合剩余时间
        // 19.压合剩余时间
        v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8;
        params.push_back(CParam("压合剩余时间", "", this->getName().c_str(), v * 0.01f));
        params.push_back(CParam("压合剩余时间", "", this->getName().c_str(), v * 0.01f));
        i += 2;
        return (int)params.size();
SourceCode/Bond/Servo/CBonder.h
@@ -22,7 +22,7 @@
        virtual void getAttributeVector(CAttributeVector& attrubutes);
        virtual int recvIntent(CPin* pPin, CIntent* pIntent);
        virtual int onProcessData(CProcessData* pProcessData);
        virtual int onProcessStateChanged(int slotNo, PROCESS_STATE state);
        virtual int onProcessStateChanged(int slotNo, PROCESS_STATE prevState, PROCESS_STATE state);
        virtual int getIndexerOperationModeBaseValue();
        virtual int parsingParams(const char* pszData, size_t size, std::vector<CParam>& parsms);
        virtual int parsingProcessData(const char* pszData, size_t size, std::vector<CParam>& parsms);
SourceCode/Bond/Servo/CEquipment.cpp
@@ -1,4 +1,4 @@
#include "stdafx.h"
#include "stdafx.h"
#include "CEquipment.h"
#include "ToolUnits.h"
#include <regex>
@@ -103,7 +103,7 @@
    void CEquipment::getProperties(std::vector<std::pair<std::string, std::string>>& container)
    {
        container.clear();
        // 示例:将一些属性添加到容器
        // 示例:将一些属性添加到容器
        container.push_back(std::make_pair("DeviceName", "ServoMotor"));
        container.push_back(std::make_pair("SerialNumber", "123456789"));
        container.push_back(std::make_pair("Version", "1.0"));
@@ -147,11 +147,12 @@
    {
        if (nSlotNo <= 0 || nSlotNo > 8) return;
        const auto prevState = m_processState[nSlotNo - 1];
        m_processState[nSlotNo - 1] = state;
        onProcessStateChanged(nSlotNo, m_processState[nSlotNo - 1]);
        onProcessStateChanged(nSlotNo, prevState, m_processState[nSlotNo - 1]);
        if (m_listener.onProcessStateChanged != nullptr) {
            m_listener.onProcessStateChanged(this, nSlotNo, m_processState[nSlotNo - 1]);
            m_listener.onProcessStateChanged(this, nSlotNo, prevState, m_processState[nSlotNo - 1]);
        }
    }
@@ -315,7 +316,7 @@
    void CEquipment::onTimer(UINT nTimerid)
    {
        // 每隔一秒,检查一下ALIVE状态
        // 每隔一秒,检查一下ALIVE状态
        static int tick = 0;
        tick++;
@@ -379,7 +380,7 @@
                }
            }
            // 梳理各玻璃之间的绑定关系
            // 梳理各玻璃之间的绑定关系
            /*
            Lock();
            for (int i = 0; i < SLOT_MAX; i++) {
@@ -391,7 +392,7 @@
                            CGlass* pBudy = (CGlass*)m_slot[j].getContext();
                            if (pBudy != nullptr && strBuddyId.compare(pBudy->getID()) == 0) {
                                pGlass->setBuddy(pBudy);
                                TRACE("绑定关系: %s <- %s\n", pGlass->getID().c_str(), pBudy->getID().c_str());
                                TRACE("绑定关系: %s <- %s\n", pGlass->getID().c_str(), pBudy->getID().c_str());
                            }
                        }
                    }
@@ -412,7 +413,7 @@
        }
        */
        // 连接信号解释和保存
        // 连接信号解释和保存
        BOOL bFlag;
        int index = 0;
        for (int i = 0; i < 8; i++) {
@@ -442,7 +443,7 @@
        }
        // 其它信号及响应
        // 其它信号及响应
        index = 0x540;
@@ -452,7 +453,7 @@
            m_alive.flag = bFlag;
            m_alive.count = 0;
            // ״̬
            // 状态
            if (!m_alive.alive) {
                m_alive.alive = TRUE;
                if (m_listener.onAlive != nullptr) {
@@ -501,7 +502,7 @@
        }
        // 以下根据信号做流程处理
        // 以下根据信号做流程处理
        for (int i = 0; i < 7; i++) {
            CHECK_READ_STEP_SIGNAL(STEP_ID_EQMODE_CHANGED + i, pszData, size);
        }
@@ -519,13 +520,13 @@
        }
        // 配方改变
        // 配方改变
        CHECK_READ_STEP_SIGNAL(STEP_ID_CURRENT_RECIPE_CHANGE_REPORT, pszData, size);
        
        // 主配方上报
        // 主配方上报
        CHECK_READ_STEP_SIGNAL(STEP_ID_MASTER_RECIPE_LIST_REPORT, pszData, size);
        // 配方参数
        // 配方参数
        CHECK_WRITE_STEP_SIGNAL(STEP_ID_RECIPE_PARAMETER_CMD_REPLY, pszData, size);
        CHECK_READ_STEP_SIGNAL(STEP_ID_RECIPE_PARAMETER_REPORT, pszData, size);
        
@@ -766,8 +767,8 @@
            else if (isCimMessageConfirmStep(pStep)) {
                SERVO::CEqReadIntStep* pEqReadIntStep = (SERVO::CEqReadIntStep*)pStep;
                int value = pEqReadIntStep->getValue();
                // 此处将value按高低位拆分为message id和panel no.
                // 可能还需要上报到cim
                // 此处将value按高低位拆分为message id和panel no.
                // 可能还需要上报到cim
                short msgId, panelNo;
                msgId = (value & 0xffff0000 >> 16);
                panelNo = (value & 0xffff);
@@ -782,7 +783,7 @@
                    m_listener.onVcrEventReport(this, pVcrEventReport);
                }
                // 0426, 先固定返回1(OK)
                // 0426, 先固定返回1(OK)
                pEqVcrEventStep->setReturnCode(1);        
                return 1;
            }
@@ -795,12 +796,12 @@
    CPin* CEquipment::addPin(PinType type, char* pszName)
    {
        // 不允许名字添加重复的pin
        // 不允许名字添加重复的pin
        CPin* pPin = getPin(pszName);
        if (pPin != nullptr) return nullptr;
        // 添加到Pin列表,看是输入pin或输出pin
        // 添加到Pin列表,看是输入pin或输出pin
        if (type == PinType::INPUT) {
            pPin = new CPin(this, type, pszName);
            m_inputPins.push_back(pPin);
@@ -865,7 +866,7 @@
        CEquipment* pFromEq = pFromPin->getEquipment();
        ASSERT(pFromEq);
        LOGD("<CEquipment><%s-%s>收到来自<%s.%s>的Intent<%d,%s,0x%x>",
        LOGD("<CEquipment><%s-%s>收到来自<%s.%s>的Intent<%d,%s,0x%x>",
            this->getName().c_str(),
            pPin->getName().c_str(),
            pFromEq->getName().c_str(),
@@ -876,11 +877,11 @@
        // 以下解释处理数据
        // 以下解释处理数据
        int code = pIntent->getCode();
        // 测试
        // 测试
        if (code == FLOW_TEST) {
            AfxMessageBox(pIntent->getMsg());
        }
@@ -895,7 +896,7 @@
            return -1;
        }
        // 找到指定的glass id,
        // 找到指定的glass id,
        Lock();
        CGlass* pContext = nullptr;
        for (int i = 0; i < SLOT_MAX; i++) {
@@ -946,7 +947,7 @@
        CGlass* pBuddy = pGlass->getBuddy();
        if (pBuddy != nullptr) pBuddy->addPath(m_nID, getSlotUnit(putSlot), putSlot);
        m_slot[putSlot - 1].setContext(pGlass);
        pGlass->release();                // tempFetchOut需要调用一次release
        pGlass->release();                // tempFetchOut需要调用一次release
        Unlock();
        /*
@@ -1174,17 +1175,17 @@
            return -1;
        }
        LOGI("<CEquipment-%s>准备设置DispatchingMode<%d>", m_strName.c_str(), (int)mode);
        LOGI("<CEquipment-%s>准备设置DispatchingMode<%d>", m_strName.c_str(), (int)mode);
        if (onWritedBlock != nullptr) {
            pStep->writeShort((short)mode, onWritedBlock);
        }
        else {
            pStep->writeShort((short)mode, [&, mode](int code) -> int {
                if (code == WOK) {
                    LOGI("<CEquipment-%s>设置DispatchingMode成功.", m_strName.c_str());
                    LOGI("<CEquipment-%s>设置DispatchingMode成功.", m_strName.c_str());
                }
                else {
                    LOGE("<CEquipment-%s>设置DispatchingMode失败,code:%d", m_strName.c_str(), code);
                    LOGE("<CEquipment-%s>设置DispatchingMode失败,code:%d", m_strName.c_str(), code);
                }
                return 0;
@@ -1202,19 +1203,19 @@
        }
        unsigned short operationMode = (unsigned short)((unsigned short)mode + getIndexerOperationModeBaseValue());
        LOGI("<CEquipment-%s>准备设置indexerOperationMode<%d>", m_strName.c_str(), (int)mode);
        LOGI("<CEquipment-%s>准备设置indexerOperationMode<%d>", m_strName.c_str(), (int)mode);
        pStep->writeShort(operationMode, [&, pStep, mode, onWritedRetBlock](int code) -> int {
            int retCode = 0;
            if (code == WOK) {
                LOGI("<CEquipment-%s>设置indexerOperationMode成功.", m_strName.c_str());
                LOGI("<CEquipment-%s>设置indexerOperationMode成功.", m_strName.c_str());
                const char* pszRetData = nullptr;
                pStep->getReturnData(pszRetData);
                ASSERT(pszRetData);
                retCode = (unsigned int)CToolUnits::toInt16(pszRetData);
                LOGI("<CEquipment-%s>返回值: %d", m_strName.c_str(), retCode);
                LOGI("<CEquipment-%s>返回值: %d", m_strName.c_str(), retCode);
            }
            else {
                LOGE("<CEquipment-%s>设置indexerOperationMode失败,code:%d", m_strName.c_str(), code);
                LOGE("<CEquipment-%s>设置indexerOperationMode失败,code:%d", m_strName.c_str(), code);
            }
            if (onWritedRetBlock != nullptr) {
@@ -1234,18 +1235,18 @@
            return -1;
        }
        LOGI("<CEquipment-%s>正在请求单元<%d>主配方列表", m_strName.c_str(), unitNo);
        LOGI("<CEquipment-%s>正在请求单元<%d>主配方列表", m_strName.c_str(), unitNo);
        m_recipesManager.setOnSyncingStateChanged(block);
        if (m_recipesManager.syncing() != 0) {
            return -2;
        }
        pStep->writeShort(unitNo, [&, unitNo](int code) -> int {
            if (code == WOK) {
                LOGI("<CEquipment-%s>请求单元<%d>主配方列表成功,正在等待数据.", m_strName.c_str(), unitNo);
                LOGI("<CEquipment-%s>请求单元<%d>主配方列表成功,正在等待数据.", m_strName.c_str(), unitNo);
            }
            else {
                m_recipesManager.syncFailed();
                LOGE("<CEquipment-%s>请求单元<%d>主配方列表失败,code:%d", m_strName.c_str(), unitNo, code);
                LOGE("<CEquipment-%s>请求单元<%d>主配方列表失败,code:%d", m_strName.c_str(), unitNo, code);
            }
            return 0;
@@ -1255,7 +1256,7 @@
    int CEquipment::recipeParameterRequest(short masterRecipeId, short localRecipeId, short unitNo, ONSYNCINGSTATECHANGED block)
    {
        LOGI("<CEquipment-%s>正在请求单元<%d>主配参数列表", m_strName.c_str(), unitNo);
        LOGI("<CEquipment-%s>正在请求单元<%d>主配参数列表", m_strName.c_str(), unitNo);
        m_recipesManager.setOnSyncingStateChanged(block);
        if (m_recipesManager.syncing() != 0) {
            return -2;
@@ -1276,11 +1277,11 @@
        pStep->writeDataEx(szBuffer, 14 * 2, [&, unitNo](int code) -> int {
            if (code == WOK) {
                LOGI("<CEquipment-%s>请求单元<%d>主配方参数列表成功,正在等待数据.", m_strName.c_str(), unitNo);
                LOGI("<CEquipment-%s>请求单元<%d>主配方参数列表成功,正在等待数据.", m_strName.c_str(), unitNo);
            }
            else {
                m_recipesManager.syncFailed();
                LOGE("<CEquipment-%s>请求单元<%d>主配方参数列表失败,code:%d", m_strName.c_str(), unitNo, code);
                LOGE("<CEquipment-%s>请求单元<%d>主配方参数列表失败,code:%d", m_strName.c_str(), unitNo, code);
            }
            return 0;
@@ -1584,7 +1585,7 @@
        int nRet = processData.unserialize(&pszData[0], (int)size);
        if (nRet < 0) return nRet;
        // 缓存Attribute,用于调试时显示信息
        // 缓存Attribute,用于调试时显示信息
        unsigned int weight = 201;
        CAttributeVector& attrubutes = pStep->attributeVector();
        processData.getAttributeVector(attrubutes, weight);
@@ -1592,11 +1593,11 @@
        // 找到玻璃,关联数据
        // 找到玻璃,关联数据
        CGlass* pGlass = this->getGlassWithCassette(processData.getCassetteSequenceNo(),
            processData.getJobSequenceNo());
        if (pGlass == nullptr) {
            LOGE("<CEquipment-%s>找不到对应Glass, 关联工艺参数失败。CassetteSequenceNo:%d/%d",
            LOGE("<CEquipment-%s>找不到对应Glass, 关联工艺参数失败。CassetteSequenceNo:%d/%d",
                this->getName().c_str(),
                processData.getCassetteSequenceNo(),
                processData.getJobSequenceNo());
@@ -1607,15 +1608,21 @@
        std::vector<CParam> tempParams;
        this->parsingProcessData((const char*)rawData.data(), rawData.size(), tempParams);
        int n = processData.getTotalParameter();
        std::vector<CParam> params(tempParams.begin(), tempParams.begin() + min(n, (int)tempParams.size()));
        std::vector<CParam> params(tempParams.begin(), tempParams.begin() + (std::min)(n, (int)tempParams.size()));
        pGlass->addParams(params);
        if (m_listener.onProcessDataReport != nullptr) {
            m_listener.onProcessDataReport(this, params);
        }
        
        // 关联的Glass也要更新
        // 关联的Glass也要更新
        CGlass* pBuddy = pGlass->getBuddy();
        LOGI("<Equipment-%s>decodeProcessDataReport pBuddy=%x %s", getName().c_str(), pBuddy, pGlass->getID().c_str());
        if (pBuddy != nullptr) {
            LOGI("<Equipment-%s>decodeProcessDataReport addParams pBuddy=%x %s", getName().c_str(), pBuddy, pGlass->getID().c_str());
            pBuddy->addParams(params);
            if (m_listener.onProcessDataReport != nullptr) {
                m_listener.onProcessDataReport(this, params);
            }
        }
        return nRet;
@@ -1627,7 +1634,7 @@
        int nRet = jobDataS.unserialize(&pszData[0], (int)size);
        if (nRet < 0) return nRet;
        // 缓存Attribute,用于调试时显示信息
        // 缓存Attribute,用于调试时显示信息
        unsigned int weight = 201;
        CAttributeVector& attrubutes = pStep->attributeVector();
        jobDataS.getAttributeVector(attrubutes, weight);
@@ -1641,10 +1648,10 @@
        LOGI("<CEquipment-%s>onReceivedJob.", m_strName.c_str());
        // 可以在此更新JobDataS数据了
        // 可以在此更新JobDataS数据了
        int nRet = ((CArm*)m_pArm)->glassUpdateJobDataS(pJobDataS);
        if (nRet < 0) {
            LOGE("<CEquipment-%s>onReceivedJob,更新JobDataS失败,glassUpdateJobDataS返回%d",
            LOGE("<CEquipment-%s>onReceivedJob,更新JobDataS失败,glassUpdateJobDataS返回%d",
                m_strName.c_str(), nRet);
        }
@@ -1657,7 +1664,7 @@
        int nRet = jobDataS.unserialize(&pszData[0], (int)size);
        if (nRet < 0) return nRet;
        // 缓存Attribute,用于调试时显示信息
        // 缓存Attribute,用于调试时显示信息
        unsigned int weight = 201;
        CAttributeVector& attrubutes = pStep->attributeVector();
        jobDataS.getAttributeVector(attrubutes, weight);
@@ -1692,7 +1699,7 @@
        index += sizeof(short);
        // 缓存Attribute,用于调试时显示信息
        // 缓存Attribute,用于调试时显示信息
        unsigned int weight = 201;
        pStep->addAttribute(new CAttribute("UnitOrPort",
            std::to_string(unitOrPort).c_str(), "", weight++));
@@ -1736,7 +1743,7 @@
            return fetchedOutJob(port, pJobDataB);
        }
        // 数据异常,处理或显示
        // 数据异常,处理或显示
        LOGI("<CEquipment-%s>onFetchedOutJob Error.ort:%d|GlassId:%s",
            m_strName.c_str(), port, pJobDataB->getGlassId().c_str());
        return -1;
@@ -1761,7 +1768,7 @@
        index += sizeof(short);
        // 缓存Attribute,用于调试时显示信息
        // 缓存Attribute,用于调试时显示信息
        unsigned int weight = 201;
        pStep->addAttribute(new CAttribute("UnitOrPort",
            std::to_string(unitOrPort).c_str(), "", weight++));
@@ -1793,7 +1800,7 @@
            vcrEventReport.getGlassId().c_str());
        // 更新Glass的ID
        // 更新Glass的ID
        CGlass* pGlass = getGlassWithCassette(vcrEventReport.getCassetteSequenceNo(),
            vcrEventReport.getJobSequenceNo());
        if (pGlass != nullptr) {
@@ -1801,13 +1808,13 @@
        }
        
        // 缓存Attribute,用于调试时显示信息
        // 缓存Attribute,用于调试时显示信息
        unsigned int weight = 201;
        CAttributeVector& attrubutes = pStep->attributeVector();
        vcrEventReport.getAttributeVector(attrubutes, weight);
        // 0426, 先固定返回1(OK)
        // 0426, 先固定返回1(OK)
        ((CReadStep*)pStep)->setReturnCode((short)VCR_Reply_Code::OK);
@@ -1829,7 +1836,7 @@
        index += 256 * 2;
        // 缓存Attribute,用于调试时显示信息
        // 缓存Attribute,用于调试时显示信息
        unsigned int weight = 201;
        pStep->addAttribute(new CAttribute("CassetteNo",
            std::to_string(cassetteNo).c_str(), "", weight++));
@@ -1841,10 +1848,10 @@
            strPanelGradeData.c_str(), "", weight++));
        // 更新检测结果
        // 更新检测结果
        CGlass* pGlass = getGlassWithCassette(cassetteNo, jobSequenceNo);
        if (pGlass == nullptr) {
            LOGE("<CEquipment-%s>更新Panel Data失败,找不到对应的Glass.cassetteNo=%d, jobSequenceNo=%d",
            LOGE("<CEquipment-%s>更新Panel Data失败,找不到对应的Glass.cassetteNo=%d, jobSequenceNo=%d",
                getName().c_str(), cassetteNo, jobSequenceNo);
            return -1;
        }
@@ -1885,7 +1892,7 @@
        // 缓存Attribute,用于调试时显示信息
        // 缓存Attribute,用于调试时显示信息
        unsigned int weight = 201;
        pStep->addAttribute(new CAttribute("CassetteSequenceNo",
            (std::to_string(cassetteSequenceNo)).c_str(), "", weight++));
@@ -1941,7 +1948,7 @@
        CGlass* pGlass = getGlassFromSlot(slotNo);
        if (pGlass == nullptr) {
            LOGE("<CEquipment-%s>decodeJobProcessStartReport, 找不到对应glass", getName().c_str());
            LOGE("<CEquipment-%s>decodeJobProcessStartReport, 找不到对应glass", getName().c_str());
        }
        if (slotNo <= 0 || slotNo > 8) return -1;
@@ -1953,7 +1960,7 @@
        }
        // 缓存Attribute,用于调试时显示信息
        // 缓存Attribute,用于调试时显示信息
        unsigned int weight = 201;
        pStep->addAttribute(new CAttribute("CassetteNo",
            std::to_string(cassetteNo).c_str(), "", weight++));
@@ -2023,7 +2030,7 @@
        }
    
        if (pGlass == nullptr) {
            LOGE("<CEquipment-%s>decodeJobProcessEndReport, 找不到对应glass", getName().c_str());
            LOGE("<CEquipment-%s>decodeJobProcessEndReport, 找不到对应glass", getName().c_str());
        }
        else {
            CJobDataS* pJs = pGlass->getJobDataS();
@@ -2032,7 +2039,7 @@
                pGlass->processEnd(m_nID, getSlotUnit(slotNo));
            }
            else {
                LOGE("<CEquipment-%s>decodeJobProcessEndReport, jobSequenceNo或jobSequenceNo不匹配",
                LOGE("<CEquipment-%s>decodeJobProcessEndReport, jobSequenceNo或jobSequenceNo不匹配",
                    getName().c_str());
            }
        }
@@ -2040,7 +2047,7 @@
        // 缓存Attribute,用于调试时显示信息
        // 缓存Attribute,用于调试时显示信息
        unsigned int weight = 201;
        pStep->addAttribute(new CAttribute("CassetteNo",
            std::to_string(cassetteNo).c_str(), "", weight++));
@@ -2064,10 +2071,10 @@
        LOGI("<CEquipment-%s>onPreStoredJob:port:%d|GlassId:%s",
            m_strName.c_str(), port, pJobDataB->getGlassId().c_str());
        // 当前要存片,之前肯定有拔片,因此片子在Arm那里
        // 当前要存片,之前肯定有拔片,因此片子在Arm那里
        CGlass* pGlass = ((CArm*)m_pArm)->getGlassFromSlot(1);
        if (pGlass == nullptr) {
            LOGE("<CFliper-%s>onPreStoredJob,缓存中没有找到对应的Glass(CassetteSequenceNo:%d, JobSequenceNo:%d),请检查数据,注意风险。", m_strName.c_str(),
            LOGE("<CFliper-%s>onPreStoredJob,缓存中没有找到对应的Glass(CassetteSequenceNo:%d, JobSequenceNo:%d),请检查数据,注意风险。", m_strName.c_str(),
                pJobDataB->getCassetteSequenceNo(), pJobDataB->getJobSequenceNo());
            return FALSE;
        }
@@ -2075,19 +2082,19 @@
        CJobDataS* pJobDataS = pGlass->getJobDataS();
        ASSERT(pJobDataS);
        if (!compareJobData(pJobDataB, pJobDataS)) {
            LOGE("<CEquipemnt-%s>onPreStoredJob,JobData数据不匹配(JobDataB(%d, %d),JobDataS(%d, %d)), 注意排查风险!", m_strName.c_str(),
            LOGE("<CEquipemnt-%s>onPreStoredJob,JobData数据不匹配(JobDataB(%d, %d),JobDataS(%d, %d)), 注意排查风险!", m_strName.c_str(),
                pJobDataB->getCassetteSequenceNo(), pJobDataB->getJobSequenceNo(),
                pJobDataS->getCassetteSequenceNo(), pJobDataS->getJobSequenceNo());
            return FALSE;
        }
        // 如果没有可用位置,报错
        // 如果没有可用位置,报错
        Lock();
        CSlot* pSlot = getSlot(putSlot - 1);
        ASSERT(pSlot);
        if (pSlot->getContext() != nullptr) {
            Unlock();
            LOGE("<CEquipemnt-%s>onPreStoredJob,指定slot(port:%d)有料,请注意风险!", m_strName.c_str(), port);
            LOGE("<CEquipemnt-%s>onPreStoredJob,指定slot(port:%d)有料,请注意风险!", m_strName.c_str(), port);
            return FALSE;
        }
        Unlock();
@@ -2117,7 +2124,7 @@
            return storedJob(port, pJobDataB, putSlot);
        }
        // 数据异常,处理或显示
        // 数据异常,处理或显示
        LOGI("<CEquipment-%s>onStoredJob Error.port:%d|GlassId:%s",
            m_strName.c_str(), port, pJobDataB->getGlassId().c_str());
        return -1;
@@ -2131,8 +2138,8 @@
    }
    /*
     * 当从CC-Link检测到设备Send Able为On时调用此函数
     * 可能会多次重复调用(根据扫描频率), 注意防呆
     * 当从CC-Link检测到设备Send Able为On时调用此函数
     * 可能会多次重复调用(根据扫描频率), 注意防呆
     */
    int CEquipment::onSendAble(int port)
    {
@@ -2148,7 +2155,7 @@
        return 0;
    }
    int CEquipment::onProcessStateChanged(int nSlotNo, PROCESS_STATE state)
    int CEquipment::onProcessStateChanged(int nSlotNo, PROCESS_STATE prevState, PROCESS_STATE state)
    {
        return 0;
    }
@@ -2261,4 +2268,4 @@
    {
        return m_svDatas;
    }
}
}
SourceCode/Bond/Servo/CEquipment.h
@@ -1,4 +1,4 @@
#pragma once
#pragma once
#include "Log.h"
#include "ServoCommo.h"
#include "CCLinkIEControl.h"
@@ -55,9 +55,10 @@
    typedef std::function<void(void* pEiuipment, void* pReport)> ONVCREVENTREPORT;
    typedef std::function<BOOL(void* pEiuipment, int port, CJobDataB* pJobDataB)> ONPREFETCHEDOUTJOB;
    typedef std::function<BOOL(void* pEiuipment, int port, CJobDataB* pJobDataB, short& putSlot)> ONPRESTOREDJOB;
    typedef std::function<void(void* pEiuipment, int nSlotNo, PROCESS_STATE state)> ONPROCESSSTATE;
    typedef std::function<void(void* pEiuipment, int nSlotNo, PROCESS_STATE prevState, PROCESS_STATE state)> ONPROCESSSTATE;
    typedef std::function<void(void* pEiuipment, short scanMap, short downMap)> ONMAPMISMATCH;
    typedef std::function<void(void* pEiuipment, short status, __int64 data)> ONPORTSTATUSCHANGED;
    typedef std::function<void(void* pEiuipment, const std::vector<CParam>& params)> ONPROCESSDATAREPORT;
    
    typedef struct _EquipmentListener
    {
@@ -73,6 +74,7 @@
        ONPORTSTATUSCHANGED    onPortStatusChanged;
        ONVCREVENTREPORT    onSVDataReport;
        ONVCREVENTREPORT    onPanelDataReport;
        ONPROCESSDATAREPORT    onProcessDataReport;
    } EquipmentListener;
@@ -140,7 +142,7 @@
        virtual int onProcessData(CProcessData* pProcessData);
        virtual int onSendAble(int port);
        virtual int onReceiveAble(int port);
        virtual int onProcessStateChanged(int nSlotNo, PROCESS_STATE state);
        virtual int onProcessStateChanged(int nSlotNo, PROCESS_STATE prevState, PROCESS_STATE state);
        virtual int getIndexerOperationModeBaseValue();
        virtual bool isSlotProcessed(int slot) { return true; };
        bool isAlarmStep(SERVO::CStep* pStep);
@@ -163,47 +165,47 @@
        void printDebugString001();
        std::vector<SERVO::CSVData>& getSVDatas();
        // 请求主配方列表
        // 请求主配方列表
        // unitNo: 0:local; Others:unit No
        int masterRecipeListRequest(short unitNo, ONSYNCINGSTATECHANGED block);
        // 请求配方参数
        // masterRecipeId: 主配方id
        // localRecipeId: 本地配方id
        // 请求配方参数
        // masterRecipeId: 主配方id
        // localRecipeId: 本地配方id
        // unitNo: 0:local; Others:unit No
        int recipeParameterRequest(short masterRecipeId, short localRecipeId, short unitNo, ONSYNCINGSTATECHANGED block);
        // 解析配方参数列表
        // 解析配方参数列表
        virtual int parsingParams(const char* pszData, size_t size, std::vector<CParam>& params) { return 0;  };
        virtual int parsingParams(const char* pszData, size_t size, std::string& strOut);
        virtual int parsingProcessData(const char* pszData, size_t size, std::vector<CParam>& params) { return 0; };
        virtual int parsingSVData(const char* pszData, size_t size, std::vector<CParam>& params) { return 0; };
        // 获取指定的Slot
        // 获取指定的Slot
        CSlot* getSlot(int index);
        CSlot* getSlotWithNo(int slotNo);
        // 获取一个可用的槽位
        // 获取一个可用的槽位
        CSlot* getAvailableSlot();
        // 获取一个指定物料类型(G1,G2,G1&G2)的空槽位
        // 获取一个指定物料类型(G1,G2,G1&G2)的空槽位
        CSlot* getAvailableSlotForGlass(MaterialsType type);
        CSlot* getAvailableSlotForGlassExcludeSignal(MaterialsType type);
        CSlot* isSlotAvailable(unsigned int slot);
        // 在指定的槽列表中,获取一个指定物料类型(G1,G2,G1&G2)的空槽位
        // 在指定的槽列表中,获取一个指定物料类型(G1,G2,G1&G2)的空槽位
        CSlot* getAvailableSlotForGlass2(MaterialsType type, const std::vector<int>& candidates);
        // 获取一个指定物料类型(G1,G2,G1&G2)的非空槽位
        // 获取一个指定物料类型(G1,G2,G1&G2)的非空槽位
        CSlot* getNonEmptySlot(MaterialsType type);
        // 获取一个指定物料类型(G1,G2,G1&G2)的且已经加工处理的槽位
        // 获取一个指定物料类型(G1,G2,G1&G2)的且已经加工处理的槽位
        CSlot* getProcessedSlot(MaterialsType putSlotType, BOOL bJobMode = FALSE);
        CSlot* getProcessedSlot2(MaterialsType putSlotType, const std::vector<int>& candidates);
        CSlot* getInspFailSlot();
        CSlot* getProcessedSlotCt(unsigned int slot);
        // 获取玻璃物料
        // 获取玻璃物料
        CGlass* getGlassFromSlot(int slotNo);
        CGlass* getGlassWithCassette(int cassetteSequenceNo, int jobSequenceNo);
        CGlass* getAnyGlass();
@@ -211,26 +213,27 @@
        int getAllGlass(std::vector<CGlass*>& glasses);
        CJobDataS* getJobDataSWithCassette(int cassetteSequenceNo, int jobSequenceNo);
        // 验证玻璃和槽是否匹配
        // 验证玻璃和槽是否匹配
        BOOL ValidateGlassSlotMatch();
        // 是否有玻璃
        // 是否有玻璃
        BOOL hasGlass();
        BOOL slotHasGlass(int slotIndex = 0);
        // 指定槽位是否可以放置玻璃
        // 指定槽位是否可以放置玻璃
        BOOL canPlaceGlassInSlot(const short slotIndex);
        // 手动移除物料
        // 手动移除物料
        int removeGlass(int slotNo);
        // 字符串检测结果转换
        // 字符串检测结果转换
        InspResult judgeStringToInspResult(std::string& strJudge);
        // for test
        void fireSetProcessState(int nSlotNo, PROCESS_STATE state) { return setProcessState(nSlotNo, state); }
    // 以下为从CC-Link读取到的Bit标志位检测函数
    // 以下为从CC-Link读取到的Bit标志位检测函数
    public:
        BOOL isAlive();
        BOOL isCimOn();
@@ -242,7 +245,7 @@
        BOOL isLinkSignalUpstreamOn(unsigned int path, unsigned int signal);
        BOOL isLinkSignalDownstreamOn(unsigned int path, unsigned int signal);
        // 只在模拟测试时使用的函数,用于模拟信号
        // 只在模拟测试时使用的函数,用于模拟信号
        void setLinkSignalUpstream(unsigned int path, unsigned int signal, BOOL bOn);
        void setLinkSignalUpstreamBlock(unsigned int path, BOOL* pSignal);
        void setLinkSignalDownstream(unsigned int path, unsigned int signal, BOOL bOn);
@@ -271,7 +274,7 @@
        float toFloat(const char* pszAddr);
    protected:
        // 部分优化/简化代码、暂实现部分,到时平铺开
        // 部分优化/简化代码、暂实现部分,到时平铺开
        void addFacDataReportStep(int dataDev, int writeSignalDev, int port);
@@ -289,7 +292,7 @@
        std::vector<CPin*> m_outputPins;
        // 以下为从CC-Link读取到的Bit标志位
        // 以下为从CC-Link读取到的Bit标志位
    protected:
        ALIVE m_alive;
        BOOL m_bCimState;            // ON/OFF
SourceCode/Bond/Servo/CMaster.cpp
@@ -1540,7 +1540,7 @@
                unlock();
            }
        };
        listener.onProcessStateChanged = [&](void* pEquipment, int slotNo, PROCESS_STATE state) -> void {
        listener.onProcessStateChanged = [&](void* pEquipment, int slotNo, PROCESS_STATE prevState, PROCESS_STATE state) -> void {
            ASSERT(1 <= slotNo && slotNo <= 8);
            int eqid = ((CEquipment*)pEquipment)->getID();
            CGlass* pGlass = ((CEquipment*)pEquipment)->getGlassFromSlot(slotNo);
@@ -1558,7 +1558,12 @@
            }
            if (m_listener.onProcessStateChanged != nullptr) {
                m_listener.onProcessStateChanged(this, (CEquipment*)pEquipment, slotNo, state);
                m_listener.onProcessStateChanged(this, (CEquipment*)pEquipment, slotNo, prevState, state);
            }
        };
        listener.onProcessDataReport = [&](void* pEquipment, const std::vector<CParam>& params) {
            if (m_listener.onProcessDataReport != nullptr) {
                m_listener.onProcessDataReport(this, (CEquipment*)pEquipment, params);
            }
        };
        listener.onMapMismatch = [&](void* pEquipment, short scanMap, short downMap) {
@@ -1781,6 +1786,10 @@
                strOut.append(szBuffer);
            }
            LOGD("<CMaster-%s>SVDataReport:%s", ((CEquipment*)pEquipment)->getName().c_str(), strOut.c_str());
            if (m_listener.onSVDataReport != nullptr) {
                m_listener.onSVDataReport(this, (CEquipment*)pEquipment, params);
            }
        };
        listener.onPanelDataReport = [&](void* pEquipment, void* pContext) {
            LOGD("<CMaster-%s>onPanelDataReport", ((CEquipment*)pEquipment)->getName().c_str());
@@ -2115,8 +2124,9 @@
                    }
                };
                auto fireProcessState = [&](SERVO::CEquipment* pEq, int slotNo, SERVO::PROCESS_STATE st) {
                    if (m_listener.onProcessStateChanged != nullptr && pEq != nullptr) {
                        m_listener.onProcessStateChanged(this, pEq, slotNo, st);
                    // Drive equipment state so listeners receive prev/current states consistently.
                    if (pEq != nullptr) {
                        pEq->fireSetProcessState(slotNo, st);
                    }
                };
SourceCode/Bond/Servo/CMaster.h
@@ -58,7 +58,9 @@
    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 status, __int64 data)> ONLOADPORTSTATUSCHANGED;
    typedef std::function<void(void* pMaster, CEquipment* pEquipment, int slotNo, PROCESS_STATE state)> ONPROCESSSTATECHANGED;
    typedef std::function<void(void* pMaster, CEquipment* pEquipment, int slotNo, PROCESS_STATE prevState, PROCESS_STATE state)> ONPROCESSSTATECHANGED;
    typedef std::function<void(void* pMaster, CEquipment* pEquipment, const std::vector<CParam>& params)> ONPROCESSDATAREPORTEX;
    typedef std::function<void(void* pMaster, CEquipment* pEquipment, const std::vector<CParam>& params)> ONSVDATAREPORT;
    typedef std::function<void(void* pMaster, int round)> ONCTROUNDEND;
    typedef std::function<void(void* pMaster, void* pj)> ONPJSTART;
    typedef std::function<void(void* pMaster)> ONCONTROLJOBCHANGED;
@@ -73,6 +75,8 @@
        ONROBOTTASKEVENT        onRobotTaskEvent;
        ONLOADPORTSTATUSCHANGED    onLoadPortStatusChanged;
        ONPROCESSSTATECHANGED   onProcessStateChanged;
        ONSVDATAREPORT          onSVDataReport;
        ONPROCESSDATAREPORTEX   onProcessDataReport;
        ONCTROUNDEND            onCTRoundEnd;
        ONPJSTART               onCjStart;
        ONPJSTART               onCjEnd;
@@ -205,7 +209,7 @@
        bool canCompleteControlJob();
        bool canDeleteControlJob();
        
        // DAQ Bridge鐩稿叧
        // DAQ Bridge 相关
        Collector* getCollector() const { return m_pCollector; }
    private:
@@ -243,10 +247,9 @@
        int m_nLastError;
        std::string m_strLastError;
        // 在开始工艺前是否先需要先比较map
        // 在开始工艺前是否需要先比较 map
        BOOL m_isCompareMapsBeforeProceeding;
        BOOL m_bJobMode;
        // 千传圈数计数
        int m_nContinuousTransferCount;
@@ -254,7 +257,7 @@
        int m_nContinuousWorkingPort;
        int m_nContinuousWorkingSlot;
        // 新增已经开始处理的ProcessJob列表
        // 已经开始处理的 ProcessJob 列表
        std::vector<CProcessJob*> m_inProcesJobs;
        std::vector<CProcessJob*> m_completeProcessJobs;
        std::vector<CGlass*> m_queueGlasses;
SourceCode/Bond/Servo/CParam.cpp
@@ -53,7 +53,7 @@
    return m_nValueType;
}
int CParam::getIntValue()
int CParam::getIntValue() const
{
    return m_nValue;
}
@@ -63,7 +63,7 @@
    m_nValue = value;
}
double CParam::getDoubleValue()
double CParam::getDoubleValue() const
{
    if(m_nValueType == PVT_DOUBLE)
        return m_fValue;
SourceCode/Bond/Servo/CParam.h
@@ -17,9 +17,9 @@
    std::string& getName();
    std::string& getUnit();
    int getValueType();
    int getIntValue();
    int getIntValue() const;
    void setIntValue(int value);
    double getDoubleValue();
    double getDoubleValue() const;
    void setDoubleValue(double value);
    void Serialize(CArchive& ar);
SourceCode/Bond/Servo/HsmsPassive.cpp
@@ -20,6 +20,19 @@
const char* ACK0 = &ACK[0];
const char* ACK1 = &ACK[1];
// Log SECS-II message briefly to avoid huge strings causing issues.
static void LogSecsMessageBrief(const char* tag, IMessage* pMessage, size_t maxLen = 1024)
{
    if (pMessage == nullptr) return;
    const char* msgStr = pMessage->toString();
    if (msgStr == nullptr) return;
    std::string buf(msgStr);
    if (buf.size() > maxLen) {
        buf = buf.substr(0, maxLen) + "...<truncated>";
    }
    LOGI("%s%s", tag, buf.c_str());
}
unsigned __stdcall CimWorkThreadFunction(LPVOID lpParam)
{
    CHsmsPassive* pPassive = (CHsmsPassive*)lpParam;
@@ -525,26 +538,37 @@
void CHsmsPassive::setVariableValue(const char* pszName, __int64 value)
{
    auto v = getVariable(pszName);
    if (v != nullptr) {
    // Protect variable list updates; multiple threads may set SVs.
    Lock();
    if (auto v = getVariable(pszName)) {
        v->setValue(value);
    }
    Unlock();
}
void CHsmsPassive::setVariableValue(const char* pszName, const char* value)
{
    auto v = getVariable(pszName);
    if (v != nullptr) {
    Lock();
    if (auto v = getVariable(pszName)) {
        v->setValue(value);
    }
    Unlock();
}
void CHsmsPassive::setVariableValue(const char* pszName, std::vector<SERVO::CVariable>& vars)
{
    auto v = getVariable(pszName);
    if (v != nullptr) {
    Lock();
    if (auto v = getVariable(pszName)) {
        v->setValue(vars);
    }
    Unlock();
}
void CHsmsPassive::withVariableLock(const std::function<void()>& fn)
{
    Lock();
    if (fn) fn();
    Unlock();
}
static bool isValidFormat(const std::string& fmt)
@@ -1287,13 +1311,19 @@
        HEADER* pHeader = pMessage->getHeader();
        int nStream = (pHeader->stream & 0x7F);
        LOGI("<HSMS>[Received]%s", pMessage->toString());
        LogSecsMessageBrief("<HSMS>[Received]", pMessage);
        if (nStream == 1 && pHeader->function == 1) {
            // S1F1
            replyAreYouThere(pMessage);
        }
        else if (nStream == 1 && pHeader->function == 3) {
            replySelectedEquipmentStatusData(pMessage);
        }
        else if (nStream == 1 && pHeader->function == 11) {
            replyStatusVariableNamelistRequest(pMessage);
        }
        else if (nStream == 1 && pHeader->function == 23) {
            replyCollectionEventNamelistRequest(pMessage);
        }
        else if (nStream == 1 && pHeader->function == 13) {
            replyEstablishCommunications(pMessage);
@@ -1621,7 +1651,7 @@
                ASSERT(pMessage);
                m_pPassive->sendMessage(pMessage);
                LOGI("<HSMS>[SEND]SysByte=%u sessionId:%d", pMessage->getHeader()->systemBytes, pMessage->getHeader()->sessionId);
                LOGI("<HSMS>[SEND]%s", pMessage->toString());
                LogSecsMessageBrief("<HSMS>[SEND]", pMessage);
                int nRet = WaitForSingleObject(pAction->getEvent(), pAction->getTimeout() * 1000);
                if (nRet == WAIT_TIMEOUT) {
@@ -1647,7 +1677,7 @@
                ASSERT(pMessage);
                m_pPassive->sendMessage(pMessage);
                LOGI("<HSMS>[SEND]SysByte=%u sessionId:%d", pMessage->getHeader()->systemBytes, pMessage->getHeader()->sessionId);
                LOGI("<HSMS>[SEND]%s", pMessage->toString());
                LogSecsMessageBrief("<HSMS>[SEND]", pMessage);
            }
        }
@@ -1671,7 +1701,7 @@
    m_pPassive->sendMessage(pMessage);
    LOGI("<HSMS>[SEND]sessionId:%d, sType:%d systemBytes:%d",
        pMessage->getHeader()->sessionId, pMessage->getHeader()->sType, pMessage->getHeader()->systemBytes);
    LOGI("<HSMS>[SEND]%s", pMessage->toString());
    LogSecsMessageBrief("<HSMS>[SEND]", pMessage);
    HSMS_Destroy1Message(pMessage);
}
@@ -1714,7 +1744,7 @@
    m_pPassive->sendMessage(pMessage);
    LOGI("<HSMS>[SEND]sessionId:%d, sType:%d systemBytes:%d",
        pMessage->getHeader()->sessionId, pMessage->getHeader()->sType, pMessage->getHeader()->systemBytes);
    LOGI("<HSMS>[SEND]%s", pMessage->toString());
    LogSecsMessageBrief("<HSMS>[SEND]", pMessage);
    HSMS_Destroy1Message(pMessage);
    return 0;
@@ -1777,7 +1807,7 @@
    m_pPassive->sendMessage(pMessage);
    LOGI("<HSMS>[SEND]sessionId:%d, sType:%d systemBytes:%d",
        pMessage->getHeader()->sessionId, pMessage->getHeader()->sType, pMessage->getHeader()->systemBytes);
    LOGI("<HSMS>[SEND]%s", pMessage->toString());
    LogSecsMessageBrief("<HSMS>[SEND]", pMessage);
    HSMS_Destroy1Message(pMessage);
    return 0;
@@ -1824,12 +1854,168 @@
    m_pPassive->sendMessage(pMessage);
    LOGI("<HSMS>[SEND]sessionId:%d, sType:%d systemBytes:%d",
        pMessage->getHeader()->sessionId, pMessage->getHeader()->sType, pMessage->getHeader()->systemBytes);
    LOGI("<HSMS>[SEND]%s", pMessage->toString());
    LogSecsMessageBrief("<HSMS>[SEND]", pMessage);
    HSMS_Destroy1Message(pMessage);
    return 0;
}
// S1F11
int CHsmsPassive::replyStatusVariableNamelistRequest(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);
            }
        }
    }
    // Build response list items: {L:3 SVID, SVNAME, UNITS}
    std::vector<unsigned short> svids;
    std::set<unsigned short> requested(reqIds.begin(), reqIds.end());
    Lock();
    if (reqIds.empty()) {
        for (auto v : m_variabels) {
            svids.push_back(static_cast<unsigned short>(v->getVarialbleId()));
        }
    }
    else {
        // include requested IDs (existing + unknown marker)
        for (auto id : requested) {
            svids.push_back(id);
        }
    }
    Unlock();
    IMessage* pMessage = NULL;
    HSMS_Create1Message(pMessage, m_nSessionId, 1, 12, pRecv->getHeader()->systemBytes);
    ASSERT(pMessage);
    ISECS2Item* pList = pMessage->getBody(); // Body is L[n] of {SVID, SVNAME, UNITS}
    for (auto id : svids) {
        ISECS2Item* pEntry = pList->addItem();
        pEntry->addU2Item(id, "SVID");
        SERVO::CVariable* v = getVariable((int)id);
        if (v != nullptr) {
            pEntry->addItem(v->getName().c_str(), "SVNAME");
            // Use remark as UNITS if provided; empty string if none.
            pEntry->addItem(v->getRemark().c_str(), "UNITS");
        }
        else {
            // Unknown SVID: A:0 for name/units
            pEntry->addItem("", "SVNAME");
            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)
{
    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);
            }
        }
    }
    struct CEInfo {
        unsigned short id{ 0 };
        std::string name;
        std::vector<unsigned short> vids;
    };
    std::vector<CEInfo> ceInfos;
    {
        Lock();
        if (reqIds.empty()) {
            for (auto e : m_collectionEvents) {
                if (e == nullptr) continue;
                CEInfo info;
                info.id = static_cast<unsigned short>(e->getEventId());
                info.name = e->getName();
                std::set<unsigned short> vidSet;
                for (auto rpt : e->getReports()) {
                    if (rpt == nullptr) continue;
                    for (auto vid : rpt->getVids()) {
                        vidSet.insert(static_cast<unsigned short>(vid));
                    }
                }
                info.vids.assign(vidSet.begin(), vidSet.end());
                ceInfos.push_back(std::move(info));
            }
        }
        else {
            for (auto id : reqIds) {
                CEInfo info;
                info.id = id;
                SERVO::CCollectionEvent* e = getEvent(id);
                if (e != nullptr) {
                    info.name = e->getName();
                    std::set<unsigned short> vidSet;
                    for (auto rpt : e->getReports()) {
                        if (rpt == nullptr) continue;
                        for (auto vid : rpt->getVids()) {
                            vidSet.insert(static_cast<unsigned short>(vid));
                        }
                    }
                    info.vids.assign(vidSet.begin(), vidSet.end());
                }
                ceInfos.push_back(std::move(info));
            }
        }
        Unlock();
    }
    IMessage* pMessage = NULL;
    HSMS_Create1Message(pMessage, m_nSessionId, 1, 24, pRecv->getHeader()->systemBytes);
    ASSERT(pMessage);
    ISECS2Item* pList = pMessage->getBody(); // Body is L[n] of {CEID, CENAME, L[VIDs]}
    for (const auto& info : ceInfos) {
        ISECS2Item* pEntry = pList->addItem();
        pEntry->addU2Item(info.id, "CEID");
        pEntry->addItem(info.name.c_str(), "CENAME"); // empty if unknown
        ISECS2Item* pVidList = pEntry->addItem();
        for (auto vid : info.vids) {
            pVidList->addU2Item(vid, "VID");
        }
    }
    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;
}
// S2F13
@@ -1875,7 +2061,7 @@
    m_pPassive->sendMessage(pMessage);
    LOGI("<HSMS>[SEND]sessionId:%d, sType:%d systemBytes:%d",
        pMessage->getHeader()->sessionId, pMessage->getHeader()->sType, pMessage->getHeader()->systemBytes);
    LOGI("<HSMS>[SEND]%s", pMessage->toString());
    LogSecsMessageBrief("<HSMS>[SEND]", pMessage);
    HSMS_Destroy1Message(pMessage);
    return 0;
@@ -2276,7 +2462,7 @@
    m_pPassive->sendMessage(pMessage);
    LOGI("<HSMS>[SEND]sessionId:%d, sType:%d systemBytes:%d",
        pMessage->getHeader()->sessionId, pMessage->getHeader()->sType, pMessage->getHeader()->systemBytes);
    LOGI("<HSMS>[SEND]%s", pMessage->toString());
    LogSecsMessageBrief("<HSMS>[SEND]", pMessage);
    HSMS_Destroy1Message(pMessage);
    
    return 0;
@@ -2381,7 +2567,7 @@
    m_pPassive->sendMessage(pMessage);
    LOGI("<HSMS>[SEND]sessionId:%d, sType:%d systemBytes:%d",
        pMessage->getHeader()->sessionId, pMessage->getHeader()->sType, pMessage->getHeader()->systemBytes);
    LOGI("<HSMS>[SEND]%s", pMessage->toString());
    LogSecsMessageBrief("<HSMS>[SEND]", pMessage);
    HSMS_Destroy1Message(pMessage);
    return 0;
@@ -2554,7 +2740,7 @@
    m_pPassive->sendMessage(pReply);
    LOGI("<HSMS>[SEND]sessionId:%d, sType:%d systemBytes:%d",
        pReply->getHeader()->sessionId, pReply->getHeader()->sType, pReply->getHeader()->systemBytes);
    LOGI("<HSMS>[SEND]%s", pReply->toString());
    LogSecsMessageBrief("<HSMS>[SEND]", pReply);
    HSMS_Destroy1Message(pReply);
@@ -2584,7 +2770,7 @@
        m_pPassive->sendMessage(pMessage);
        LOGI("<HSMS>[SEND]sessionId:%d, sType:%d systemBytes:%d",
            pMessage->getHeader()->sessionId, pMessage->getHeader()->sType, pMessage->getHeader()->systemBytes);
        LOGI("<HSMS>[SEND]%s", pMessage->toString());
        LogSecsMessageBrief("<HSMS>[SEND]", pMessage);
        HSMS_Destroy1Message(pMessage);
        return 0;
    }
@@ -2671,7 +2857,7 @@
    m_pPassive->sendMessage(pMessage);
    LOGI("<HSMS>[SEND]sessionId:%d, sType:%d systemBytes:%d",
        pMessage->getHeader()->sessionId, pMessage->getHeader()->sType, pMessage->getHeader()->systemBytes);
    LOGI("<HSMS>[SEND]%s", pMessage->toString());
    LogSecsMessageBrief("<HSMS>[SEND]", pMessage);
    HSMS_Destroy1Message(pMessage);
SourceCode/Bond/Servo/HsmsPassive.h
@@ -160,6 +160,8 @@
    void setVariableValue(const char* pszName, __int64 value);
    void setVariableValue(const char* pszName, const char* value);
    void setVariableValue(const char* pszName, std::vector<SERVO::CVariable>& vars);
    // 执行一段持锁的代码块,用于保证 set+send 的原子性
    void withVariableLock(const std::function<void()>& fn);
    // 从文件中加载CReport列表
    int loadReports(const char* pszFilepath);
@@ -232,6 +234,8 @@
    int replyAreYouThere(IMessage* pRecv);
    int replyEstablishCommunications(IMessage* pRecv);
    int replySelectedEquipmentStatusData(IMessage* pRecv);
    int replyStatusVariableNamelistRequest(IMessage* pRecv);  // S1F11/S1F12
    int replyCollectionEventNamelistRequest(IMessage* pRecv); // S1F23/S1F24
    int replyOnLine(IMessage* pRecv);
    int replyOffLine(IMessage* pRecv);
    int replyEquipmentConstantRequest(IMessage* pRecv);
SourceCode/Bond/Servo/Model.cpp
@@ -9,6 +9,11 @@
#include "TransferManager.h"
#include "RecipeManager.h"
#include "GlassLogDb.h"
#include "CParam.h"
#include <algorithm>
#include <iomanip>
#include <sstream>
#include <array>
#include <map>
@@ -35,17 +40,17 @@
{
    const auto prev = m_currentControlState;
    if (newState != m_currentControlState) {
        m_hsmsPassive.setVariableValue("PreviousControlState", (__int64)static_cast<uint8_t>(prev));
        m_currentControlState = newState;
    }
    // Always keep SV in sync (even if state didn't change or variables were just loaded).
    m_hsmsPassive.setVariableValue("CurrentControlState", (__int64)static_cast<uint8_t>(m_currentControlState));
    if (newState != prev) {
        // S6F11 (CEID=600): ControlStateChanged
        m_hsmsPassive.requestEventReportSend("ControlStateChanged");
        m_hsmsPassive.withVariableLock([&] {
            m_hsmsPassive.setVariableValue("PreviousControlState", (__int64)static_cast<uint8_t>(prev));
            m_hsmsPassive.setVariableValue("CurrentControlState", (__int64)static_cast<uint8_t>(m_currentControlState));
            m_hsmsPassive.requestEventReportSend("ControlStateChanged");
        });
        notifyInt(RX_CODE_CONTROL_STATE_CHANGED, static_cast<int>(m_currentControlState));
    } else {
        // Keep SV in sync even if unchanged/load-time refresh.
        m_hsmsPassive.setVariableValue("CurrentControlState", (__int64)static_cast<uint8_t>(m_currentControlState));
    }
}
@@ -241,9 +246,11 @@
                    return CAACK_5;
                }
                m_hsmsPassive.setVariableValue("SlotMapScan", pLoadPort->getScanCassetteMap());
                m_hsmsPassive.setVariableValue("SlotMapDownload", pLoadPort->getDownloadCassetteMap());
                m_hsmsPassive.requestEventReportSend_SlotMapVerificationOK();
                m_hsmsPassive.withVariableLock([&] {
                    m_hsmsPassive.setVariableValue("SlotMapScan", pLoadPort->getScanCassetteMap());
                    m_hsmsPassive.setVariableValue("SlotMapDownload", pLoadPort->getDownloadCassetteMap());
                    m_hsmsPassive.requestEventReportSend_SlotMapVerificationOK();
                });
                // Host 确认 SlotMap 后再开始加工/流程
                m_master.proceedWithCarrier(portIndex);
@@ -271,8 +278,10 @@
            vars.push_back(var);
        }
        m_hsmsPassive.setVariableValue("PJQueued", vars);
        m_hsmsPassive.requestEventReportSend_PJ_Queued();
        m_hsmsPassive.withVariableLock([&] {
            m_hsmsPassive.setVariableValue("PJQueued", vars);
            m_hsmsPassive.requestEventReportSend_PJ_Queued();
        });
        return nRet;
    };
    listener.onControlJobCreate = [&](void* pFrom, SERVO::CControlJob& controlJob) -> int {
@@ -298,6 +307,12 @@
    SERVO::MasterListener masterListener;
    auto formatParamValue = [](const CParam& p) {
        std::ostringstream oss;
        oss.setf(std::ios::fixed);
        oss << std::setprecision(4) << p.getDoubleValue();
        return oss.str();
    };
    masterListener.onMasterStateChanged = [&](void* pMaster, SERVO::MASTERSTATE state) -> void {
        LOGI("<CModel>Master state changed(%d)", (int)state);
        notify(RX_CODE_MASTER_STATE_CHANGED);
@@ -376,11 +391,13 @@
    masterListener.onEqVcrEventReport = [&](void* pMaster, SERVO::CEquipment* pEquipment, SERVO::CVcrEventReport* pReport) {
        LOGE("<CModel>onEqVcrEventReport.");
        if (pReport != nullptr) {
            m_hsmsPassive.setVariableValue("VCRPanelID", pReport->getGlassId().c_str());
            int nRet = m_hsmsPassive.requestEventReportSend_OCR_PanelID_Read_OK();
            if (nRet != ER_NOERROR) {
                LOGE("<CModel>requestEventReportSend_OCR_PanelID_Read_OK failed, ret=%d", nRet);
            }
            m_hsmsPassive.withVariableLock([&] {
                m_hsmsPassive.setVariableValue("VCRPanelID", pReport->getGlassId().c_str());
                int nRet = m_hsmsPassive.requestEventReportSend_OCR_PanelID_Read_OK();
                if (nRet != ER_NOERROR) {
                    LOGE("<CModel>requestEventReportSend_OCR_PanelID_Read_OK failed, ret=%d", nRet);
                }
            });
        }
    };
    masterListener.onEqDataChanged = [&](void* pMaster, SERVO::CEquipment* pEquipment, int code) {
@@ -484,99 +501,246 @@
        const int eqId = (pEquipment != nullptr) ? pEquipment->getID() : 0;
        const short prevStatus = s_prevPortStatus[eqId];
        s_prevPortStatus[eqId] = status;
        SERVO::CLoadPort* pLoadPort = dynamic_cast<SERVO::CLoadPort*>(pEquipment);
        // Unified PortStateChange event + SV maintenance
        if (pLoadPort != nullptr) {
            m_hsmsPassive.withVariableLock([&] {
                m_hsmsPassive.setVariableValue("PortTransferState", (__int64)status); // maintain SVID=100
                m_hsmsPassive.setVariableValue("PortStateChangePortId", pLoadPort->getID());
                m_hsmsPassive.setVariableValue("PortState", (__int64)status);
                m_hsmsPassive.requestEventReportSend("PortStateChange");
            });
        }
        if (status == PORT_INUSE) {
            SERVO::CLoadPort* pLoadPort = dynamic_cast<SERVO::CLoadPort*>(pEquipment);
            if (pLoadPort != nullptr) {
                m_hsmsPassive.setVariableValue("CarrierID", pLoadPort->getCassetteId().c_str());
                if (prevStatus != PORT_INUSE && pLoadPort->isCompareMapsBeforeProceeding()) {
                    // TODO(Host协商):
                    // 文档中标明:1-Empty,3-Exist,因此我们可能需要将uint的map转换为list上传
                    m_hsmsPassive.setVariableValue("SlotMap", pLoadPort->getScanCassetteMap());
                    m_hsmsPassive.requestEventReportSend_CheckSlotMap();
            m_hsmsPassive.withVariableLock([&] {
                if (pLoadPort != nullptr) {
                    m_hsmsPassive.setVariableValue("CarrierID", pLoadPort->getCassetteId().c_str());
                    if (prevStatus != PORT_INUSE && pLoadPort->isCompareMapsBeforeProceeding()) {
                        // TODO(Host协商):
                        // 文档中标明:1-Empty,3-Exist,因此我们可能需要将uint的map转换为list上传
                        m_hsmsPassive.setVariableValue("SlotMap", pLoadPort->getScanCassetteMap());
                        m_hsmsPassive.requestEventReportSend_CheckSlotMap();
                    }
                }
            }
            m_hsmsPassive.requestEventReportSend_CarrierID_Readed();
                m_hsmsPassive.requestEventReportSend_CarrierID_Readed();
            });
        }
        else if (status == PORT_BLOCKED) {
            SERVO::CLoadPort* pLoadPort = dynamic_cast<SERVO::CLoadPort*>(pEquipment);
            if (pLoadPort != nullptr) {
                m_hsmsPassive.setVariableValue("BlockedPortId", pLoadPort->getID());
            }
            m_hsmsPassive.requestEventReportSend_Port_Blocked();
            m_hsmsPassive.withVariableLock([&] {
                if (pLoadPort != nullptr) {
                    m_hsmsPassive.setVariableValue("BlockedPortId", pLoadPort->getID());
                }
                m_hsmsPassive.requestEventReportSend_Port_Blocked();
            });
        }
        else if (status == PORT_LOAD_READY) {
            SERVO::CLoadPort* pLoadPort = dynamic_cast<SERVO::CLoadPort*>(pEquipment);
            if (pLoadPort != nullptr) {
                m_hsmsPassive.setVariableValue("LoadReadyPortId", pLoadPort->getID());
            }
            m_hsmsPassive.requestEventReportSend_Port_Load_Ready();
            m_hsmsPassive.withVariableLock([&] {
                if (pLoadPort != nullptr) {
                    m_hsmsPassive.setVariableValue("LoadReadyPortId", pLoadPort->getID());
                }
                m_hsmsPassive.requestEventReportSend_Port_Load_Ready();
            });
        }
        else if (status == PORT_UNLOAD_READY) {
            SERVO::CLoadPort* pLoadPort = dynamic_cast<SERVO::CLoadPort*>(pEquipment);
            if (pLoadPort != nullptr) {
                m_hsmsPassive.setVariableValue("UnloadReadyPortId", pLoadPort->getID());
                if (prevStatus == PORT_INUSE) {
                    m_hsmsPassive.setVariableValue("ReadyToReleasePortId", pLoadPort->getID());
                    m_hsmsPassive.requestEventReportSend_Port_Ready_To_Release();
            m_hsmsPassive.withVariableLock([&] {
                if (pLoadPort != nullptr) {
                    m_hsmsPassive.setVariableValue("UnloadReadyPortId", pLoadPort->getID());
                    if (prevStatus == PORT_INUSE) {
                        m_hsmsPassive.setVariableValue("ReadyToReleasePortId", pLoadPort->getID());
                        m_hsmsPassive.requestEventReportSend_Port_Ready_To_Release();
                    }
                }
            }
            m_hsmsPassive.requestEventReportSend_Port_Unload_Ready();
                m_hsmsPassive.requestEventReportSend_Port_Unload_Ready();
            });
        }
        else if (status == PORT_EMPTY) {
            SERVO::CLoadPort* pLoadPort = dynamic_cast<SERVO::CLoadPort*>(pEquipment);
            if (pLoadPort != nullptr) {
                m_hsmsPassive.setVariableValue("LoadPortNotAssocPortId", pLoadPort->getID());
            }
            m_hsmsPassive.requestEventReportSend_LoadPortNotAssoc();
            m_hsmsPassive.withVariableLock([&] {
                if (pLoadPort != nullptr) {
                    m_hsmsPassive.setVariableValue("LoadPortNotAssocPortId", pLoadPort->getID());
                }
                m_hsmsPassive.requestEventReportSend_LoadPortNotAssoc();
            });
        }
        notifyPtr(RX_CODE_LOADPORT_STATUS_CHANGED, pEquipment);
    };
    masterListener.onProcessStateChanged = [&](void* pMaster, SERVO::CEquipment* pEquipment, int slotNo, SERVO::PROCESS_STATE state) {
        // SubEqpStart/SubEqpEnd: align to log's EV_SubEqpStart/EV_SubEqpEnd stage (no report payload required).
    masterListener.onProcessStateChanged = [&](void* pMaster, SERVO::CEquipment* pEquipment, int slotNo, SERVO::PROCESS_STATE prevState, SERVO::PROCESS_STATE state) {
        (void)pMaster;
        if (pEquipment != nullptr) {
            m_hsmsPassive.setVariableValue("SubEqpName", pEquipment->getName().c_str());
        const int eqId = pEquipment ? pEquipment->getID() : 0;
        // 保持同一锁范围内:更新所需 SV 并依次上报,保证 set+send 原子性
        m_hsmsPassive.withVariableLock([&] {
            // Timestamp VID (Clock, VID=500) for all related reports.
            m_hsmsPassive.setVariableValue("Clock", CToolUnits::getCurrentTimeString().c_str());
            // Common payload VIDs for SubEqp/Unit
            if (pEquipment != nullptr) {
                m_hsmsPassive.setVariableValue("SubEqpName", pEquipment->getName().c_str());
            }
            m_hsmsPassive.setVariableValue("SubEqpSlot", slotNo);
            // ProcessStateChanged (equipment-level): update SVs 700/701, then report CEID=700
            m_hsmsPassive.setVariableValue("PreviousProcessState", (__int64)prevState);
            m_hsmsPassive.setVariableValue("CurrentProcessState", (__int64)state);
            m_hsmsPassive.requestEventReportSend("ProcessStateChanged");
            // SubEqp events (per equipment, ignore slot distinction except payload)
            static std::map<int, SERVO::PROCESS_STATE> s_prevSubEqpState;
            const auto prevEqState = s_prevSubEqpState[eqId];
            if (prevEqState != state) {
                // state change
                m_hsmsPassive.requestEventReportSend("SubEqpStateChange");
            }
            if (state == SERVO::PROCESS_STATE::Processing) {
                m_hsmsPassive.requestEventReportSend_SubEqpStart();
            }
            else if (state == SERVO::PROCESS_STATE::Complete) {
                m_hsmsPassive.requestEventReportSend_SubEqpEnd();
            }
            s_prevSubEqpState[eqId] = state;
            // Unit events (per equipment slot)
            static std::map<int, std::map<int, SERVO::PROCESS_STATE>> s_prevUnitState;
            const auto prevUnitState = s_prevUnitState[eqId][slotNo];
            if (prevUnitState != state) {
                m_hsmsPassive.requestEventReportSend("UnitStateChange");
                if (state == SERVO::PROCESS_STATE::Processing) {
                    m_hsmsPassive.requestEventReportSend("UnitStart");
                }
                else if (state == SERVO::PROCESS_STATE::Complete) {
                    m_hsmsPassive.requestEventReportSend("UnitEnd");
                }
                s_prevUnitState[eqId][slotNo] = state;
            }
        });
    };
    masterListener.onSVDataReport = [&](void* pMaster, SERVO::CEquipment* pEquipment, const std::vector<CParam>& params) {
        (void)pMaster;
        const int eqId = pEquipment ? pEquipment->getID() : 0;
        auto sendSv = [&](const auto& vidMap, const char* evName) {
            const size_t count = (std::min)(params.size(), vidMap.size());
            m_hsmsPassive.withVariableLock([&] {
                m_hsmsPassive.setVariableValue("Clock", CToolUnits::getCurrentTimeString().c_str());
                for (size_t idx = 0; idx < count; ++idx) {
                    const std::string val = formatParamValue(params[idx]);
                    m_hsmsPassive.setVariableValue(std::to_string(vidMap[idx]).c_str(), val.c_str());
                }
                m_hsmsPassive.requestEventReportSend(evName);
            });
        };
        if (eqId == EQ_ID_Bonder1 || eqId == EQ_ID_Bonder2) {
            static constexpr std::array<int, 19> vids = {
                6000,6001,6002,6003,6004,6005,6006,6007,6008,6009,
                6010,6011,6012,6013,6014,6015,6016,6017,6018
            };
            sendSv(vids, "BonderSVData");
        }
        m_hsmsPassive.setVariableValue("SubEqpSlot", slotNo);
        if (state == SERVO::PROCESS_STATE::Processing) {
            m_hsmsPassive.requestEventReportSend_SubEqpStart();
        else if (eqId == EQ_ID_VACUUMBAKE) {
            static constexpr std::array<int, 18> vids = {
                6200,6201,6202,6203,6204,6205,6206,6207,6208,
                6209,6210,6211,6212,6213,6214,6215,6216,6217
            };
            sendSv(vids, "VacuumBakeSVData");
        }
        else if (state == SERVO::PROCESS_STATE::Complete) {
            m_hsmsPassive.requestEventReportSend_SubEqpEnd();
        else if (eqId == EQ_ID_BAKE_COOLING) {
            static constexpr std::array<int, 20> vids = {
                6400,6401,6402,6403,6404,6405,6406,6407,6408,6409,
                6410,6411,6412,6413,6414,6415,6416,6417,6418,6419
            };
            sendSv(vids, "BakeCoolingSVData");
        }
        else if (eqId == EQ_ID_MEASUREMENT) {
            static constexpr std::array<int, 2> vids = { 6600, 6601 };
            sendSv(vids, "MeasurementSVData");
        }
    };
    masterListener.onProcessDataReport = [&](void* pMaster, SERVO::CEquipment* pEquipment, const std::vector<CParam>& params) {
        (void)pMaster;
        const int eqId = pEquipment ? pEquipment->getID() : 0;
        auto sendProcess = [&](const auto& vidMap, const char* evName) {
            const size_t count = (std::min)(params.size(), vidMap.size());
            m_hsmsPassive.withVariableLock([&] {
                m_hsmsPassive.setVariableValue("Clock", CToolUnits::getCurrentTimeString().c_str());
                for (size_t idx = 0; idx < count; ++idx) {
                    const std::string val = formatParamValue(params[idx]);
                    m_hsmsPassive.setVariableValue(std::to_string(vidMap[idx]).c_str(), val.c_str());
                }
                m_hsmsPassive.requestEventReportSend(evName);
            });
        };
        if (eqId == EQ_ID_Bonder1 || eqId == EQ_ID_Bonder2) {
            static constexpr std::array<int, 22> vids = {
                6100,6101,6102,6103,6104,6105,6106,6107,6108,6109,6110,
                6111,6112,6113,6114,6115,6116,6117,6118,6119,6120,6121
            };
            sendProcess(vids, "BonderProcessData");
        }
        else if (eqId == EQ_ID_VACUUMBAKE) {
            static constexpr std::array<int, 5> vids = { 6300,6301,6302,6303,6304 };
            sendProcess(vids, "VacuumBakeProcessData");
        }
        else if (eqId == EQ_ID_BAKE_COOLING) {
            static constexpr std::array<int, 4> vids = { 6500,6501,6502,6503 };
            sendProcess(vids, "BakeCoolingProcessData");
        }
        else if (eqId == EQ_ID_MEASUREMENT) {
            static constexpr std::array<int, 4> vids = { 6700,6701,6702,6703 };
            sendProcess(vids, "MeasurementProcessData");
        }
    };
    masterListener.onCTRoundEnd = [&](void* pMaster, int round) {
        m_configuration.setContinuousTransferCount(round);
    };
    masterListener.onCjStart = [&](void* pMaster, void* pj) {
        m_hsmsPassive.setVariableValue("CJStartID", ((SERVO::CControlJob*)pj)->id().c_str());
        m_hsmsPassive.requestEventReportSend_CJ_Start();
        m_hsmsPassive.withVariableLock([&] {
            m_hsmsPassive.setVariableValue("CJStartID", ((SERVO::CControlJob*)pj)->id().c_str());
            m_hsmsPassive.requestEventReportSend_CJ_Start();
        });
    };
    masterListener.onCjEnd = [&](void* pMaster, void* pj) {
        m_hsmsPassive.setVariableValue("CJEndID", ((SERVO::CControlJob*)pj)->id().c_str());
        m_hsmsPassive.requestEventReportSend_CJ_End();
        m_hsmsPassive.withVariableLock([&] {
            m_hsmsPassive.setVariableValue("CJEndID", ((SERVO::CControlJob*)pj)->id().c_str());
            m_hsmsPassive.requestEventReportSend_CJ_End();
        });
        // 结批,保存ControlJob
        // 
    };
    masterListener.onPjStart = [&](void* pMaster, void* pj) {
        m_hsmsPassive.setVariableValue("PJStartID", ((SERVO::CProcessJob*)pj)->id().c_str());
        m_hsmsPassive.requestEventReportSend_PJ_Start();
        m_hsmsPassive.withVariableLock([&] {
            m_hsmsPassive.setVariableValue("PJStartID", ((SERVO::CProcessJob*)pj)->id().c_str());
            m_hsmsPassive.requestEventReportSend_PJ_Start();
        });
    };
    masterListener.onPjEnd = [&](void* pMaster, void* pj) {
        m_hsmsPassive.setVariableValue("PJEndID", ((SERVO::CProcessJob*)pj)->id().c_str());
        m_hsmsPassive.requestEventReportSend_PJ_End();
        m_hsmsPassive.withVariableLock([&] {
            m_hsmsPassive.setVariableValue("PJEndID", ((SERVO::CProcessJob*)pj)->id().c_str());
            m_hsmsPassive.requestEventReportSend_PJ_End();
        });
    };
    masterListener.onPanelStart = [&](void* pMaster, void* pPanel) {
        m_hsmsPassive.setVariableValue("PanelStartID", ((SERVO::CGlass*)pPanel)->getID().c_str());
        m_hsmsPassive.requestEventReportSend_Panel_Start();
        m_hsmsPassive.withVariableLock([&] {
            m_hsmsPassive.setVariableValue("PanelStartID", ((SERVO::CGlass*)pPanel)->getID().c_str());
            m_hsmsPassive.requestEventReportSend_Panel_Start();
        });
    };
    masterListener.onPanelEnd = [&](void* pMaster, void* pPanel) {
        m_hsmsPassive.setVariableValue("PanelEndID", ((SERVO::CGlass*)pPanel)->getID().c_str());
        m_hsmsPassive.requestEventReportSend_Panel_End();
        // Placeholder payload to match log shape: EV_PROCESS_DATA_REPORT can carry a single A-string (may be empty).
        m_hsmsPassive.setVariableValue("ProcessDataReportText", "");
        m_hsmsPassive.requestEventReportSend_ProcessDataReport();
        m_hsmsPassive.withVariableLock([&] {
            m_hsmsPassive.setVariableValue("PanelEndID", ((SERVO::CGlass*)pPanel)->getID().c_str());
            m_hsmsPassive.requestEventReportSend_Panel_End();
            // Placeholder payload to match log shape: EV_PROCESS_DATA_REPORT can carry a single A-string (may be empty).
            m_hsmsPassive.setVariableValue("ProcessDataReportText", "");
            m_hsmsPassive.requestEventReportSend_ProcessDataReport();
        });
        auto& db = GlassLogDb::Instance();
        db.insertFromCGlass((*(SERVO::CGlass*)pPanel));
        SERVO::CGlass* pBuddy = ((SERVO::CGlass*)pPanel)->getBuddy();
SourceCode/Bond/x64/Debug/CollectionEventList.txt
@@ -6,6 +6,7 @@
10018,ProcessDataReport,,(33)
10015,SubEqpStart,,(10015)
10016,SubEqpEnd,,(10016)
10017,SubEqpStateChange,,(10017)
10000,RecipeChanged,,(10000)
10030,CarrierArrived,,(10300)
10031,CarrierRemoved,,(10300)
@@ -55,3 +56,15 @@
50010,Port_Blocked,,(50010)
50011,OCR_PanelID_Read_OK,扫码事件上报,(50012)
50012,Port_Ready_To_Release,,(50013)
50020,PortStateChange,,(50020)
60000,BonderSVData,,(60000)
61000,BonderProcessData,,(61000)
62000,VacuumBakeSVData,,(62000)
63000,VacuumBakeProcessData,,(63000)
64000,BakeCoolingSVData,,(64000)
65000,BakeCoolingProcessData,,(65000)
66000,MeasurementSVData,,(66000)
67000,MeasurementProcessData,,(67000)
12000,UnitStart,,(12000)
12001,UnitStateChange,,(12001)
12002,UnitEnd,,(12002)
SourceCode/Bond/x64/Debug/ReportList.txt
@@ -31,5 +31,18 @@
50012,(5014)
50013,(5015)
50014,(5016)
50020,(500,5020,5021)
60000,(500,6000,6001,6002,6003,6004,6005,6006,6007,6008,6009,6010,6011,6012,6013,6014,6015,6016,6017,6018)
61000,(500,6100,6101,6102,6103,6104,6105,6106,6107,6108,6109,6110,6111,6112,6113,6114,6115,6116,6117,6118,6119,6120,6121)
62000,(500,6200,6201,6202,6203,6204,6205,6206,6207,6208,6209,6210,6211,6212,6213,6214,6215,6216,6217)
63000,(500,6300,6301,6302,6303,6304)
64000,(500,6400,6401,6402,6403,6404,6405,6406,6407,6408,6409,6410,6411,6412,6413,6414,6415,6416,6417,6418,6419)
65000,(500,6500,6501,6502,6503)
66000,(500,6600,6601)
67000,(500,6700,6701,6702,6703)
10015,(5018,5019)
10016,(5018,5019)
10017,(500,5018)
12000,(500,5018,5019)
12001,(500,5018,5019)
12002,(500,5018,5019)
SourceCode/Bond/x64/Debug/VariableList.txt
@@ -54,6 +54,102 @@
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)