mrDarker
2025-09-04 1c8098f74227411b5417c560eb7e6d7c0a61ae6e
Merge branch 'clh' into liuyang

# Conflicts:
# SourceCode/Bond/Servo/PageRecipe.cpp
# SourceCode/Bond/Servo/RecipeManager.h
已添加6个文件
已修改36个文件
1541 ■■■■ 文件已修改
Document/CEID.xlsx 补丁 | 查看 | 原始文档 | blame | 历史
Document/EO2860AVA-101工艺参数(1).xlsx 补丁 | 查看 | 原始文档 | blame | 历史
Document/EO2860AVA-101工艺参数.xlsx 补丁 | 查看 | 原始文档 | blame | 历史
Document/ESWIN_EAS_Bonder_Inline_Mapping_Address_v1.1.10.xlsx 补丁 | 查看 | 原始文档 | blame | 历史
Document/Panel Bonder八零联合 SecsTest CheckList_v3.0.xlsx 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CBakeCooling.cpp 89 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CBakeCooling.h 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CBonder.cpp 136 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CBonder.h 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CEFEM.cpp 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CEquipment.cpp 100 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CEquipment.h 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CEquipmentPage2.cpp 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CJobDataS.cpp 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CLoadPort.cpp 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CMaster.cpp 235 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CMaster.h 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CMeasurement.cpp 67 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CMeasurement.h 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CParam.cpp 107 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CParam.h 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CRecipeList.cpp 129 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CRecipeList.h 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CRecipesManager.cpp 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CRecipesManager.h 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CRobotTask.cpp 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CVacuumBake.cpp 96 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CVacuumBake.h 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/HsmsPassive.cpp 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/HsmsPassive.h 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/Model.cpp 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/PageRecipe.cpp 213 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/PageRecipe.h 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/RecipeManager.h 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/Servo.vcxproj 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/Servo.vcxproj.filters 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/Servo.vcxproj.user 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/ServoCommo.h 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/ServoDlg.cpp 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/x64/Debug/CollectionEventList.txt 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/x64/Debug/ReportList.txt 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/x64/Debug/VariableList.txt 62 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Document/CEID.xlsx
Binary files differ
Document/EO2860AVA-101¹¤ÒÕ²ÎÊý(1).xlsx
Binary files differ
Document/EO2860AVA-101¹¤ÒÕ²ÎÊý.xlsx
Binary files differ
Document/ESWIN_EAS_Bonder_Inline_Mapping_Address_v1.1.10.xlsx
Binary files differ
Document/Panel Bonder°ËÁãÁªºÏ SecsTest CheckList_v3.0.xlsx
Binary files differ
SourceCode/Bond/Servo/CBakeCooling.cpp
@@ -207,33 +207,34 @@
        {
            // è¯·æ±‚配方参数
            //CEqWriteStep* pStep = new CEqWriteStep();
            //pStep->setName(STEP_EQ_RECIPE_PARAMETER_REQ);
            //pStep->setWriteSignalDev(0x967);
            //pStep->setDataDev(0x379b);
            //if (addStep(STEP_ID_RECIPE_PARAMETER_CMD_REPLY, pStep) != 0) {
            //    delete pStep;
            //}
            CEqWriteStep* pStep = new CEqWriteStep();
            pStep->setName(STEP_EQ_RECIPE_PARAMETER_REQ);
            pStep->setWriteSignalDev(0x967);
            pStep->setDataDev(0x24fb);
            if (addStep(STEP_ID_RECIPE_PARAMETER_CMD_REPLY, pStep) != 0) {
                delete pStep;
            }
        }
        {
            // recipe parameter report
            //CEqReadStep* pStep = new CEqReadStep(0x1aa54, 257 * 2,
            //    [&](void* pFrom, int code, const char* pszData, size_t size) -> int {
            //        if (code == ROK && pszData != nullptr && size > 0) {
            //            // æ­¤å¤„解释配方数据
            //            short ret = decodeRecipeParameterReport(pszData, size);
            //            pStep->setReturnCode(ret);
            //        }
            //        pStep->setReturnCode(MRLRC_OK);
            //        return -1;
            //    });
            //pStep->setName(STEP_EQ_RECIPE_PARAMETER);
            //pStep->setWriteSignalDev(0x94c);
            //pStep->setReturnDev(m_nIndex == 0 ? 0x126c : 0x1bbc);
            //if (addStep(STEP_ID_RECIPE_PARAMETER_REPORT, pStep) != 0) {
            //    delete pStep;
            //}
            CEqReadStep* pStep = new CEqReadStep(0x12a54, 257 * 2,
                [&](void* pFrom, int code, const char* pszData, size_t size) -> int {
                    CEqReadStep* pTmpStep = (CEqReadStep*)pFrom;
                    if (code == ROK && pszData != nullptr && size > 0) {
                        // æ­¤å¤„解释配方数据
                        short ret = decodeRecipeParameterReport(pszData, size);
                        pTmpStep->setReturnCode(ret);
                    }
                    pTmpStep->setReturnCode(MRLRC_OK);
                    return -1;
                });
            pStep->setName(STEP_EQ_RECIPE_PARAMETER);
            pStep->setWriteSignalDev(0x94c);
            pStep->setReturnDev(0x250c);
            if (addStep(STEP_ID_RECIPE_PARAMETER_REPORT, pStep) != 0) {
                delete pStep;
            }
        }
        // ä½¿ç”¨CEqReadStep替换CEqJobEventStep
@@ -422,4 +423,46 @@
        if (pGlass == nullptr) return false;
        return pGlass->isProcessed(m_nID, getSlotUnit(slot));
    }
    int CBakeCooling::parsingParams(const char* pszData, size_t size, std::vector<CParam>& params)
    {
        ASSERT(pszData);
        if (size < 250) return 0;
        int i = 0, v;
        // 1.A_腔烘烤时间
        v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8;
        params.push_back(CParam("A_腔烘烤时间", "", "", v * 0.01f));
        i += 2;
        // 2.A_腔冷却时间
        v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8;
        params.push_back(CParam("A_腔冷却时间", "", "", v * 0.01f));
        i += 2;
        // 3.B_腔烘烤时间
        v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8;
        params.push_back(CParam("B_腔烘烤时间", "", "", v * 0.01f));
        i += 2;
        // 4.BB_腔冷却时间
        v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8;
        params.push_back(CParam("B_腔冷却时间", "", "", v * 0.01f));
        i += 2;
        // 5.A_烘烤温度设定
        v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8;
        params.push_back(CParam("A_烘烤温度设定", "", "", v * 0.1f));
        i += 2;
        // 6.B_烘烤温度设定
        v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8;
        params.push_back(CParam("B_烘烤温度设定", "", "", v * 0.1f));
        i += 2;
        return (int)params.size();
    }
}
SourceCode/Bond/Servo/CBakeCooling.h
@@ -24,6 +24,7 @@
        virtual int getIndexerOperationModeBaseValue();
        virtual short getSlotUnit(short slotNo) { return slotNo % 2 == 1 ? 0 : 1; };
        virtual bool isSlotProcessed(int slot);
        virtual int parsingParams(const char* pszData, size_t size, std::vector<CParam>& parsms);
    };
}
SourceCode/Bond/Servo/CBonder.cpp
@@ -224,13 +224,14 @@
        {
            // recipe parameter report
            CEqReadStep* pStep = new CEqReadStep(m_nIndex == 0 ? 0xaa54 : 0xea54, 257 * 2,
                [&](void* pFrom, int code, const char* pszData, size_t size) -> int {
                [&, pStep](void* pFrom, int code, const char* pszData, size_t size) -> int {
                    CEqReadStep* pTmpStep = (CEqReadStep*)pFrom;
                    short ret = MRLRC_OK;
                    if (code == ROK && pszData != nullptr && size > 0) {
                        // æ­¤å¤„解释配方数据
                        short ret = decodeRecipeParameterReport(pszData, size);
                        pStep->setReturnCode(ret);
                        ret = decodeRecipeParameterReport(pszData, size);
                    }
                    pStep->setReturnCode(MRLRC_OK);
                    pTmpStep->setReturnCode(ret);
                    return -1;
                });
            pStep->setName(STEP_EQ_RECIPE_PARAMETER);
@@ -351,10 +352,10 @@
        {
            // FAC Data Report
            CEqReadStep* pStep = new CEqReadStep(0xA60E, 108 * 2,
            CEqReadStep* pStep = new CEqReadStep(m_nIndex == 0 ? 0xA60E : 0xE60E, 108 * 2,
                [&](void* pFrom, int code, const char* pszData, size_t size) -> int {
                    if (code == ROK && pszData != nullptr && size > 0) {
                        decodePanelDataReport((CStep*)pFrom, pszData, size);
                        decodeFacDataReport((CStep*)pFrom, pszData, size);
                    }
                    return -1;
                });
@@ -460,7 +461,7 @@
        return m_nIndex;
    }
    BOOL CBonder::hasBondClass()
    BOOL CBonder::hasBondGlass()
    {
        CGlass* pGlass = (CGlass*)m_slot[1].getContext();
        if (pGlass == nullptr) return FALSE;
@@ -468,7 +469,7 @@
        return pBuddy != nullptr;
    }
    BOOL CBonder::hasG2Class()
    BOOL CBonder::hasG2Glass()
    {
        CGlass* pGlass = (CGlass*)m_slot[0].getContext();
        return (pGlass != nullptr);
@@ -522,4 +523,123 @@
    {
        return m_nIndex == 0 ? 15000 : 20000;
    }
    int CBonder::parsingParams(const char* pszData, size_t size, std::vector<CParam>& params)
    {
        ASSERT(pszData);
        if (size < 250) return 0;
        int i = 0, v;
        // 1.校正对位延时
        v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8;
        params.push_back(CParam("校正对位延时", "", "", v * 0.01f));
        i += 2;
        // 2.保压时间
        v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8;
        params.push_back(CParam("保压时间", "", "", v * 0.01f));
        i += 2;
        // 3.腔体破真空延时
        v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8;
        params.push_back(CParam("腔体破真空延时", "", "", v * 0.01f));
        i += 2;
        // 4.腔体分子泵启动延时
        v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8;
        params.push_back(CParam("腔体分子泵启动延时", "", "", v * 0.1f));
        i += 2;
        // 5.腔体贴附抽真空延时
        v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8;
        params.push_back(CParam("腔体贴附抽真空延时", "", "", v * 0.1f));
        i += 2;
        // 6.加热等待延时
        v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8;
        params.push_back(CParam("加热等待延时", "", "", v * 0.1f));
        i += 2;
        // 7.气囊压力设定
        v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8 | (pszData[i + 2] & 0xff) << 16 | (pszData[i + 3] & 0xff) << 24;
        params.push_back(CParam("气囊压力设定", "", "", v * 0.001f));
        i += 4;
        // 8.气囊加压速率
        v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8 | (pszData[i + 2] & 0xff) << 16 | (pszData[i + 3] & 0xff) << 24;
        params.push_back(CParam("气囊加压速率", "", "", v * 0.001f));
        i += 4;
        // 9.气囊泄压速率
        v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8 | (pszData[i + 2] & 0xff) << 16 | (pszData[i + 3] & 0xff) << 24;
        params.push_back(CParam("气囊泄压速率", "", "", v * 0.001f));
        i += 4;
        // 10.贴附压力上限
        v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8 | (pszData[i + 2] & 0xff) << 16 | (pszData[i + 3] & 0xff) << 24;
        params.push_back(CParam("贴附压力上限", "", "", v * 0.1f));
        i += 4;
        // 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轴转矩速度设定", "", "", v * 0.001f));
        i += 4;
        // 12.上腔温度设定
        v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8;
        params.push_back(CParam("上腔温度设定", "", "", v * 0.1f));
        i += 2;
        // 13.下腔温度设定
        v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8;
        params.push_back(CParam("下腔温度设定", "", "", v * 0.1f));
        i += 2;
        // 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轴预贴合位速度", "", "", v * 0.001f));
        i += 4;
        // 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轴贴附位速度", "", "", v * 0.001f));
        i += 4;
        // 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上腔加热位间距", "", "", v * 0.001f));
        i += 4;
        // 17.上腔贴附位压入量
        v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8 | (pszData[i + 2] & 0xff) << 16 | (pszData[i + 3] & 0xff) << 24;
        params.push_back(CParam("上腔贴附位压入量", "", "", v * 0.001f));
        i += 4;
        // 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轴破真空距离", "", "", v * 0.001f));
        i += 4;
        // 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破真空距离", "", "", v * 0.001f));
        i += 4;
        // 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加热位间距", "", "", v * 0.001f));
        i += 4;
        // 21.腔体真空泵真空规设定值
        params.push_back(CParam("腔体真空泵真空规设定值", "", "", (double)toFloat(&pszData[i])));
        i += 4;
        // 22.腔体分子泵到达设定值
        params.push_back(CParam("腔体分子泵到达设定值", "", "", (double)toFloat(&pszData[i])));
        i += 4;
        return (int)params.size();
    }
}
SourceCode/Bond/Servo/CBonder.h
@@ -24,12 +24,13 @@
        virtual int onProcessData(CProcessData* pProcessData);
        virtual int onProcessStateChanged(PROCESS_STATE state);
        virtual int getIndexerOperationModeBaseValue();
        virtual int parsingParams(const char* pszData, size_t size, std::vector<CParam>& parsms);
    public:
        void setIndex(unsigned int index);
        unsigned int getIndex();
        BOOL hasBondClass();
        BOOL hasG2Class();
        BOOL hasBondGlass();
        BOOL hasG2Glass();
    private:
        unsigned int m_nIndex;
SourceCode/Bond/Servo/CEFEM.cpp
@@ -892,7 +892,7 @@
    {
        LOGI("<CEFEM>Robot status:%d, ARM1:%s, ARM2:%s",
            m_robotData.status,
            m_robotData.armState[1] ? _T("ON") : _T("OFF"),
            m_robotData.armState[2] ? _T("ON") : _T("OFF"));
            m_robotData.armState[0] ? _T("ON") : _T("OFF"),
            m_robotData.armState[1] ? _T("ON") : _T("OFF"));
    }
}
SourceCode/Bond/Servo/CEquipment.cpp
@@ -27,6 +27,7 @@
        m_pArm = nullptr;
        m_processState = PROCESS_STATE::Ready;
        m_blockReadBit = { 0 };
        m_nTestFlag = 0;
        InitializeCriticalSection(&m_criticalSection);
    }
@@ -495,6 +496,11 @@
        // ä¸»é…æ–¹ä¸ŠæŠ¥
        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);
        // CIM Mode
        CHECK_WRITE_STEP_SIGNAL(STEP_ID_CIMMODE_CHANGED_CMD_REPLY, pszData, size);
@@ -810,6 +816,16 @@
    CRecipeList* CEquipment::getRecipeList(int unitNo)
    {
        return m_recipesManager.getRecipeList(unitNo);
    }
    bool CEquipment::saveRecipeList(int unitNo, std::string& strFilepath)
    {
        return m_recipesManager.saveRecipeList(unitNo, strFilepath);
    }
    bool CEquipment::readRecipeList(int unitNo, std::string& strFilepath)
    {
        return m_recipesManager.readRecipeList(unitNo, strFilepath);
    }
    int CEquipment::recvIntent(CPin* pPin, CIntent* pIntent)
@@ -1188,28 +1204,39 @@
        return 0;
    }
    int CEquipment::recipeParameterRequest(short masterRecipeId, short localRecipeId, short unitNo)
    int CEquipment::recipeParameterRequest(short masterRecipeId, short localRecipeId, short unitNo, ONSYNCINGSTATECHANGED block)
    {
        SERVO::CEqWriteStep* pStep = (SERVO::CEqWriteStep*)getStepWithName(STEP_EQ_MASTER_RECIPE_LIST_REQ);
        LOGI("<CEquipment-%s>正在请求单元<%d>主配参数列表", m_strName.c_str(), unitNo);
        m_recipesManager.setOnSyncingStateChanged(block);
        if (m_recipesManager.syncing() != 0) {
            return -2;
        }
        SERVO::CEqWriteStep* pStep = (SERVO::CEqWriteStep*)getStepWithName(STEP_EQ_RECIPE_PARAMETER_REQ);
        if (pStep == nullptr) {
            return -1;
        }
        LOGI("<CEquipment-%s>正在请求单元<%d>主配方列表", m_strName.c_str(), unitNo);
        if (m_recipesManager.syncing() != 0) {
            return -2;
        }
        pStep->writeShort(unitNo, [&, unitNo](int code) -> int {
        char szBuffer[14 * 2] = {0};
        int index = 0;
        memcpy(&szBuffer[index], &masterRecipeId, sizeof(short));
        index += sizeof(short);
        memcpy(&szBuffer[index], &localRecipeId, sizeof(short));
        index += sizeof(short);
        memcpy(&szBuffer[index], &unitNo, sizeof(short));
        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();
                LOGI("<CEquipment-%s>请求单元<%d>主配方列表失败,code:%d", m_strName.c_str(), unitNo, code);
                LOGI("<CEquipment-%s>请求单元<%d>主配方参数列表失败,code:%d", m_strName.c_str(), unitNo, code);
            }
            return 0;
            });
        return 0;
    }
@@ -1328,24 +1355,32 @@
    CSlot* CEquipment::getProcessedSlot(MaterialsType putSlotType, BOOL bJobMode/* = FALSE*/)
    {
        for (int i = 0; i < SLOT_MAX; i++) {
            if (m_nTestFlag == 1) LOGI("getProcessedSlot 001");
            if (!m_slot[i].isEnable()) continue;
            if (m_nTestFlag == 1) LOGI("getProcessedSlot 002");
            if (m_slot[i].isLock()) continue;
            if (m_nTestFlag == 1) LOGI("getProcessedSlot 003");
            CGlass* pGlass = (CGlass*)m_slot[i].getContext();
            if (!isSlotProcessed(i)) continue;
            if (m_nTestFlag == 1) LOGI("getProcessedSlot 004");
            if (pGlass == nullptr) continue;
            if (m_nTestFlag == 1) LOGI("getProcessedSlot 005");
            if (!pGlass->isScheduledForProcessing()) continue;
            if (m_nTestFlag == 1) LOGI("getProcessedSlot 006");
            if (bJobMode && pGlass->getProcessJob() == nullptr) continue;
            if (m_nTestFlag == 1) LOGI("getProcessedSlot 007");
            if(pGlass->getInspResult(m_nID, 0) == InspResult::Fail) continue;
            int lsPath = m_slot[i].getLinkSignalPath();
            if(!m_bLinkSignalToUpstream[lsPath][SIGNAL_UPSTREAM_INLINE]
                || m_bLinkSignalToUpstream[lsPath][SIGNAL_UPSTREAM_TROUBLE]
                || !m_bLinkSignalToUpstream[lsPath][SIGNAL_INTERLOCK]
                || !m_bLinkSignalToUpstream[lsPath][SIGNAL_SEND_ABLE] ) continue;
            if (m_nTestFlag == 1) LOGI("getProcessedSlot 008");
            MaterialsType glassType = pGlass->getType();
            if (glassType == MaterialsType::G1 && putSlotType == MaterialsType::G2) continue;
            if (m_nTestFlag == 1) LOGI("getProcessedSlot 009");
            if (glassType == MaterialsType::G2 && putSlotType == MaterialsType::G1) continue;
            if (m_nTestFlag == 1) LOGI("getProcessedSlot 00a");
            return &m_slot[i];
        }
@@ -1443,6 +1478,13 @@
        if (m_slot[slotIndex].getContext() != nullptr) return FALSE;
        return TRUE;
    }
    BOOL CEquipment::slotHasGlass(int slotIndex/* = 0*/)
    {
        ASSERT(slotIndex < 8);
        CGlass* pGlass = (CGlass*)m_slot[slotIndex].getContext();
        return (pGlass != nullptr);
    }
    int CEquipment::removeGlass(int slotNo)
@@ -1717,7 +1759,7 @@
        std::string strSvTimeRecord, strSvData;
        CToolUnits::convertString(&pszData[index], 8 * 2, strSvTimeRecord);
        index += 128 * 2;
        CToolUnits::convertString(&pszData[index], 640 * 2, strSvData);
        CToolUnits::convertString(&pszData[index], 100 * 2, strSvData);
        index += 256 * 2;
@@ -2059,4 +2101,38 @@
        return InspResult::NotInspected;
    }
    float CEquipment::toFloat(const char* pszAddr)
    {
        BYTE szBuffer[4];
        szBuffer[0] = pszAddr[0];
        szBuffer[1] = pszAddr[1];
        szBuffer[2] = pszAddr[2];
        szBuffer[3] = pszAddr[3];
        float f = 0.0;
        memcpy(&f, szBuffer, 4);
        return f;
    }
    int CEquipment::parsingParams(const char* pszData, size_t size, std::string& strOut)
    {
        std::vector<CParam> params;
        int nRet = parsingParams(pszData, size, params);
        if (nRet <= 0) return nRet;
        char szBuffer[256];
        for (auto p : params) {
            if(!strOut.empty()) strOut.append(",");
            if (p.getValueType() == PVT_INT) {
                sprintf_s(szBuffer, 256, "%s:%d", p.getName().c_str(), p.getIntValue());
            }
            else if (p.getValueType() == PVT_DOUBLE) {
                sprintf_s(szBuffer, 256, "%s:%f", p.getName().c_str(), p.getDoubleValue());
            }
            strOut.append(szBuffer);
        }
        return 0;
    };
}
SourceCode/Bond/Servo/CEquipment.h
@@ -35,6 +35,7 @@
#include "CProcessData.h"
#include "CPortStatusReport.h"
#include "CSlot.h"
#include "CParam.h"
namespace SERVO {
@@ -122,6 +123,8 @@
        std::vector<CPin*>& CEquipment::getInputPins();
        std::vector<CPin*>& CEquipment::getOutputPins();
        CRecipeList* getRecipeList(int unitNo);
        bool saveRecipeList(int unitNo, std::string& strFilepath);
        bool readRecipeList(int unitNo, std::string& strFilepath);
        virtual int recvIntent(CPin* pPin, CIntent* pIntent);
        virtual int fetchedOutJob(int port, CJobDataB* pJobDataB);
        virtual int storedJob(int port, CJobDataB* pJobDataB, short putSlot);
@@ -165,7 +168,11 @@
        // masterRecipeId: ä¸»é…æ–¹id
        // localRecipeId: æœ¬åœ°é…æ–¹id
        // unitNo: 0:local; Others:unit No
        int recipeParameterRequest(short masterRecipeId, short localRecipeId, short unitNo);
        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);
        // èŽ·å–æŒ‡å®šçš„Slot
        CSlot* getSlot(int index);
@@ -202,6 +209,7 @@
        // æ˜¯å¦æœ‰çŽ»ç’ƒ
        BOOL hasGlass();
        BOOL slotHasGlass(int slotIndex = 0);
        // æŒ‡å®šæ§½ä½æ˜¯å¦å¯ä»¥æ”¾ç½®çŽ»ç’ƒ
        BOOL canPlaceGlassInSlot(const short slotIndex);
@@ -253,6 +261,7 @@
        int decodeJobProcessEndReport(CStep* pStep, const char* pszData, size_t size);
        BOOL compareJobData(CJobDataB* pJobDataB, CJobDataS* pJobDataS);
        void setProcessState(PROCESS_STATE state);
        float toFloat(const char* pszAddr);
    protected:
        BOOL m_bEnable;
@@ -290,6 +299,9 @@
    private:
        CEquipment* m_pArm;
    public:
        int m_nTestFlag;
    };
}
SourceCode/Bond/Servo/CEquipmentPage2.cpp
@@ -180,7 +180,17 @@
            SERVO::CGlass* pGlass = (SERVO::CGlass*)pSlot->getContext();
            if (pGlass != nullptr) {
                m_listCtrl.SetItemText(index, 3, pGlass->getID().c_str());
                CString strText;
                if (pGlass->getType() == SERVO::MaterialsType::G1) {
                    strText.Format(_T("(G1)%s"), pGlass->getID().c_str());
                }
                else if (pGlass->getType() == SERVO::MaterialsType::G2) {
                    strText.Format(_T("(G2)%s"), pGlass->getID().c_str());
                }
                else {
                    strText.Format(_T("(%s"), pGlass->getID().c_str());
                }
                m_listCtrl.SetItemText(index, 3, strText);
                SERVO::CGlass* pBuddy = pGlass->getBuddy();
                if (pBuddy != nullptr) {
                    m_listCtrl.SetItemText(index, 4, pBuddy->getID().c_str());
SourceCode/Bond/Servo/CJobDataS.cpp
@@ -457,7 +457,7 @@
    int CJobDataS::serialize(char* pszBuffer, int nBufferSize)
    {
        if (nBufferSize < 256 * 2) return -1;
        if (nBufferSize < JOBDATAS_SIZE) return -1;
        int index = 0;
        memcpy(&pszBuffer[index], &m_nCassetteSequenceNo, sizeof(short));
@@ -558,7 +558,7 @@
        memcpy(&pszBuffer[index], &m_nProductJudge, sizeof(short));
        index += sizeof(short);
        return 256 * 2;
        return JOBDATAS_SIZE;
    }
    int CJobDataS::unserialize(const char* pszBuffer, int nBufferSize)
SourceCode/Bond/Servo/CLoadPort.cpp
@@ -363,14 +363,15 @@
        // æ¨¡æ‹Ÿæµ‹è¯•
        /*
        if (m_nIndex == 0) {
            static int ii = 0;
            ii++;
            if (ii == 50) {
                char szBuffer[64] = {0};
                CStep* pStep = getStepWithName(STEP_EQ_PORT1_INUSE);
                CStep* pStep = getStepWithName(STEP_EQ_PORT1_BLOCKED);
                CPortStatusReport portStatusReport;
                portStatusReport.setPortStatus(PORT_INUSE);
                portStatusReport.setPortStatus(PORT_BLOCKED);
                portStatusReport.setJobExistenceSlot(0xf);
                portStatusReport.setCassetteId("CID1001");
                int nRet = portStatusReport.serialize(szBuffer, 64);
@@ -382,15 +383,16 @@
            ii++;
            if (ii == 55) {
                char szBuffer[64] = { 0 };
                CStep* pStep = getStepWithName(STEP_EQ_PORT2_INUSE);
                CStep* pStep = getStepWithName(STEP_EQ_PORT2_BLOCKED);
                CPortStatusReport portStatusReport;
                portStatusReport.setPortStatus(PORT_INUSE);
                portStatusReport.setPortStatus(PORT_BLOCKED);
                portStatusReport.setJobExistenceSlot(0xff );
                portStatusReport.setCassetteId("CID1004");
                int nRet = portStatusReport.serialize(szBuffer, 64);
                decodePortStatusReport(pStep, szBuffer, 64);
            }
        }
        */
    }
    void CLoadPort::serialize(CArchive& ar)
SourceCode/Bond/Servo/CMaster.cpp
@@ -63,6 +63,7 @@
        m_nContinuousTransferCount = 0;
        m_nContinuousTransferStep = CTStep_Unknow;
        m_pControlJob = nullptr;
        m_nTestFlag = 0;
        InitializeCriticalSection(&m_criticalSection);
    }
@@ -505,13 +506,11 @@
                }
                
                // æ£€æŸ¥çœ‹æ˜¯å¦éƒ½å·²ç»åˆ‡æ¢åˆ°START状态
                /*
                if (!bIomcOk[6]) {
                    unlock();
                    setState(MASTERSTATE::MSERROR);
                    continue;
                }
                */
                unlock();
                if(m_bContinuousTransfer)
@@ -596,37 +595,62 @@
                }
                // æ­¤å¤„检测优先类型和次要类型(G1或G2)
                // å¦‚果其中一Bonder有单个玻璃,优先取它的配对类型,否则无所谓了
                primaryType = MaterialsType::G1;
                secondaryType = MaterialsType::G2;
                if ((!pBonder1->canPlaceGlassInSlot(0) && !pBonder1->canPlaceGlassInSlot(1))
                    && (!pBonder2->canPlaceGlassInSlot(0) && !pBonder2->canPlaceGlassInSlot(1))) {
                    // å¦‚æžœG1和G2都满了,那就看Aligner, å¦‚æžœAligner有玻璃为G1, åˆ™å–G2
                    CGlass* pGlass = pAligner->getGlassFromSlot(1);
                    if (pGlass != nullptr && pGlass->getType() == MaterialsType::G1) {
                        primaryType = MaterialsType::G2;
                        secondaryType = MaterialsType::G1;
                // Bonder1、Bonder2、Fliper、VacuumBake、Aligner,统计G2和G1的数量, é…å¯¹ç»„æ•°, å¤šå‡ºçš„类型
                int nG2Count = 0, nG1Count = 0, nGlassGroup, nExtraType;
                if (pBonder1->slotHasGlass(0)) {
                    nG2Count++;
                    }
                if (pBonder1->slotHasGlass(1)) {
                    nG1Count++;
                }
                else if ((pBonder1->canPlaceGlassInSlot(0) && !pBonder1->canPlaceGlassInSlot(1))
                    || (pBonder2->canPlaceGlassInSlot(0) && !pBonder2->canPlaceGlassInSlot(1))) {
                    primaryType = MaterialsType::G2;
                    secondaryType = MaterialsType::G1;
                if (pBonder2->slotHasGlass(0)) {
                    nG2Count++;
                }
                if (pBonder2->slotHasGlass(1)) {
                    nG1Count++;
                }
                if (pFliper->slotHasGlass(0)) {
                    nG2Count++;
                }
                if (pVacuumBake->slotHasGlass(0)) {
                    nG1Count++;
                }
                if (pVacuumBake->slotHasGlass(1)) {
                    nG1Count++;
                }
                CGlass* pTempGlass = pAligner->getGlassFromSlot(0);
                if (pTempGlass != nullptr) {
                    MaterialsType type = pTempGlass->getType();
                    if(type == MaterialsType::G1)
                        nG1Count++;
                    else if (type == MaterialsType::G2)
                        nG2Count++;
                }
                nGlassGroup = min(nG1Count, nG2Count);
                if (nG1Count == nG2Count) {
                    nExtraType = 0;
                }
                else if (nG1Count > nG2Count) {
                    nExtraType = 1;
                }
                else {
                    nExtraType = 2;
                }
                secondaryType = MaterialsType::G0;
                // Measurement -> LoadPort
                if (rmd.armState[0] || rmd.armState[1]) {
                    LOGI("Arm1 %s, Arm2 %s.", rmd.armState[0] ? _T("不可用") : _T("可用"),
                        rmd.armState[1] ? _T("不可用") : _T("可用"));
                }
                for (int s = 0; s < 4; s++) {
                    PortType pt = pLoadPorts[s]->getPortType();
                    if (!rmd.armState[0] && pLoadPorts[s]->isEnable()
                        && (pt == PortType::Unloading || pt == PortType::Both)
                        && pLoadPorts[s]->getPortStatus() == PORT_INUSE) {
                        m_pActiveRobotTask = createTransferTask(pMeasurement, pLoadPorts[s], primaryType, secondaryType);
                        m_pActiveRobotTask = createTransferTask(pMeasurement, pLoadPorts[s], MaterialsType::G1, secondaryType);
                        if (m_pActiveRobotTask != nullptr) {
                            goto PORT_PUT;
                        }
@@ -673,25 +697,30 @@
                // Fliper(G2) -> Bonder
                auto pSrcSlot = pVacuumBake->getProcessedSlot(primaryType);
                if (pSrcSlot != nullptr && !rmd.armState[1] && !pBonder1->hasBondClass()) {
                    m_pActiveRobotTask = createTransferTask(pFliper, pBonder1, primaryType, secondaryType, 2);
                //m_nTestFlag = 1;
                //pVacuumBake->m_nTestFlag = 1;
                auto pSrcSlot = pVacuumBake->getProcessedSlot(MaterialsType::G1);
                //LOGI("<Master>pSrcSlot = %x", pSrcSlot,);
                if (pSrcSlot != nullptr && !rmd.armState[1]
                    && pBonder1->canPlaceGlassInSlot(0)) {
                    m_pActiveRobotTask = createTransferTask(pFliper, pBonder1, MaterialsType::G2, MaterialsType::G0, 2);
                    CHECK_RUN_ACTIVE_ROBOT_TASK(m_pActiveRobotTask);
                }
                if (pSrcSlot != nullptr && !rmd.armState[1] && !pBonder2->hasBondClass()) {
                    m_pActiveRobotTask = createTransferTask(pFliper, pBonder2, primaryType, secondaryType, 2);
                if (pSrcSlot != nullptr && !rmd.armState[1]
                    && pBonder2->canPlaceGlassInSlot(0)) {
                    m_pActiveRobotTask = createTransferTask(pFliper, pBonder2, MaterialsType::G2, MaterialsType::G0, 2);
                    CHECK_RUN_ACTIVE_ROBOT_TASK(m_pActiveRobotTask);
                }
                //m_nTestFlag = 0
                    ;
                // VacuumBake(G1) -> Bonder
                if (!rmd.armState[0] && !pBonder1->hasBondClass()) {
                    m_pActiveRobotTask = createTransferTask(pVacuumBake, pBonder1, primaryType, secondaryType);
                if (!rmd.armState[0] && pBonder1->slotHasGlass(0) && !pBonder1->slotHasGlass(1)) {
                    m_pActiveRobotTask = createTransferTask(pVacuumBake, pBonder1, MaterialsType::G1, MaterialsType::G0);
                    CHECK_RUN_ACTIVE_ROBOT_TASK(m_pActiveRobotTask);
                }
                if (!rmd.armState[0] && !pBonder2->hasBondClass()) {
                    m_pActiveRobotTask = createTransferTask(pVacuumBake, pBonder2, primaryType, secondaryType);
                if (!rmd.armState[0] && pBonder2->slotHasGlass(0) && !pBonder2->slotHasGlass(1)) {
                    m_pActiveRobotTask = createTransferTask(pVacuumBake, pBonder2, MaterialsType::G1, MaterialsType::G0);
                    CHECK_RUN_ACTIVE_ROBOT_TASK(m_pActiveRobotTask);
                }
@@ -699,13 +728,16 @@
                // Aligner -> Fliper(G2)
                // Aligner -> VacuumBake(G1)
                if (!rmd.armState[1]) {
                    m_pActiveRobotTask = createTransferTask(pAligner, pFliper, primaryType, secondaryType);
                    m_pActiveRobotTask = createTransferTask(pAligner, pFliper, MaterialsType::G2, secondaryType);
                    CHECK_RUN_ACTIVE_ROBOT_TASK(m_pActiveRobotTask);
                }
                if (!rmd.armState[0]) {
                    m_pActiveRobotTask = createTransferTask(pAligner, pVacuumBake, primaryType, secondaryType);
                    // m_nTestFlag = 1;
                    if (m_nTestFlag == 1) LOGI("createTransferTask 004df %d, %d", MaterialsType::G1, secondaryType);
                    m_pActiveRobotTask = createTransferTask(pAligner, pVacuumBake, MaterialsType::G1, secondaryType);
                    CHECK_RUN_ACTIVE_ROBOT_TASK(m_pActiveRobotTask);
                    m_nTestFlag = 0;
                }
@@ -717,6 +749,17 @@
                // LoadPort -> Aligner
                if (nGlassGroup >= 2) {
                    unlock();
                    continue;
                }
                if(nExtraType == 0)
                    primaryType = MaterialsType::G2;
                else {
                    primaryType = MaterialsType::G1;
                }
                for (int s = 0; s < 4; s++) {
                    PortType pt = pLoadPorts[s]->getPortType();
                    if (!rmd.armState[0] && pLoadPorts[s]->isEnable()
@@ -761,6 +804,10 @@
                if (m_pControlJob->state() == CJState::Queued) {
                    LOGI("<Master>ControlJob已经启动");
                    m_pControlJob->start();
                    if (m_listener.onCjStart != nullptr) {
                        m_listener.onCjStart(this, m_pControlJob);
                    }
                }
                if (m_pControlJob->state() == CJState::Paused) {
                    LOGI("<Master>ControlJob已经恢复运行");
@@ -889,23 +936,23 @@
                // Fliper(G2) -> Bonder
                auto pSrcSlot = pVacuumBake->getProcessedSlot(primaryType);
                if (pSrcSlot != nullptr && !rmd.armState[1] && !pBonder1->hasBondClass()) {
                if (pSrcSlot != nullptr && !rmd.armState[1] && !pBonder1->hasBondGlass()) {
                    m_pActiveRobotTask = createTransferTask(pFliper, pBonder1, primaryType, secondaryType, 2);
                    CHECK_RUN_ACTIVE_ROBOT_TASK(m_pActiveRobotTask);
                }
                if (pSrcSlot != nullptr && !rmd.armState[1] && !pBonder2->hasBondClass()) {
                if (pSrcSlot != nullptr && !rmd.armState[1] && !pBonder2->hasBondGlass()) {
                    m_pActiveRobotTask = createTransferTask(pFliper, pBonder2, primaryType, secondaryType, 2);
                    CHECK_RUN_ACTIVE_ROBOT_TASK(m_pActiveRobotTask);
                }
                // VacuumBake(G1) -> Bonder
                if (!rmd.armState[0] && !pBonder1->hasBondClass()) {
                if (!rmd.armState[0] && !pBonder1->hasBondGlass()) {
                    m_pActiveRobotTask = createTransferTask(pVacuumBake, pBonder1, primaryType, secondaryType);
                    CHECK_RUN_ACTIVE_ROBOT_TASK(m_pActiveRobotTask);
                }
                if (!rmd.armState[0] && !pBonder2->hasBondClass()) {
                if (!rmd.armState[0] && !pBonder2->hasBondGlass()) {
                    m_pActiveRobotTask = createTransferTask(pVacuumBake, pBonder2, primaryType, secondaryType);
                    CHECK_RUN_ACTIVE_ROBOT_TASK(m_pActiveRobotTask);
                }
@@ -940,6 +987,12 @@
                        m_pActiveRobotTask = createTransferTask(pLoadPorts[s], pAligner, primaryType, secondaryType, m_bJobMode);
                        if (m_pActiveRobotTask != nullptr) {
                            CGlass* pGlass = (CGlass*)m_pActiveRobotTask->getContext();
                            if (pGlass->getBuddy() != nullptr) {
                                delete m_pActiveRobotTask;
                                m_pActiveRobotTask = nullptr;
                                continue;
                            }
                            pEFEM->setContext(pGlass);
                            pGlass->start();
                            bool bMoved = glassFromQueueToInPorcess(pGlass);
@@ -950,6 +1003,11 @@
                            else {
                                LOGE("<Master>Glass(%s)从等待列队到工艺列队转移失败.",
                                    pGlass->getID().c_str());
                            }
                            // è¿™é‡Œä¸ŠæŠ¥Panel Start事件
                            if (m_listener.onPanelStart != nullptr) {
                                m_listener.onPanelStart(this, pGlass);
                            }
                            goto BATCH_PORT_GET;
@@ -1090,7 +1148,7 @@
                
                // Bonder1 -> Bonder2
                if ((m_nContinuousTransferStep == CTStep_Unknow || m_nContinuousTransferStep == CTStep_Fliper_Bonder1)
                    && !rmd.armState[0] && !pBonder2->hasBondClass()) {
                    && !rmd.armState[0] && !pBonder2->hasBondGlass()) {
                    m_pActiveRobotTask = createTransferTask_continuous_transfer(pBonder1,
                        1, pBonder2, 1);
                    if (m_pActiveRobotTask != nullptr) {
@@ -1102,7 +1160,7 @@
                // Fliper(G2) -> Bonder1
                if ((m_nContinuousTransferStep == CTStep_Unknow || m_nContinuousTransferStep == CTStep_Aligner_Fliper)
                    &&!rmd.armState[0] && !pBonder1->hasBondClass()) {
                    &&!rmd.armState[0] && !pBonder1->hasBondGlass()) {
                    m_pActiveRobotTask = createTransferTask_continuous_transfer(pFliper,
                        0, pBonder1, 1);
                    if (m_pActiveRobotTask != nullptr) {
@@ -1310,7 +1368,7 @@
                    if (pGlass == nullptr) {
                        bOk = TRUE;
                        slot = m_pActiveRobotTask->getTarSlot();
                        LOGI("<CMaster>onPreFethedOutJob, å·²æ ¡éªŒæ•°æ®ä¸€è‡´æ€§.");
                        LOGI("<CMaster>onPreStoredJob, å·²æ ¡éªŒæ•°æ®ä¸€è‡´æ€§.");
                    }
                }
@@ -1321,7 +1379,7 @@
                    if (pGlass == nullptr && m_pActiveRobotTask->getSrcSlot() == port) {
                        bOk = TRUE;
                        slot = m_pActiveRobotTask->getSrcSlot();
                        LOGI("<CMaster>onPreFethedOutJob, å·²æ ¡éªŒæ•°æ®ä¸€è‡´æ€§.");
                        LOGI("<CMaster>onPreStoredJob, å·²æ ¡éªŒæ•°æ®ä¸€è‡´æ€§.");
                    }
                }
            }
@@ -1384,6 +1442,7 @@
                    if (m_pActiveRobotTask->getSrcPosition() == EQ_ID_MEASUREMENT) {
                        CGlass* pGlass = (CGlass*)m_pActiveRobotTask->getContext();
                        pGlass->complete();
                        this->saveState();
                        bool bMoved = glassFromInPorcessToComplete(pGlass);
                        if (bMoved) {
                            LOGI("<Master>Glass(%s)从工艺列队到完成列队转移成功.",
@@ -1393,14 +1452,29 @@
                            LOGE("<Master>Glass(%s)从工艺列队到完成列队转移失败.",
                                pGlass->getID().c_str());
                        }
                        if (m_listener.onPanelEnd != nullptr) {
                            m_listener.onPanelEnd(this, pGlass);
                        }
                        // æ£€æŸ¥PJ是否已经完成
                        CProcessJob* pJob = getGlassProcessJob((CGlass*)m_pActiveRobotTask->getContext());
                        if (pJob != nullptr && checkAndUpdatePjComplete(pJob)) {
                            this->saveState();
                            LOGE("<Master>ProcessJob(%s)完成.",
                                pJob->id().c_str());
                            if (m_listener.onPjEnd != nullptr) {
                                m_listener.onPjEnd(this, pJob);
                            }
                            // æ£€æŸ¥CJ是否已经完成
                            ASSERT(m_pControlJob);
                            if (checkAndUpdateCjComplete(m_pControlJob)) {
                                this->saveState();
                                LOGE("<Master>ControlJob(%s)完成.",
                                    m_pControlJob->id().c_str());
                                if (m_listener.onCjEnd != nullptr) {
                                    m_listener.onCjEnd(this, pJob);
                                }
                            }
                        }
                    }
@@ -1711,7 +1785,6 @@
        // æ¨¡æ‹Ÿæµ‹è¯•
        /*
        static int aaa = 0;
        aaa++;
        if (aaa % 30 == 0) {
@@ -1719,6 +1792,12 @@
                CGlass* pGlass = m_queueGlasses.front();
                pGlass->start();
                glassFromQueueToInPorcess(pGlass);
                this->saveState();
                // è¿™é‡Œä¸ŠæŠ¥Panel Start事件
                if (m_listener.onPanelStart != nullptr) {
                    m_listener.onPanelStart(this, pGlass);
                }
            }
        }
@@ -1727,19 +1806,37 @@
                CGlass* pGlass = m_inProcesGlasses.front();
                pGlass->complete();
                glassFromInPorcessToComplete(pGlass);
                this->saveState();
                // è¿™é‡Œä¸ŠæŠ¥Panel End事件
                if (m_listener.onPanelEnd != nullptr) {
                    m_listener.onPanelEnd(this, pGlass);
                }
                CProcessJob* pJob = getGlassProcessJob(pGlass);
                if (pJob != nullptr && checkAndUpdatePjComplete(pJob)) {
                    processJobFromInPorcessToComplete(pJob);
                    this->saveState();
                    LOGE("<Master>ProcessJob(%s)完成.",
                        pJob->id().c_str());
                    if (m_listener.onPjEnd != nullptr) {
                        m_listener.onPjEnd(this, pJob);
                    }
                    // æ£€æŸ¥CJ是否已经完成
                    ASSERT(m_pControlJob);
                    if (checkAndUpdateCjComplete(m_pControlJob)) {
                        this->saveState();
                        LOGE("<Master>ControlJob(%s)完成.",
                            m_pControlJob->id().c_str());
                        if (m_listener.onCjEnd != nullptr) {
                            m_listener.onCjEnd(this, pJob);
                }
            }
        }
        */
            }
        }
    }
    void CMaster::connectEquipments()
@@ -1909,16 +2006,17 @@
        if (!pSrcEq->IsEnabled()) { 
            return nullptr;
        }
        CRobotTask* pTask = nullptr;
        CSlot* pSrcSlot, * pTarSlot;
        pSrcEq->m_nTestFlag = m_nTestFlag;
        pTarSlot = pTarEq->getAvailableSlotForGlass(primaryType);
        pSrcSlot = pSrcEq->getProcessedSlot(primaryType, bJobMode);
        if (pSrcSlot == nullptr || nullptr == pTarSlot) {
        if (m_nTestFlag == 1) LOGI("createTransferTask 003 %x, %x", pTarSlot, pSrcSlot);
        if (pSrcSlot == nullptr || nullptr == pTarSlot && secondaryType != SERVO::MaterialsType::G0) {
            pTarSlot = pTarEq->getAvailableSlotForGlass(secondaryType);
            pSrcSlot = pSrcEq->getProcessedSlot(secondaryType, bJobMode);
        }
        if (m_nTestFlag == 1) LOGI("createTransferTask 004 %x, %x", pTarSlot, pSrcSlot);
        if (pSrcSlot != nullptr && nullptr != pTarSlot) {
            pTask = new CRobotTask();
@@ -2401,7 +2499,9 @@
            m_pControlJob = new CControlJob();
            if (!CControlJob::deserialize(ifs, *m_pControlJob)) return false;
        }
        else {
            return false;
        }
        // è¯»å– ProcessJob åˆ—表
        uint32_t count = 0;
@@ -2438,8 +2538,8 @@
        for (const auto pj : pjs) {
            if (pj->state() == PJState::Queued) {
                pj->start();
            }
            return pj;
            }
        }
@@ -2513,6 +2613,17 @@
        return false;
    }
    bool CMaster::processJobFromInPorcessToComplete(CProcessJob* pProcessJob)
    {
        auto it = std::find(m_inProcesJobs.begin(), m_inProcesJobs.end(), pProcessJob);
        if (it != m_inProcesJobs.end()) {
            m_completeProcessJobs.push_back(*it);
            m_inProcesJobs.erase(it);
            return true;
        }
        return false;
    }
    bool CMaster::checkAndUpdatePjComplete(CProcessJob* pJob)
    {
        ASSERT(pJob);
@@ -2521,10 +2632,26 @@
        for (auto c : pJob->carriers()) {
            for (auto g : c.contexts) {
                CGlass* pGlass = (CGlass*)g;
                if (pGlass->state() != GlsState::Aborted
                    && pGlass->state() != GlsState::Completed
                    && pGlass->state() != GlsState::Failed) return false;
                auto state = ((CGlass*)g)->state();
                if (state != GlsState::Aborted && state != GlsState::Completed
                    && state != GlsState::Failed) return false;
            }
        }
        return pJob->complete();
    }
    bool CMaster::checkAndUpdateCjComplete(CControlJob* pJob)
    {
        ASSERT(pJob);
        auto state = pJob->state();
        if (state != CJState::Executing && state != CJState::Paused) return false;
        for (auto pj : pJob->getPjs()) {
            auto state = pj->state();
            if (state != PJState::Aborted && state != PJState::Completed
                && state != PJState::Failed) {
                return false;
            }
        }
SourceCode/Bond/Servo/CMaster.h
@@ -65,8 +65,12 @@
        ONROBOTTASKEVENT        onRobotTaskEvent;
        ONLOADPORTSTATUSCHANGED    onLoadPortStatusChanged;
        ONCTROUNDEND            onCTRoundEnd;
        ONPJSTART               onCjStart;
        ONPJSTART               onCjEnd;
        ONPJSTART               onPjStart;
        ONPJSTART               onPjEnd;
        ONPJSTART               onPanelStart;
        ONPJSTART               onPanelEnd;
    } MasterListener;
    class CMaster : public IResourceView
@@ -167,7 +171,9 @@
        bool addGlassToQueue(CGlass* pGlass);
        bool glassFromQueueToInPorcess(CGlass* pGlass);
        bool glassFromInPorcessToComplete(CGlass* pGlass);
        bool processJobFromInPorcessToComplete(CProcessJob* pProcessJob);
        bool checkAndUpdatePjComplete(CProcessJob* pJob);
        bool checkAndUpdateCjComplete(CControlJob* pJob);
        CProcessJob* getGlassProcessJob(CGlass* pGlass);
@@ -217,6 +223,7 @@
        // æ–°å¢žå·²ç»å¼€å§‹å¤„理的ProcessJob列表
        std::vector<CProcessJob*> m_inProcesJobs;
        std::vector<CProcessJob*> m_completeProcessJobs;
        std::vector<CGlass*> m_queueGlasses;
        std::vector<CGlass*> m_inProcesGlasses;
        std::vector<CGlass*> m_completeGlasses;
@@ -227,6 +234,8 @@
        SERVO::CControlJob* m_pControlJob;
        std::vector<SERVO::CProcessJob*> m_processJobs;
        std::string m_strStatePath;
        int m_nTestFlag;
    };
}
SourceCode/Bond/Servo/CMeasurement.cpp
@@ -207,33 +207,34 @@
        {
            // è¯·æ±‚配方参数
            //CEqWriteStep* pStep = new CEqWriteStep();
            //pStep->setName(STEP_EQ_RECIPE_PARAMETER_REQ);
            //pStep->setWriteSignalDev(0xf67);
            //pStep->setDataDev(0x379b);
            //if (addStep(STEP_ID_RECIPE_PARAMETER_CMD_REPLY, pStep) != 0) {
            //    delete pStep;
            //}
            CEqWriteStep* pStep = new CEqWriteStep();
            pStep->setName(STEP_EQ_RECIPE_PARAMETER_REQ);
            pStep->setWriteSignalDev(0xf67);
            pStep->setDataDev(0x379b);
            if (addStep(STEP_ID_RECIPE_PARAMETER_CMD_REPLY, pStep) != 0) {
                delete pStep;
            }
        }
        {
            // recipe parameter report
            //CEqReadStep* pStep = new CEqReadStep(0x1aa54, 257 * 2,
            //    [&](void* pFrom, int code, const char* pszData, size_t size) -> int {
            //        if (code == ROK && pszData != nullptr && size > 0) {
            //            // æ­¤å¤„解释配方数据
            //            short ret = decodeRecipeParameterReport(pszData, size);
            //            pStep->setReturnCode(ret);
            //        }
            //        pStep->setReturnCode(MRLRC_OK);
            //        return -1;
            //    });
            //pStep->setName(STEP_EQ_RECIPE_PARAMETER);
            //pStep->setWriteSignalDev(0xf4c);
            //pStep->setReturnDev(m_nIndex == 0 ? 0x126c : 0x1bbc);
            //if (addStep(STEP_ID_RECIPE_PARAMETER_REPORT, pStep) != 0) {
            //    delete pStep;
            //}
            CEqReadStep* pStep = new CEqReadStep(0x1aa54, 257 * 2,
                [&](void* pFrom, int code, const char* pszData, size_t size) -> int {
                    CEqReadStep* pTmpStep = (CEqReadStep*)pFrom;
                    if (code == ROK && pszData != nullptr && size > 0) {
                        // æ­¤å¤„解释配方数据
                        short ret = decodeRecipeParameterReport(pszData, size);
                        pTmpStep->setReturnCode(ret);
                    }
                    pTmpStep->setReturnCode(MRLRC_OK);
                    return -1;
                });
            pStep->setName(STEP_EQ_RECIPE_PARAMETER);
            pStep->setWriteSignalDev(0xf4c);
            pStep->setReturnDev(0x37ac);
            if (addStep(STEP_ID_RECIPE_PARAMETER_REPORT, pStep) != 0) {
                delete pStep;
            }
        }
        // ä½¿ç”¨CEqReadStep替换CEqJobEventStep
@@ -416,4 +417,24 @@
    {
        return 35000;
    }
    int CMeasurement::parsingParams(const char* pszData, size_t size, std::vector<CParam>& params)
    {
        ASSERT(pszData);
        if (size < 250) return 0;
        int i = 0, v;
        // 1.检测功能启用/禁用
        v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8;
        params.push_back(CParam("检测功能启用/禁用", "", "", v));
        i += 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("检测速度", "", "", v * 0.001));
        i += 4;
        return (int)params.size();
    }
}
SourceCode/Bond/Servo/CMeasurement.h
@@ -22,6 +22,7 @@
        virtual void getAttributeVector(CAttributeVector& attrubutes);
        virtual int recvIntent(CPin* pPin, CIntent* pIntent);
        virtual int getIndexerOperationModeBaseValue();
        virtual int parsingParams(const char* pszData, size_t size, std::vector<CParam>& parsms);
    };
}
SourceCode/Bond/Servo/CParam.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,107 @@
#include "stdafx.h"
#include "CParam.h"
CParam::CParam()
{
    m_nValueType = PVT_INT;
    m_nValue = 0;
    m_fValue = 0.0;
}
CParam::CParam(const char* pszName, const char* pszId, const char* pszUnit, int value)
{
    m_nValueType = PVT_INT;
    m_nValue = value;
    m_fValue = 0.0;
    m_strId = pszId;
    m_strName = pszName;
    m_strUnit = pszUnit;
}
CParam::CParam(const char* pszName, const char* pszId, const char* pszUnit, double value)
{
    m_nValueType = PVT_DOUBLE;
    m_nValue = 0;
    m_fValue = value;
    m_strId = pszId;
    m_strName = pszName;
    m_strUnit = pszUnit;
}
CParam::~CParam()
{
}
std::string& CParam::getName()
{
    return m_strName;
}
std::string& CParam::getId()
{
    return m_strId;
}
std::string& CParam::getUnit()
{
    return m_strUnit;
}
int CParam::getValueType()
{
    return m_nValueType;
}
int CParam::getIntValue()
{
    return m_nValue;
}
void CParam::setIntValue(int value)
{
    m_nValue = value;
}
double CParam::getDoubleValue()
{
    return m_fValue;
}
void CParam::setDoubleValue(double value)
{
    m_fValue = value;
}
void CParam::Serialize(CArchive& ar)
{
    if (ar.IsStoring())
    {
        WriteString(ar, m_strName);
        WriteString(ar, m_strUnit);
        ar << m_nValueType;
        ar << m_nValue;
        ar << m_fValue;
    }
    else
    {
        ReadString(ar, m_strName);
        ReadString(ar, m_strUnit);
        ar >> m_nValueType;
        ar >> m_nValue;
        ar >> m_fValue;
    }
}
void CParam::ReadString(CArchive& ar, std::string& string)
{
    CString strTemp;
    ar >> strTemp;
    string = (LPTSTR)(LPCTSTR)strTemp;
}
void CParam::WriteString(CArchive& ar, std::string& string)
{
    CString strTemp = string.c_str();
    ar << strTemp;
}
SourceCode/Bond/Servo/CParam.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,38 @@
#pragma once
#include <string>
#define PVT_INT        0
#define PVT_DOUBLE    1
class CParam
{
public:
    CParam();
    CParam(const char* pszName, const char* pszId, const char* pszUnit, int value);
    CParam(const char* pszName, const char* pszId, const char* pszUnit, double value);
    ~CParam();
public:
    std::string& getId();
    std::string& getName();
    std::string& getUnit();
    int getValueType();
    int getIntValue();
    void setIntValue(int value);
    double getDoubleValue();
    void setDoubleValue(double value);
    void Serialize(CArchive& ar);
private:
    void ReadString(CArchive& ar, std::string& string);
    void WriteString(CArchive& ar, std::string& string);
private:
    int m_nValueType;
    std::string m_strId;
    std::string m_strName;
    std::string m_strUnit;
    int m_nValue;
    double m_fValue;
};
SourceCode/Bond/Servo/CRecipeList.cpp
@@ -2,6 +2,7 @@
#include "CRecipeList.h"
#include "Common.h"
#include "ToolUnits.h"
#include <fstream>
namespace SERVO {
@@ -53,6 +54,8 @@
        }
        if (m_nCurrentGroupCount == m_nToatlGroupCount) {
            m_nToatlGroupCount = 0;
            m_nCurrentGroupCount = 0;
            return MRLRC_CURRENT_RECIPE_COMPLETE;
        }
@@ -77,10 +80,136 @@
        return m_ids;
    }
    std::unordered_map<short, std::vector<uint8_t>>& CRecipeList::getParamsRawData()
    {
        return m_paramsRawData;
    }
    void CRecipeList::reset()
    {
        m_nToatlGroupCount = 0;
        m_nCurrentGroupCount = 0;
        m_ids.clear();
        m_paramsRawData.clear();
    }
    void CRecipeList::reset2()
    {
        m_nToatlGroupCount = 0;
        m_nCurrentGroupCount = 0;
    }
    int CRecipeList::addParamsPacket(int totalCount, int totalGroup, int currentGroup,
        short unitId, short recipeId,
        const char* pszData, size_t size)
    {
        if (m_nToatlGroupCount == 0) m_nToatlGroupCount = totalGroup;
        if (m_nToatlGroupCount != totalGroup) {
            reset2();
            return MRLRC_GROUP_COUNT_NG;
        }
        if (currentGroup == 0) {
            reset2();
        }
        if (m_nCurrentGroupCount + 1 > currentGroup) {
            return MRLRC_DUPLICATION_GROUP_COUNT_NG;
        }
        if (m_nCurrentGroupCount + 1 < currentGroup) {
            return ORDER_BY_GROUP_COUNT_NG;
        }
        m_nCurrentGroupCount++;
        m_paramsRawData[recipeId].insert(m_paramsRawData[recipeId].end(), (uint8_t*)(pszData), (uint8_t*)(pszData) + size);
        if (m_nCurrentGroupCount == m_nToatlGroupCount) {
            // è§£é‡Šæ•°æ®å°±äº¤ç»™åº”用层吧
            reset2();
            return MRLRC_CURRENT_RECIPE_COMPLETE;
        }
        return MRLRC_CONTINUE;
    }
    // åºåˆ—化
    bool CRecipeList::serialize(const std::string& filename) const
    {
        std::ofstream ofs(filename, std::ios::binary);
        if (!ofs) return false;
        // å†™åŸºæœ¬æˆå‘˜
        ofs.write(reinterpret_cast<const char*>(&m_nUnitNo), sizeof(m_nUnitNo));
        ofs.write(reinterpret_cast<const char*>(&m_nToatlGroupCount), sizeof(m_nToatlGroupCount));
        ofs.write(reinterpret_cast<const char*>(&m_nCurrentGroupCount), sizeof(m_nCurrentGroupCount));
        // Ð´ m_ids
        size_t idsSize = m_ids.size();
        ofs.write(reinterpret_cast<const char*>(&idsSize), sizeof(idsSize));
        for (auto& kv : m_ids) {
            ofs.write(reinterpret_cast<const char*>(&kv.first), sizeof(kv.first));
            ofs.write(reinterpret_cast<const char*>(&kv.second), sizeof(kv.second));
        }
        // Ð´ m_paramsRawData
        size_t paramsSize = m_paramsRawData.size();
        ofs.write(reinterpret_cast<const char*>(&paramsSize), sizeof(paramsSize));
        for (auto& kv : m_paramsRawData) {
            // Ð´ key
            ofs.write(reinterpret_cast<const char*>(&kv.first), sizeof(kv.first));
            // å†™ vector å¤§å°
            size_t vecSize = kv.second.size();
            ofs.write(reinterpret_cast<const char*>(&vecSize), sizeof(vecSize));
            // å†™ vector å†…容
            if (!kv.second.empty()) {
                ofs.write(reinterpret_cast<const char*>(kv.second.data()), vecSize);
            }
        }
        return true;
    }
    // ååºåˆ—化
    bool CRecipeList::deserialize(const std::string& filename)
    {
        std::ifstream ifs(filename, std::ios::binary);
        if (!ifs) return false;
        reset(); // æ¸…空旧数据
        // è¯»åŸºæœ¬æˆå‘˜
        ifs.read(reinterpret_cast<char*>(&m_nUnitNo), sizeof(m_nUnitNo));
        ifs.read(reinterpret_cast<char*>(&m_nToatlGroupCount), sizeof(m_nToatlGroupCount));
        ifs.read(reinterpret_cast<char*>(&m_nCurrentGroupCount), sizeof(m_nCurrentGroupCount));
        // è¯» m_ids
        size_t idsSize = 0;
        ifs.read(reinterpret_cast<char*>(&idsSize), sizeof(idsSize));
        for (size_t i = 0; i < idsSize; ++i) {
            int key;
            short value;
            ifs.read(reinterpret_cast<char*>(&key), sizeof(key));
            ifs.read(reinterpret_cast<char*>(&value), sizeof(value));
            m_ids[key] = value;
        }
        // è¯» m_paramsRawData
        size_t paramsSize = 0;
        ifs.read(reinterpret_cast<char*>(&paramsSize), sizeof(paramsSize));
        for (size_t i = 0; i < paramsSize; ++i) {
            short key;
            size_t vecSize = 0;
            ifs.read(reinterpret_cast<char*>(&key), sizeof(key));
            ifs.read(reinterpret_cast<char*>(&vecSize), sizeof(vecSize));
            std::vector<uint8_t> buffer(vecSize);
            if (vecSize > 0) {
                ifs.read(reinterpret_cast<char*>(buffer.data()), vecSize);
            }
            m_paramsRawData[key] = std::move(buffer);
        }
        return true;
    }
}
SourceCode/Bond/Servo/CRecipeList.h
@@ -1,4 +1,4 @@
#pragma once
#pragma once
#include <map>
@@ -15,13 +15,25 @@
        int addRecipePacket(int totalCount,int totalGroup, int currentGroup, const char* pszData, size_t size);
        int addRecipe(int index, short id);
        std::map<int, short>& getIds();
        std::unordered_map<short, std::vector<uint8_t>>& getParamsRawData();
        void reset();
        void reset2();
        // æ·»åŠ å‚æ•°åŒ…
        int addParamsPacket(int totalCount, int totalGroup, int currentGroup,
            short unitId, short recipeId,
            const char* pszData, size_t size);
        // â­ æ–°å¢žåºåˆ—化和反序列化函数
        bool serialize(const std::string& filename) const;
        bool deserialize(const std::string& filename);
    private:
        int m_nUnitNo;
        int m_nToatlGroupCount;
        int m_nCurrentGroupCount;
        std::map<int, short> m_ids;
        std::unordered_map<short, std::vector<uint8_t>> m_paramsRawData;
    };
}
SourceCode/Bond/Servo/CRecipesManager.cpp
@@ -169,7 +169,7 @@
                }
                m_mapRecipes = m_mapRecipesTemp;
                m_mapRecipesTemp.clear();
                m_nSyncStatus = SS_COMPLETE;
                m_nSyncStatus = SS_LIST_COMPLETE;
                unlock();
                if (m_onSyncingStateChanged != nullptr) {
@@ -230,17 +230,14 @@
        // æ‰¾åˆ°å¯¹åº”CRecipeList, æ‰¾ä¸åˆ°åˆ™æ–°å»º
        /*
        // æ‰¾åˆ°å¯¹åº”CRecipeList, æ‰¾ä¸åˆ°åˆ™è¿”回NG
        lock();
        CRecipeList* pRecipeList = getRecipeListFromTemp(unitNo);
        CRecipeList* pRecipeList = getRecipeList(unitNo);
        if (pRecipeList == nullptr) {
            pRecipeList = new CRecipeList(unitNo);
            m_mapRecipesTemp[unitNo] = pRecipeList;
            unlock();
            return MRLRC_NG;
        }
        unlock();
        ASSERT(pRecipeList);
        */
        /*
         1: Create
@@ -248,7 +245,6 @@
         3: Delete
         4: Request from EAS
         */
        /*
        if (reportType == RT_CREATE) {
        }
@@ -259,26 +255,24 @@
        }
        else if (reportType == RT_REQUEST_FROM_EAS) {
            int nRet = pRecipeList->addRecipePacket(toatlGroupCount, currentGroupCount, pszIdsData, 250 * 2);
            int nRet = pRecipeList->addParamsPacket(totalParameterCount, toatlGroupCount, currentGroupCount,
                unitNo, localRecipeId,
                pszParameterData, 250 * 2);
            if (MRLRC_CURRENT_RECIPE_COMPLETE == nRet) {
                lock();
                if (m_nTotalMasterRecipeCount == m_mapRecipesTemp.size()) {
                    for (auto item : m_mapRecipes) {
                        delete item.second;
                    }
                    m_mapRecipes = m_mapRecipesTemp;
                    m_mapRecipesTemp.clear();
                    m_nSyncStatus = SS_COMPLETE;
                m_nSyncStatus = SS_PARAMS_COMPLETE;
                    unlock();
                if (m_onSyncingStateChanged != nullptr) {
                    m_onSyncingStateChanged(m_nSyncStatus);
                }
                    return MRLRC_OK;
                }
                unlock();
            return nRet;
            }
            else if (MRLRC_CONTINUE == nRet) {
                return MRLRC_CONTINUE;
            }
        }
        */
        return MRLRC_OK;
    }
@@ -297,6 +291,23 @@
        return iter->second;
    }
    bool CRecipesManager::saveRecipeList(int unitNo, std::string& strFilepath)
    {
        CRecipeList* pRecipeList = getRecipeList(unitNo);
        if (pRecipeList == nullptr) return false;
        return pRecipeList->serialize(strFilepath);
    }
    bool CRecipesManager::readRecipeList(int unitNo, std::string& strFilepath)
    {
        CRecipeList* pRecipeList = getRecipeList(unitNo);
        if (pRecipeList == nullptr) {
            pRecipeList = new CRecipeList();
            m_mapRecipes[unitNo] = pRecipeList;
        }
        return pRecipeList->deserialize(strFilepath);
    }
    void CRecipesManager::setOnSyncingStateChanged(ONSYNCINGSTATECHANGED block)
    {
        m_onSyncingStateChanged = block;
SourceCode/Bond/Servo/CRecipesManager.h
@@ -6,9 +6,10 @@
#define SS_NONE                    0
#define SS_SYNCING                1
#define SS_COMPLETE                2
#define SS_TIMEOUT                3
#define SS_FAILED                4
#define SS_LIST_COMPLETE        2
#define SS_PARAMS_COMPLETE        3
#define SS_TIMEOUT                4
#define SS_FAILED                5
namespace SERVO {
    typedef std::function<void(int state)> ONSYNCINGSTATECHANGED;
@@ -29,6 +30,8 @@
        short decodeRecipeParameterReport(const char* pszData, size_t size);
        CRecipeList* getRecipeListFromTemp(int unitNo);
        CRecipeList* getRecipeList(int unitNo);
        bool saveRecipeList(int unitNo, std::string& strFilepath);
        bool readRecipeList(int unitNo, std::string& strFilepath);
    public:
        inline void lock() { ::EnterCriticalSection(&m_cs); };
SourceCode/Bond/Servo/CRobotTask.cpp
@@ -220,7 +220,7 @@
                    LOGI(_T("RobotTask已下发到EFEM"));
                }
                else {
                    LOGI(_T("RobotTask已下发失败"));
                    LOGI(_T("RobotTask下发失败"));
                }
                return 0;
SourceCode/Bond/Servo/CVacuumBake.cpp
@@ -207,33 +207,34 @@
        {
            // è¯·æ±‚配方参数
            //CEqWriteStep* pStep = new CEqWriteStep();
            //pStep->setName(STEP_EQ_RECIPE_PARAMETER_REQ);
            //pStep->setWriteSignalDev(0xc67);
            //pStep->setDataDev(0x379b);
            //if (addStep(STEP_ID_RECIPE_PARAMETER_CMD_REPLY, pStep) != 0) {
            //    delete pStep;
            //}
            CEqWriteStep* pStep = new CEqWriteStep();
            pStep->setName(STEP_EQ_RECIPE_PARAMETER_REQ);
            pStep->setWriteSignalDev(0xc67);
            pStep->setDataDev(0x2e4b);
            if (addStep(STEP_ID_RECIPE_PARAMETER_CMD_REPLY, pStep) != 0) {
                delete pStep;
            }
        }
        {
            // recipe parameter report
            //CEqReadStep* pStep = new CEqReadStep(0x1aa54, 257 * 2,
            //    [&](void* pFrom, int code, const char* pszData, size_t size) -> int {
            //        if (code == ROK && pszData != nullptr && size > 0) {
            //            // æ­¤å¤„解释配方数据
            //            short ret = decodeRecipeParameterReport(pszData, size);
            //            pStep->setReturnCode(ret);
            //        }
            //        pStep->setReturnCode(MRLRC_OK);
            //        return -1;
            //    });
            //pStep->setName(STEP_EQ_RECIPE_PARAMETER);
            //pStep->setWriteSignalDev(0xc4c);
            //pStep->setReturnDev(m_nIndex == 0 ? 0x126c : 0x1bbc);
            //if (addStep(STEP_ID_RECIPE_PARAMETER_REPORT, pStep) != 0) {
            //    delete pStep;
            //}
            CEqReadStep* pStep = new CEqReadStep(0x16a54, 257 * 2,
                [&](void* pFrom, int code, const char* pszData, size_t size) -> int {
                    CEqReadStep* pTmpStep = (CEqReadStep*)pFrom;
                    if (code == ROK && pszData != nullptr && size > 0) {
                        // æ­¤å¤„解释配方数据
                        short ret = decodeRecipeParameterReport(pszData, size);
                        pTmpStep->setReturnCode(ret);
                    }
                    pTmpStep->setReturnCode(MRLRC_OK);
                    return -1;
                });
            pStep->setName(STEP_EQ_RECIPE_PARAMETER);
            pStep->setWriteSignalDev(0xc4c);
            pStep->setReturnDev(0x2ec);
            if (addStep(STEP_ID_RECIPE_PARAMETER_REPORT, pStep) != 0) {
                delete pStep;
            }
        }
        // ä½¿ç”¨CEqReadStep替换CEqJobEventStep
@@ -409,4 +410,53 @@
    {
        return 30000;
    }
    int CVacuumBake::parsingParams(const char* pszData, size_t size, std::vector<CParam>& params)
    {
        ASSERT(pszData);
        if (size < 250) return 0;
        int i = 0, v;
        // 1.A_腔加热时间
        v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8;
        params.push_back(CParam("A_腔加热时间", "", "", v * 0.1f));
        i += 2;
        // 2.B_腔加热时间
        v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8;
        params.push_back(CParam("B_腔加热时间", "", "", v * 0.1f));
        i += 2;
        // 3.A_腔破真空时间
        v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8;
        params.push_back(CParam("A_腔破真空时间", "", "", v * 0.01f));
        i += 2;
        // 4.B_腔破真空时间
        v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8;
        params.push_back(CParam("B_腔破真空时间", "", "", v * 0.01f));
        i += 2;
        // 5.A_腔真空到达值
        params.push_back(CParam("A_腔真空到达值", "", "", (double)toFloat(&pszData[i])));
        i += 4;
        // 6.B_腔真空到达值
        params.push_back(CParam("B_腔真空到达值", "", "", (double)toFloat(&pszData[i])));
        i += 4;
        // 7.A_腔温控表主控温度设定
        v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8 | (pszData[i + 2] & 0xff) << 16 | (pszData[i + 3] & 0xff) << 24;
        params.push_back(CParam("A_腔温控表主控温度设定", "", "", v * 0.1f));
        i += 4;
        // 8.B_腔温控表主控温度设定
        v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8 | (pszData[i + 2] & 0xff) << 16 | (pszData[i + 3] & 0xff) << 24;
        params.push_back(CParam("B_腔温控表主控温度设定", "", "", v * 0.1f));
        i += 4;
        return (int)params.size();
    }
}
SourceCode/Bond/Servo/CVacuumBake.h
@@ -22,7 +22,7 @@
        virtual void getAttributeVector(CAttributeVector& attrubutes);
        virtual int recvIntent(CPin* pPin, CIntent* pIntent);
        virtual int getIndexerOperationModeBaseValue();
        virtual int parsingParams(const char* pszData, size_t size, std::vector<CParam>& parsms);
    };
}
SourceCode/Bond/Servo/HsmsPassive.cpp
@@ -1874,6 +1874,21 @@
    return requestEventReportSend("CarrierID_Readed");
}
int CHsmsPassive::requestEventReportSend_Port_Unload_Ready()
{
    return requestEventReportSend("Port_Unload_Ready");
}
int CHsmsPassive::requestEventReportSend_Port_Load_Ready()
{
    return requestEventReportSend("Port_Load_Ready");
}
int CHsmsPassive::requestEventReportSend_Port_Blocked()
{
    return requestEventReportSend("Port_Blocked");
}
int CHsmsPassive::requestEventReportSend_PJ_Queued()
{
    return requestEventReportSend("PJ_Queued");
@@ -1889,6 +1904,25 @@
    return requestEventReportSend("PJ_End");
}
int CHsmsPassive::requestEventReportSend_CJ_Start()
{
    return requestEventReportSend("CJ_Start");
}
int CHsmsPassive::requestEventReportSend_CJ_End()
{
    return requestEventReportSend("CJ_End");
}
int CHsmsPassive::requestEventReportSend_Panel_Start()
{
    return requestEventReportSend("Panel_Start");
}
int CHsmsPassive::requestEventReportSend_Panel_End()
{
    return requestEventReportSend("Panel_End");
}
SourceCode/Bond/Servo/HsmsPassive.h
@@ -191,9 +191,16 @@
    int requestEventReportSend(unsigned int CEID);
    int requestEventReportSend(const char* pszEventName);
    int requestEventReportSend_CarrierID_Readed();
    int requestEventReportSend_Port_Unload_Ready();
    int requestEventReportSend_Port_Load_Ready();
    int requestEventReportSend_Port_Blocked();
    int requestEventReportSend_PJ_Queued();
    int requestEventReportSend_PJ_Start();
    int requestEventReportSend_PJ_End();
    int requestEventReportSend_CJ_Start();
    int requestEventReportSend_CJ_End();
    int requestEventReportSend_Panel_Start();
    int requestEventReportSend_Panel_End();
private:
    void replyAck(int s, int f, unsigned int systemBytes, BYTE ack, const char* pszAckName);
SourceCode/Bond/Servo/Model.cpp
@@ -382,10 +382,42 @@
            }
            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();
        }
        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();
        }
        else if (status == PORT_UNLOAD_READY) {
            SERVO::CLoadPort* pLoadPort = dynamic_cast<SERVO::CLoadPort*>(pEquipment);
            if (pLoadPort != nullptr) {
                m_hsmsPassive.setVariableValue("UnloadReadyPortId", pLoadPort->getID());
            }
            m_hsmsPassive.requestEventReportSend_Port_Unload_Ready();
        }
        notifyPtr(RX_CODE_LOADPORT_STATUS_CHANGED, pEquipment);
    };
    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();
    };
    masterListener.onCjEnd = [&](void* pMaster, void* pj) {
        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());
@@ -395,6 +427,14 @@
        m_hsmsPassive.setVariableValue("PJEndID", ((SERVO::CProcessJob*)pj)->id().c_str());
        m_hsmsPassive.requestEventReportSend_PJ_End();
    };
    masterListener.onPanelStart = [&](void* pMaster, void* pj) {
        m_hsmsPassive.setVariableValue("PanelStartID", ((SERVO::CGlass*)pj)->getID().c_str());
        m_hsmsPassive.requestEventReportSend_Panel_Start();
    };
    masterListener.onPanelEnd = [&](void* pMaster, void* pj) {
        m_hsmsPassive.setVariableValue("PanelEndID", ((SERVO::CGlass*)pj)->getID().c_str());
        m_hsmsPassive.requestEventReportSend_Panel_End();
    };
    m_master.setListener(masterListener);
    m_master.setContinuousTransferCount(m_configuration.getContinuousTransferCount());
SourceCode/Bond/Servo/PageRecipe.cpp
@@ -9,6 +9,7 @@
#include "InputDialog.h"
#include "RecipeDeviceBindDlg.h"
// CPageRecipe å¯¹è¯æ¡†
IMPLEMENT_DYNAMIC(CPageRecipe, CDialogEx)
@@ -172,48 +173,43 @@
    m_listPPID.SetColumnWidth(nColCount - 1, LVSCW_AUTOSIZE_USEHEADER);
}
void CPageRecipe::FillRecipeListToListCtrl(SERVO::CRecipeList* pList)
void CPageRecipe::FillRecipeListToListCtrl(SERVO::CEquipment* pEq)
{
    SERVO::CRecipeList* pRecipeList = pEq->getRecipeList(0);
    CListCtrl* pListCtrl = (CListCtrl*)GetDlgItem(IDC_LIST_PPID);
    if (pListCtrl == nullptr || !::IsWindow(pListCtrl->m_hWnd)) {
        return;
    }
    CComboBox* pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_EQUIPMENT);
    if (pComboBox == nullptr || !::IsWindow(pComboBox->m_hWnd)) {
        return;
    }
    int nEqSel = pComboBox->GetCurSel();
    if (nEqSel == CB_ERR) {
        return;
    }
    auto& mgr = RecipeManager::getInstance();
    SERVO::CEquipment* pEq = (SERVO::CEquipment*)pComboBox->GetItemDataPtr(nEqSel);
    if (pEq == nullptr) {
        return;
    }
    // æ¸…空当前CListCtrl中的所有项
    pListCtrl->DeleteAllItems();
    if (pList == nullptr) {
    if (pRecipeList == nullptr) {
        return;
    }
    // éåŽ†æ•°æ®å¹¶æ’å…¥åˆ°CListCtrl中
    std::map<int, short>& ids = pList->getIds();
    auto& mgr = RecipeManager::getInstance();
    std::map<int, short>& ids = pRecipeList->getIds();
    auto rawDatas = pRecipeList->getParamsRawData();
    for (auto item : ids) {
        int index = m_listPPID.InsertItem(m_listPPID.GetItemCount(), _T(""));
        m_listPPID.SetItemText(index, 1, std::to_string(item.first).c_str());
        m_listPPID.SetItemText(index, 2, std::to_string(item.second).c_str());
        std::string strRecipeName = mgr.getDeviceRecipeName(pEq->getName(), item.second);
        m_listPPID.SetItemText(index, 3, strRecipeName.c_str());
        auto iter = rawDatas.find(item.second);
        if (iter != rawDatas.end()) {
            std::string strDescription;
            pEq->parsingParams((const char*)iter->second.data(), iter->second.size(), strDescription);
            m_listPPID.SetItemText(index, 4, strDescription.c_str());
        }
        if (strRecipeName.empty()) {
            strRecipeName = std::to_string(item.second);
            mgr.addDeviceRecipe(pEq->getName(), item.second, strRecipeName);
        }
        m_listPPID.SetItemText(index, 3, strRecipeName.c_str());
    }
    // èŽ·å–åˆ—æ•°
@@ -374,8 +370,12 @@
                    pEq[i] == nullptr ? _T("Master") : pEq[i]->getName().c_str());
                pComboBox->SetItemDataPtr(i, pEq[i]);
                // è¯»å–回来
                char szBuffer[_MAX_PATH];
                if (pEq[i]) {
                    pEq[i]->masterRecipeListRequest(0, nullptr);
                    sprintf_s(szBuffer, _MAX_PATH, "%s\\Recipe\\EQ%d_Unit0.recipelist", (LPTSTR)(LPCTSTR)theApp.m_strAppDir, pEq[i]->getID());
                    std::string strFilepath(szBuffer);
                    pEq[i]->readRecipeList(0, strFilepath);
                }
            }
            pComboBox->SetCurSel(0);
@@ -547,32 +547,11 @@
        FillDataToListCtrl(vecData);
    }
    else {
        // enable port
        CMsgDlg msgDlg("请等待", "正在获取配方...");
        pEq->masterRecipeListRequest(0, [&, pEq](int status) -> void {
            if (status == SS_FAILED || status == SS_TIMEOUT) {
                CString strMsg;
                strMsg.Format(status == SS_FAILED ? _T("获取配方失败!") : _T("获取配方超时!"));
                msgDlg.DelayClose(3000);
                msgDlg.SetIcon(MSG_BOX_ERROR);
                msgDlg.SetTitle(_T("操作失败"));
                msgDlg.SetMessage((LPTSTR)(LPCTSTR)strMsg);
                msgDlg.SetMarquee(FALSE, 0);
                msgDlg.SetCompleteCode(-1);
            }
            else if (status == SS_COMPLETE) {
                CString strMsg;
                strMsg.Format(_T("获取配方完成!"));
                msgDlg.DelayClose(3000);
                msgDlg.SetIcon(MSG_BOX_SUCCEED);
                msgDlg.SetTitle(_T("操作成功"));
                msgDlg.SetMessage((LPTSTR)(LPCTSTR)strMsg);
                msgDlg.SetMarquee(FALSE, 0);
                msgDlg.SetCompleteCode(0);
                SERVO::CRecipeList* pRecipeList = pEq->getRecipeList(0);
                FillRecipeListToListCtrl(pRecipeList);
            }
        });
        // èŽ·å–é…æ–¹åˆ—è¡¨
        CMsgDlg msgDlg("请等待", "正在获取配方列表...");
        msgDlg.SetData((DWORD_PTR)this);
        msgDlg.SetDataEx((DWORD_PTR)pEq);
        msgDlg.BeginThread(SyncThreadFunction);
        msgDlg.DoModal();
    }
}
@@ -592,9 +571,9 @@
    int nEqSel = pComboBox->GetCurSel();
    GetDlgItem(IDC_BUTTON_NEW)->EnableWindow(nEqSel == 0);
    GetDlgItem(IDC_BUTTON_MODIFY)->EnableWindow(nItem > 0);
    GetDlgItem(IDC_BUTTON_DELETE)->EnableWindow(nEqSel == 0 && nItem > 0);
    GetDlgItem(IDC_BUTTON_DELETE_ALL)->EnableWindow(nEqSel == 0 && nItem > 0);
    GetDlgItem(IDC_BUTTON_MODIFY)->EnableWindow(nItem != -1);
    GetDlgItem(IDC_BUTTON_DELETE)->EnableWindow(nEqSel == 0 && nItem != -1);
    GetDlgItem(IDC_BUTTON_DELETE_ALL)->EnableWindow(nEqSel == 0 && nItem != -1);
}
void CPageRecipe::OnDblclkListPPID(NMHDR* pNMHDR, LRESULT* pResult)
@@ -625,12 +604,12 @@
{
    CComboBox* pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_EQUIPMENT);
    int nEqSel = pComboBox->GetCurSel();
    int selectedCount = ListView_GetSelectedCount(m_listPPID.GetSafeHwnd());
    int nItem = ListView_GetSelectedCount(m_listPPID.GetSafeHwnd());
    GetDlgItem(IDC_BUTTON_NEW)->EnableWindow(nEqSel == 0/* && selectedCount > 0*/);
    GetDlgItem(IDC_BUTTON_MODIFY)->EnableWindow(nEqSel == 0 && selectedCount > 0);
    GetDlgItem(IDC_BUTTON_DELETE)->EnableWindow(nEqSel == 0 && selectedCount > 0);
    GetDlgItem(IDC_BUTTON_DELETE_ALL)->EnableWindow(nEqSel == 0 && selectedCount > 0);
    GetDlgItem(IDC_BUTTON_NEW)->EnableWindow(nEqSel == 0);
    GetDlgItem(IDC_BUTTON_MODIFY)->EnableWindow(nEqSel == 0 && nItem != -1);
    GetDlgItem(IDC_BUTTON_DELETE)->EnableWindow(nEqSel == 0 && nItem != -1);
    GetDlgItem(IDC_BUTTON_DELETE_ALL)->EnableWindow(nEqSel == 0 && nItem != -1);
    GetDlgItem(IDC_EDIT_KEYWORD)->EnableWindow(nEqSel == 0);
    GetDlgItem(IDC_BUTTON_SEARCH)->EnableWindow(nEqSel == 0);
@@ -642,7 +621,127 @@
    }
    else {
        InitListCtrlHeaderForDevice();
        SERVO::CRecipeList* pRecipeList = pEq->getRecipeList(0);
        FillRecipeListToListCtrl(pRecipeList);
        FillRecipeListToListCtrl(pEq);
    }
}
UINT CPageRecipe::SyncThreadFunction(LPVOID lpvData)
{
    CMsgDlg* pMsgDlg = (CMsgDlg*)lpvData;
    CPageRecipe* pPageRecipe = (CPageRecipe*)pMsgDlg->GetData();
    return pPageRecipe->SyncThreadFunctionInner(pMsgDlg);
}
UINT CPageRecipe::SyncThreadFunctionInner(CMsgDlg* pMsgDlg)
{
    SERVO::CEquipment* pEq = (SERVO::CEquipment*)pMsgDlg->GetDataEx();
    HANDLE hEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
    int nStep = 0;
    // å‡†å¤‡é…æ–¹è·¯å¾„
    char szBuffer[_MAX_PATH];
    sprintf_s(szBuffer, _MAX_PATH, "%s\\Recipe\\EQ%d_Unit0.recipelist", (LPTSTR)(LPCTSTR)theApp.m_strAppDir, pEq->getID());
    std::string strFilepath(szBuffer);
    pEq->masterRecipeListRequest(0, [&, pEq, pMsgDlg, hEvent](int status) -> void {
        Sleep(300);
        if (status == SS_FAILED || status == SS_TIMEOUT) {
            CString strMsg;
            strMsg.Format(status == SS_FAILED ? _T("获取配方列表失败!") : _T("获取配方列表超时!"));
            pMsgDlg->SetIcon(MSG_BOX_ERROR);
            pMsgDlg->SetTitle(_T("操作失败"));
            pMsgDlg->SetMessage((LPTSTR)(LPCTSTR)strMsg);
            SetEvent(hEvent);
        }
        else if (status == SS_LIST_COMPLETE) {
            CString strMsg;
            strMsg.Format(_T("获取配方列表完成!"));
            pMsgDlg->SetTitle(_T("操作成功"));
            pMsgDlg->SetMessage((LPTSTR)(LPCTSTR)strMsg);
            SERVO::CRecipeList* pRecipeList = pEq->getRecipeList(0);
            if (pRecipeList != nullptr && !pRecipeList->getIds().empty()) {
                nStep = 1;
            }
            SetEvent(hEvent);
        }
    });
    ::WaitForSingleObject(hEvent, INFINITE);
    if (nStep != 1) {
        pEq->saveRecipeList(0, strFilepath);
        pMsgDlg->SetIcon(MSG_BOX_SUCCEED);
        pMsgDlg->SetMarquee(FALSE, 0);
        pMsgDlg->SetCompleteCode(-1);
        pMsgDlg->DelayClose(3000);
    }
    ResetEvent(hEvent);
    // å‚数列表
    if (nStep == 1) {
        SERVO::CRecipeList* pRecipeList = pEq->getRecipeList(0);
        ASSERT(pRecipeList);
        auto& ids = pRecipeList->getIds();
        pMsgDlg->SetTitle(_T("正在获取参数"));
        for (auto item : ids) {
            int recipeId = item.second;
            CString strMsg;
            strMsg.Format(_T("正在获取配方 %d å‚æ•°..."), item.second);
            pMsgDlg->SetMessage((LPTSTR)(LPCTSTR)strMsg);
            pEq->recipeParameterRequest(0, recipeId, 0, [&, pEq, pMsgDlg, recipeId, hEvent](int status) -> void {
                Sleep(500);
                if (status == SS_FAILED || status == SS_TIMEOUT) {
                    CString strMsg;
                    strMsg.Format(status == SS_FAILED ? _T("获取配方 %d å‚数失败!") : _T("获取配方 %d å‚数超时!"), recipeId);
                    pMsgDlg->SetMessage((LPTSTR)(LPCTSTR)strMsg);
                    Sleep(30);
                    SetEvent(hEvent);
                }
                else if (status == SS_PARAMS_COMPLETE) {
                    CString strMsg;
                    strMsg.Format(_T("获取配方 %d å‚数完成!"), item.second);
                    pMsgDlg->SetMessage((LPTSTR)(LPCTSTR)strMsg);
                    Sleep(30);
                    SetEvent(hEvent);
                }
                });
            ::WaitForSingleObject(hEvent, INFINITE);
            ResetEvent(hEvent);
        }
        pEq->saveRecipeList(0, strFilepath);
        pMsgDlg->SetIcon(MSG_BOX_SUCCEED);
        pMsgDlg->SetTitle(_T("操作完成"));
        pMsgDlg->SetCompleteCode(0);
        pMsgDlg->SetMarquee(FALSE, 0);
        pMsgDlg->DelayClose(3000);
    };
    FillRecipeListToListCtrl(pEq);
    CloseHandle(hEvent);
    // åœ¨æ­¤æ‰“印配方参数以便核对数据
    SERVO::CRecipeList* pRecipeList = pEq->getRecipeList(0);
    ASSERT(pRecipeList);
    auto rawDatas = pRecipeList->getParamsRawData();
    for (auto item : rawDatas) {
        TRACE("================= é…æ–¹ %d\n", item.first);
        std::vector<CParam> params;
        pEq->parsingParams((const char*)item.second.data(), item.second.size(), params);
        for (auto p : params) {
            if (p.getValueType() == PVT_INT) {
                TRACE("%s: %d\n", p.getName().c_str(), p.getIntValue());
            }
            else if (p.getValueType() == PVT_DOUBLE) {
                TRACE("%s: %f\n", p.getName().c_str(), p.getDoubleValue());
            }
        }
    }
    return 0;
}
SourceCode/Bond/Servo/PageRecipe.h
@@ -2,6 +2,8 @@
#include "afxdialogex.h"
#include "RecipeManager.h"
#include "ListCtrlEx.h"
#include "MsgDlg.h"
// CPageRecipe å¯¹è¯æ¡†
@@ -13,12 +15,16 @@
    CPageRecipe(CWnd* pParent = nullptr);   // æ ‡å‡†æž„造函数
    virtual ~CPageRecipe();
public:
    static UINT SyncThreadFunction(LPVOID lpvData);
    UINT SyncThreadFunctionInner(CMsgDlg* pMsgDlg);
private:
    void InitListCtrlHeaderForMaster();
    void InitListCtrlHeaderForDevice();
    void UpdateRecipeByPPID(const CString& strPPID);
    void FillDataToListCtrl(const std::vector<RecipeInfo>& vecRecipe);
    void FillRecipeListToListCtrl(SERVO::CRecipeList* pList);
    void FillRecipeListToListCtrl(SERVO::CEquipment* pEq);
// å¯¹è¯æ¡†æ•°æ®
#ifdef AFX_DESIGN_TIME
SourceCode/Bond/Servo/RecipeManager.h
@@ -6,13 +6,17 @@
#include <mutex>
#include <unordered_map>
#include "Database.h"
#include "CParam.h"
// å•个设备配方映射信息
struct DeviceRecipe {
    int nDeviceID;               // è®¾å¤‡ID
    int nRecipeID;               // å­é…æ–¹ID
    std::string strDeviceName;   // è®¾å¤‡åç§°
    std::string strRecipeName;   // å­é…æ–¹åç§°
    std::string strRecipeName;                // è®¾å¤‡åç§°
    std::string strDeviceName;                // å­é…æ–¹åç§°
    std::vector<uint8_t> paramsRawData;     // åŽŸå§‹å‚æ•°æ•°æ®
    std::vector<CParam*> m_params;            // å‚数对象列表
};
// é…æ–¹ä¿¡æ¯
SourceCode/Bond/Servo/Servo.vcxproj
@@ -214,6 +214,7 @@
    <ClInclude Include="CPageLinkSignal.h" />
    <ClInclude Include="CPageReport.h" />
    <ClInclude Include="CPageVarialbles.h" />
    <ClInclude Include="CParam.h" />
    <ClInclude Include="CReport.h" />
    <ClInclude Include="CRobotCmdContainerDlg.h" />
    <ClInclude Include="CRobotCmdTestDlg.h" />
@@ -368,6 +369,7 @@
    <ClCompile Include="CPageLinkSignal.cpp" />
    <ClCompile Include="CPageReport.cpp" />
    <ClCompile Include="CPageVarialbles.cpp" />
    <ClCompile Include="CParam.cpp" />
    <ClCompile Include="CReport.cpp" />
    <ClCompile Include="CRobotCmdContainerDlg.cpp" />
    <ClCompile Include="CRobotCmdTestDlg.cpp" />
SourceCode/Bond/Servo/Servo.vcxproj.filters
@@ -180,6 +180,7 @@
    <ClCompile Include="CControlJob.cpp" />
    <ClCompile Include="CExpandableListCtrl.cpp" />
    <ClCompile Include="CControlJobDlg.cpp" />
    <ClCompile Include="CParam.cpp" />
  </ItemGroup>
  <ItemGroup>
    <ClInclude Include="AlarmManager.h" />
@@ -366,6 +367,7 @@
    <ClInclude Include="SerializeUtil.h" />
    <ClInclude Include="CExpandableListCtrl.h" />
    <ClInclude Include="CControlJobDlg.h" />
    <ClInclude Include="CParam.h" />
  </ItemGroup>
  <ItemGroup>
    <ResourceCompile Include="Servo.rc" />
SourceCode/Bond/Servo/Servo.vcxproj.user
@@ -7,6 +7,6 @@
    <RemoteDebuggerCommand>\\DESKTOP-IODBVIQ\Servo\Debug\Servo.exe</RemoteDebuggerCommand>
    <RemoteDebuggerWorkingDirectory>\\DESKTOP-IODBVIQ\Servo\Debug\</RemoteDebuggerWorkingDirectory>
    <RemoteDebuggerServerName>DESKTOP-IODBVIQ</RemoteDebuggerServerName>
    <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
    <DebuggerFlavor>WindowsRemoteDebugger</DebuggerFlavor>
  </PropertyGroup>
</Project>
SourceCode/Bond/Servo/ServoCommo.h
@@ -73,6 +73,7 @@
    };
    enum class MaterialsType {
        G0 = 0,
        G1 = 1,
        G2 = 2,
        G1G2 = 3
SourceCode/Bond/Servo/ServoDlg.cpp
@@ -243,7 +243,7 @@
                        pEq2 = theApp.m_model.getMaster().getEquipment(pTask->getTarPosition());
                        if (pEq1 != nullptr && pEq2 != nullptr) {
                            CString strText;
                            if (theApp.m_model.getMaster().getContinuousTransferCount() > 0) {
                            if (theApp.m_model.getMaster().getState() == SERVO::MASTERSTATE::RUNNING_CONTINUOUS_TRANSFER) {
                                strText.Format(_T("[%d]%s --> %s"),
                                    theApp.m_model.getMaster().getContinuousTransferCount(),
                                    pEq1->getName().c_str(), pEq2->getName().c_str());
SourceCode/Bond/x64/Debug/CollectionEventList.txt
@@ -40,4 +40,12 @@
50000,CarrierID_Readed,,(50000)
50001,PJ_Queued,,(50001)
50002,PJ_Start,,(50002)
50002,PJ_End,,(50003)
50003,PJ_End,,(50003)
50004,Panel_Start,,(50004)
50005,Panel_End,,(50005)
50006,CJ_Start,,(50006)
50007,CJ_End,,(50007)
50008,Port_Unload_Ready,,(50008)
50009,Port_Load_Ready,,(50009)
50010,Port_Blocked,,(50010)
SourceCode/Bond/x64/Debug/ReportList.txt
@@ -18,4 +18,13 @@
50000,(5000)
50001,(5003)
50002,(5004)
50003,(5005)
50004,(5006)
50005,(5007)
50006,(5008)
50007,(5009)
50008,(5010)
50009,(5011)
50010,(5012)
SourceCode/Bond/x64/Debug/VariableList.txt
@@ -8,34 +8,42 @@
701,PreviousProcessState,U1,
800,EFEMPPExecName,A20,
801,EQPPExecName,A20,
2000,RbRAxisTorque,I2,机器人R轴扭矩
2001,RbLAxisTorque,l2,机器人L轴扭矩
2002,RbZAxisTorque,l2,机器人Z轴扭矩
2003,RbTHAxisTorque,l2,机器人TH轴扭矩
2004,RbXAxisTorque,l2,机器人X轴扭矩
2005,AxisX111,l2,X111相机前移栽电机扭矩
2006,AxisX112,l2,X112相机后移栽电机扭矩
2007,AxisU113,l2,U113产品旋转电机扭矩
2008,AxisX114,l2,X114产品左整列电机扭矩
2009,AxisY121,l2,Y121产品右整列电机扭矩
2010,AxisY122,l2,Y122产品前整列电机扭矩
2011,AxisY123,l2,Y123产品后阵列电机扭矩
2012,MainAir,U2,总进气压力值
2013,MainVacuum,l2,总真空压力值
2014,RbMainVacuum,l2,机器人真空值
2015,LPMainVacuum,l2,LP真空值#D265
2016,LPMainAir,U2,LP压空值
2017,ALVacuum,l2,Aligner真空值
2018,FFU1RPM,U2,FFU1转速
2019,FFU2RPM,U2,FFU2转速
2020,FFU3RPM,U2,FFU3转速
2021,FFU4RPM,U2,FFU4转速
2022,ESDValue,I2,静电检测值
2023,OCREnable,U2,"OCR使能:O:开启 1:屏蔽"
2024,CCDEnable,U2,"CCD使能:O:开启 1:屏蔽"
2025,FFUParameter,U2,FFU设定值
5000,CarrierID,A20,卡匣ID
2000,RbRAxisTorque,I2,机器人R轴扭矩
2001,RbLAxisTorque,l2,机器人L轴扭矩
2002,RbZAxisTorque,l2,机器人Z轴扭矩
2003,RbTHAxisTorque,l2,机器人TH轴扭矩
2004,RbXAxisTorque,l2,机器人X轴扭矩
2005,AxisX111,l2,X111相机前移栽电机扭矩
2006,AxisX112,l2,X112相机后移栽电机扭矩
2007,AxisU113,l2,U113产品旋转电机扭矩
2008,AxisX114,l2,X114产品左整列电机扭矩
2009,AxisY121,l2,Y121产品右整列电机扭矩
2010,AxisY122,l2,Y122产品前整列电机扭矩
2011,AxisY123,l2,Y123产品后阵列电机扭矩
2012,MainAir,U2,总进气压力值
2013,MainVacuum,l2,总真空压力值
2014,RbMainVacuum,l2,机器人真空值
2015,LPMainVacuum,l2,LP真空值#D265
2016,LPMainAir,U2,LP压空值
2017,ALVacuum,l2,Aligner真空值
2018,FFU1RPM,U2,FFU1转速
2019,FFU2RPM,U2,FFU2转速
2020,FFU3RPM,U2,FFU3转速
2021,FFU4RPM,U2,FFU4转速
2022,ESDValue,I2,静电检测值
2023,OCREnable,U2,"OCR使能:O:开启 1:屏蔽"
2024,CCDEnable,U2,"CCD使能:O:开启 1:屏蔽"
2025,FFUParameter,U2,FFU设定值
5000,CarrierID,A20,卡匣ID
5001,CJobSpace,U1,CJ Space
5002,PJobSpace,U1,PJ Space
5003,PJQueued,L,PJ Queued
5004,PJStartID,A20,PJStartID
5005,PJEndID,A20,PJEndID
5006,PanelStartID,A20,PanelStartID
5007,PanelEndID,A20,PanelEndID
5008,CJStartID,A20,CJStartID
5009,CJEndID,A20,CJEndID
5010,UnloadReadyPortId,U2,"Port ID"
5011,LoadReadyPortId,U2,"Port ID"
5012,BlockedPortId,U2,"Port ID"