chenluhua1980
2026-01-08 9c9100b078e9ac4ee7ed61500b4d7c7a74207549
1.继续完善模拟测试等
已修改11个文件
136 ■■■■ 文件已修改
SourceCode/Bond/EAPSimulator/CHsmsActive.cpp 48 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/EAPSimulator/CHsmsActive.h 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/EAPSimulator/CPJsDlg.cpp 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/EAPSimulator/EAPSimulator.rc 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/EAPSimulator/EAPSimulatorDlg.cpp 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/EAPSimulator/EAPSimulatorDlg.h 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/EAPSimulator/Resource.h 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CLoadPort.cpp 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CMaster.cpp 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/HsmsPassive.cpp 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/Model.cpp 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/EAPSimulator/CHsmsActive.cpp
@@ -1,9 +1,9 @@
#include "pch.h"
#include "pch.h"
#include "CHsmsActive.h"
#include "Log.h"
static unsigned int DATAID = 1;
static unsigned short DATAID = 1;
CHsmsActive::CHsmsActive()
{
@@ -64,7 +64,7 @@
        HEADER* pHeader = pMessage->getHeader();
        int nStream = (pHeader->stream & 0x7F);
        TRACE("收到消息 S%dF%d================\n", pHeader->stream & 0x7F, pHeader->function);
        TRACE("收到消息 S%dF%d================\n", pHeader->stream & 0x7F, pHeader->function);
        TRACE("Body:%s\n", pMessage->toString());
        LOGI("onRecvDataMessage(%s).", pMessage->toString());
@@ -349,12 +349,50 @@
    return hsmsCarrierActionRequest(DATAID, "CarrierRelease", pszCarrierId, PTN);
}
int CHsmsActive::hsmsProceedWithSlotMap(unsigned int DATAID,
    const char* pszCarrierId,
    unsigned char PTN,
    const char* pszLotId,
    const std::vector<std::string>& panelIds,
    const std::vector<unsigned char>& slotMap)
{
    IMessage* pMessage = nullptr;
    int nRet = HSMS_Create1Message(pMessage, m_nSessionId, 3 | REPLY, 17, ++m_nSystemByte);
    if (nRet != 0 || pMessage == nullptr) {
        return nRet;
    }
    pMessage->getBody()->addU4Item(DATAID, "DATAID");
    pMessage->getBody()->addItem("ProceedWithSlotMap", "CARRIERACTION");
    pMessage->getBody()->addItem(pszCarrierId, "CARRIERID");
    pMessage->getBody()->addU1Item(PTN, "PTN");
    // Extended params (currently not parsed by Servo side): { LOTID, PANELID_LIST, SLOTMAP_LIST }
    ISECS2Item* pParams = pMessage->getBody()->addItem(); // L
    pParams->addItem(pszLotId != nullptr ? pszLotId : "", "LOTID");
    ISECS2Item* pPanelList = pParams->addItem(); // L
    for (const auto& id : panelIds) {
        pPanelList->addItem(id.c_str(), "PANELID");
    }
    ISECS2Item* pSlotMapList = pParams->addItem(); // L
    for (auto v : slotMap) {
        pSlotMapList->addU1Item(v, "SLOTSTATE");
    }
    m_pActive->sendMessage(pMessage);
    HSMS_Destroy1Message(pMessage);
    return 0;
}
int CHsmsActive::hsmsPRJobMultiCreate(std::vector<SERVO::CProcessJob*>& pjs)
{
    IMessage* pMessage = nullptr;
    int nRet = HSMS_Create1Message(pMessage, m_nSessionId, 16 | REPLY, 15, ++m_nSystemByte);
    char szMF[32] = {14};
    pMessage->getBody()->addU4Item(++DATAID, "DATAID");
    pMessage->getBody()->addU2Item(++DATAID, "DATAID");
    auto itemPjs = pMessage->getBody()->addItem();
    for (auto pj : pjs) {
        auto itemPj = itemPjs->addItem();
@@ -434,7 +472,7 @@
    return 0;
}
// 通用的reply ack函数
// 通用的reply ack函数
void CHsmsActive::replyAck(int s, int f, unsigned int systemBytes, BYTE ack, const char* pszAckName)
{
    IMessage* pMessage = NULL;
SourceCode/Bond/EAPSimulator/CHsmsActive.h
@@ -1,4 +1,4 @@
#pragma once
#pragma once
#include <string>
#include <vector>
#include <map>
@@ -36,7 +36,7 @@
    // Deselect Request
    int hsmsDeselectRequest();
    // 建立通讯(S1F13)
    // 建立通讯(S1F13)
    int hsmsEstablishCommunications();
    // Are You There
@@ -63,18 +63,18 @@
    // Configure Spooling
    int hsmsConfigureSpooling(std::map<unsigned int, std::set<unsigned int>>& spoolingConfig);
    // 发送或清空缓存的消息
    // 发送或清空缓存的消息
    int hsmsTransmitSpooledData();
    int hsmsPurgeSpooledData();
    // 查询变量
    // 查询变量
    int hsmsSelectedEquipmentStatusRequest(unsigned int SVID);
    // 查询PPID List
    // 查询PPID List
    int hsmsQueryPPIDList();
    // S3F17
    // 卡匣动作请求
    // 卡匣动作请求
    int hsmsCarrierActionRequest(unsigned int DATAID, 
        const char* pszCarrierAction,
        const char* pszCarrierId,
@@ -82,7 +82,13 @@
    int hsmsProceedWithCarrier(unsigned int DATAID,
        const char* pszCarrierId,
        unsigned char PTN);
    int CHsmsActive::hsmsCarrierRelease(unsigned int DATAID,
    int hsmsProceedWithSlotMap(unsigned int DATAID,
        const char* pszCarrierId,
        unsigned char PTN,
        const char* pszLotId,
        const std::vector<std::string>& panelIds,
        const std::vector<unsigned char>& slotMap);
    int hsmsCarrierRelease(unsigned int DATAID,
        const char* pszCarrierId,
        unsigned char PTN);
@@ -92,7 +98,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/CPJsDlg.cpp
@@ -98,7 +98,7 @@
    {
        SERVO::CProcessJob* pj = new SERVO::CProcessJob("PJ0001");
        std::vector<uint8_t> slots1{ 1, 2, 3 };
        pj->addCarrier("CID1001", slots1);
        pj->addCarrier("Test-Cassette-001", slots1);
        pj->setRecipe(SERVO::RecipeMethod::NoTuning, "P1001");
        m_pjs.push_back(pj);
    }
SourceCode/Bond/EAPSimulator/EAPSimulator.rc
Binary files differ
SourceCode/Bond/EAPSimulator/EAPSimulatorDlg.cpp
@@ -9,6 +9,8 @@
#include "afxdialogex.h"
#include "Common.h"
#include <regex>
#include <string>
#include <vector>
#include "CTerminalDisplayDlg.h"
#include "CEDEventReportDlg.h"
#include "CDefineReportsDlg.h"
@@ -90,6 +92,7 @@
    ON_BN_CLICKED(IDC_BUTTON_PURGE_SPOOLED_DATA, &CEAPSimulatorDlg::OnBnClickedButtonPurgeSpooledData)
    ON_BN_CLICKED(IDC_BUTTON_QUERY_PPID_LIST, &CEAPSimulatorDlg::OnBnClickedButtonQueryPpidList)
    ON_BN_CLICKED(IDC_BUTTON_PROCEED_WITH_CARRIER, &CEAPSimulatorDlg::OnBnClickedButtonProceedWithCarrier)
    ON_BN_CLICKED(IDC_BUTTON_PROCEED_WITH_SLOTMAP, &CEAPSimulatorDlg::OnBnClickedButtonProceedWithSlotMap)
    ON_BN_CLICKED(IDC_BUTTON_CARRIER_RELEASE, &CEAPSimulatorDlg::OnBnClickedButtonCarrierRelease)
    ON_BN_CLICKED(IDC_BUTTON_QUERY_CJ_SPACE, &CEAPSimulatorDlg::OnBnClickedButtonQueryCjSpace)
    ON_BN_CLICKED(IDC_BUTTON_QUERY_PJ_SPACE, &CEAPSimulatorDlg::OnBnClickedButtonQueryPjSpace)
@@ -177,6 +180,19 @@
    //  执行此操作
    SetIcon(m_hIcon, TRUE);            // 设置大图标
    SetIcon(m_hIcon, FALSE);        // 设置小图标
    // Add missing test button at runtime (resource file is UTF-16, keep it unchanged)
    {
        CRect rc(126, 120, 126 + 108, 120 + 14); // dialog units
        MapDialogRect(&rc);
        HWND hBtn = ::CreateWindow(_T("BUTTON"), _T("S3F17_ProceedWithSlotMap"),
            WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
            rc.left, rc.top, rc.Width(), rc.Height(),
            m_hWnd, (HMENU)IDC_BUTTON_PROCEED_WITH_SLOTMAP, 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);
@@ -283,6 +299,9 @@
    GetDlgItem(IDC_BUTTON_PURGE_SPOOLED_DATA)->EnableWindow(enabled);
    GetDlgItem(IDC_BUTTON_QUERY_PPID_LIST)->EnableWindow(enabled);    
    GetDlgItem(IDC_BUTTON_PROCEED_WITH_CARRIER)->EnableWindow(enabled);    
    if (GetDlgItem(IDC_BUTTON_PROCEED_WITH_SLOTMAP) != nullptr) {
        GetDlgItem(IDC_BUTTON_PROCEED_WITH_SLOTMAP)->EnableWindow(enabled);
    }
    GetDlgItem(IDC_BUTTON_CARRIER_RELEASE)->EnableWindow(enabled);
    GetDlgItem(IDC_BUTTON_QUERY_CJ_SPACE)->EnableWindow(enabled);
    GetDlgItem(IDC_BUTTON_QUERY_PJ_SPACE)->EnableWindow(enabled);
@@ -406,6 +425,19 @@
    theApp.m_model.m_pHsmsActive->hsmsProceedWithCarrier(DATAID++, "CSX 52078", 1);
}
void CEAPSimulatorDlg::OnBnClickedButtonProceedWithSlotMap()
{
    // Example payload (edit as needed)
    std::vector<std::string> panelIds = {
        "PANEL_01","PANEL_02","PANEL_03","PANEL_04",
        "PANEL_05","PANEL_06","PANEL_07","PANEL_08"
    };
    std::vector<unsigned char> slotMap = {
        3,3,1,1,1,1,1,1 // 1=Empty, 3=Exist
    };
    theApp.m_model.m_pHsmsActive->hsmsProceedWithSlotMap(DATAID++, "CSX 52078", 1, "LOT_0001", panelIds, slotMap);
}
void CEAPSimulatorDlg::OnBnClickedButtonCarrierRelease()
{
    theApp.m_model.m_pHsmsActive->hsmsCarrierRelease(DATAID++, "CSX 52078", 2);
@@ -419,6 +451,6 @@
void CEAPSimulatorDlg::OnBnClickedButtonCreateCj()
{
    std::vector<std::string> processJobIds = {"PJ0001", "PJ0003"};
    std::vector<std::string> processJobIds = {"PJ0001"};
    theApp.m_model.m_pHsmsActive->hsmsCreateControlJob("CJ5007", processJobIds);
}
SourceCode/Bond/EAPSimulator/EAPSimulatorDlg.h
@@ -58,6 +58,7 @@
    afx_msg void OnBnClickedButtonPurgeSpooledData();
    afx_msg void OnBnClickedButtonQueryPpidList();
    afx_msg void OnBnClickedButtonProceedWithCarrier();
    afx_msg void OnBnClickedButtonProceedWithSlotMap();
    afx_msg void OnBnClickedButtonCarrierRelease();
    afx_msg void OnBnClickedButtonQueryCjSpace();
    afx_msg void OnBnClickedButtonQueryPjSpace();
SourceCode/Bond/EAPSimulator/Resource.h
@@ -57,6 +57,7 @@
#define IDC_BUTTON_CREATE_PJ2           1040
#define IDC_BUTTON_CREATE_CJ            1040
#define IDC_BUTTON_DELETE               1041
#define IDC_BUTTON_PROCEED_WITH_SLOTMAP 1042
// Next default values for new objects
// 
@@ -64,7 +65,7 @@
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE        143
#define _APS_NEXT_COMMAND_VALUE         32771
#define _APS_NEXT_CONTROL_VALUE         1042
#define _APS_NEXT_CONTROL_VALUE         1043
#define _APS_NEXT_SYMED_VALUE           101
#endif
#endif
SourceCode/Bond/Servo/CLoadPort.cpp
@@ -364,7 +364,6 @@
        // 模拟测试
        /*
        if (m_nIndex == 0) {
            static int ii = 0;
            ii++;
@@ -377,6 +376,7 @@
                portStatusReport.setCassetteId("CID1001");
                int nRet = portStatusReport.serialize(szBuffer, 64);
                decodePortStatusReport(pStep, szBuffer, 64);
                LOGI("<CLoadPort>Port1载入模拟数据, id:CID1001 map: 0xf");
            }
        }
        if (m_nIndex == 1) {
@@ -391,9 +391,9 @@
                portStatusReport.setCassetteId("CID1004");
                int nRet = portStatusReport.serialize(szBuffer, 64);
                decodePortStatusReport(pStep, szBuffer, 64);
                LOGI("<CLoadPort>Port2载入模拟数据, id:CID1004 map: 0xff");
            }
        }
        */
    }
    void CLoadPort::serialize(CArchive& ar)
SourceCode/Bond/Servo/CMaster.cpp
@@ -2082,8 +2082,8 @@
                static bool inited = false;
                static SERVO::CGlass simGlass;
                static SERVO::CVcrEventReport simVcr;
                static SERVO::CProcessJob simPj("SIM_PJ_001");
                static SERVO::CControlJob simCj("SIM_CJ_001");
                static SERVO::CProcessJob simPj("PJ1001");
                static SERVO::CControlJob simCj("CJ5007");
                if (!inited) {
                    inited = true;
@@ -2814,6 +2814,9 @@
        this->saveState();
        if (m_listener.onControlJobChanged) {
            m_listener.onControlJobChanged(this);
        }
        return (int)m_processJobs.size();
    }
SourceCode/Bond/Servo/HsmsPassive.cpp
@@ -2585,9 +2585,6 @@
        pjs.push_back(pj);
    }
    ASSERT(m_listener.onPRJobMultiCreate != nullptr);
    int nRet = m_listener.onPRJobMultiCreate(this, pjs);
    // 回复报文
    IMessage* pMessage = NULL;
@@ -2622,6 +2619,10 @@
    HSMS_Destroy1Message(pMessage);
    ASSERT(m_listener.onPRJobMultiCreate != nullptr);
    int nRet = m_listener.onPRJobMultiCreate(this, pjs);
    // 释放有问题(未添加到master)的内存
    for (auto p : pjs) {
        if(!p->issues().empty()) delete p;
SourceCode/Bond/Servo/Model.cpp
@@ -26,6 +26,9 @@
{
    // CJobSpace: how many ControlJobs can be created (current implementation supports 0/1).
    m_hsmsPassive.setVariableValue("CJobSpace", (__int64)(m_master.canCreateControlJob() ? 1 : 0));
    // PJobSpace: how many ProcessJobs can be created (current implementation supports 0/1).
    m_hsmsPassive.setVariableValue("PJobSpace", (__int64)(m_master.isProcessJobsEmpty() ? 1 : 0));
}
IObservable* CModel::getObservable()
@@ -181,11 +184,13 @@
            const unsigned int portIndex = PTN - 1;
            SERVO::CLoadPort* pLoadPort = (SERVO::CLoadPort*)m_master.getEquipment(EQ_ID_LOADPORT1 + portIndex);
            LOGI("<Model>onCarrierAction %d, %s, %d, %d", DATAID, pszCarrierAction, pszCarrierId, PTN);
            if (_strcmpi(pszCarrierAction, "ProceedWithCarrier") == 0) {
                // 文档流程:ProceedWithCarrier 之后设备进入 Check SlotMap(WFH),
                // 真正的“开始”由 ProceedWithSlotMap 决策触发。
                // 仅当未开启 CompareMapsBeforeProceeding 时,才沿用旧逻辑直接 Start。
                LOGI("<CModel>ProceedWithCarrier");
                if (pLoadPort == nullptr || !pLoadPort->isCompareMapsBeforeProceeding()) {
                    m_master.proceedWithCarrier(portIndex);
                }
@@ -197,6 +202,7 @@
                // 当前 S3F17 解析结构仅支持 {DATAID, CarrierAction, CarrierID, PTN},尚未实现上述扩展字段的解析/校验。
                // 未来若客户确认 SECS-II 结构,需要在 CHsmsPassive::replyCarrierAction() 扩展解析并在此处落库/校验。
                // 仅在 CompareMapsBeforeProceeding 启用(Host 模式)下允许此动作
                LOGI("<CModel>ProceedWithSlotMap");
                if (pLoadPort == nullptr || !pLoadPort->isCompareMapsBeforeProceeding()) {
                    strErrorTxt = "rejected - SlotMap check disabled";
                    return CAACK_5;
@@ -211,13 +217,13 @@
                return CAACK_0;
            }
            else if (_strcmpi(pszCarrierAction, "CarrierRelease") == 0) {
                LOGI("<CModel>CarrierRelease");
                m_master.carrierRelease(portIndex);
                return CAACK_0;
            }
            strErrorTxt = "rejected - invalid state";
            return CAACK_5;
            LOGI("<Model>onCarrierAction %d, %s, %d, %d", DATAID, pszCarrierAction, pszCarrierId, PTN);
    };
    listener.onPRJobMultiCreate = [&](void* pFrom, std::vector<SERVO::CProcessJob*>& pjs) -> int {
        for (auto p : pjs) {