LAPTOP-SNT8I5JK\Boounion
2025-09-04 1efb832676e8ad27e7a495dba6ffc19479e0c76f
1.机器配方参数的获取;
已添加1个文件
已删除1个文件
已修改13个文件
379 ■■■■ 文件已修改
Document/EO2860AVA-101工艺参数(1).xlsx 补丁 | 查看 | 原始文档 | blame | 历史
Document/配方参数.xlsx 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CBakeCooling.cpp 21 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CBonder.cpp 57 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CEquipment.cpp 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CEquipment.h 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CMeasurement.cpp 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CRecipeList.cpp 96 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CRecipeList.h 9 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CRecipesManager.cpp 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CRecipesManager.h 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CVacuumBake.cpp 25 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/PageRecipe.cpp 68 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/PageRecipe.h 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/RecipeManager.h 19 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Document/EO2860AVA-101¹¤ÒÕ²ÎÊý(1).xlsx
Binary files differ
Document/Åä·½²ÎÊý.xlsx
Binary files differ
SourceCode/Bond/Servo/CBakeCooling.cpp
@@ -220,12 +220,13 @@
            // recipe parameter report
            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);
                        pStep->setReturnCode(ret);
                        pTmpStep->setReturnCode(ret);
                    }
                    pStep->setReturnCode(MRLRC_OK);
                    pTmpStep->setReturnCode(MRLRC_OK);
                    return -1;
                });
            pStep->setName(STEP_EQ_RECIPE_PARAMETER);
@@ -423,7 +424,7 @@
        return pGlass->isProcessed(m_nID, getSlotUnit(slot));
    }
    int CBakeCooling::parsingParams(const char* pszData, size_t size, std::vector<CParam>& parsms)
    int CBakeCooling::parsingParams(const char* pszData, size_t size, std::vector<CParam>& params)
    {
        ASSERT(pszData);
        if (size < 250) return 0;
@@ -432,36 +433,36 @@
        // 1.A_腔烘烤时间
        v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8;
        parsms.push_back(CParam("A_腔烘烤时间", 0, "", v * 0.01f));
        params.push_back(CParam("A_腔烘烤时间", "", "", v * 0.01f));
        i += 2;
        // 2.A_腔冷却时间
        v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8;
        parsms.push_back(CParam("A_腔冷却时间", 0, "", v * 0.01f));
        params.push_back(CParam("A_腔冷却时间", "", "", v * 0.01f));
        i += 2;
        // 3.B_腔烘烤时间
        v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8;
        parsms.push_back(CParam("B_腔烘烤时间", 0, "", v * 0.01f));
        params.push_back(CParam("B_腔烘烤时间", "", "", v * 0.01f));
        i += 2;
        // 4.BB_腔冷却时间
        v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8;
        parsms.push_back(CParam("B_腔冷却时间", 0, "", v * 0.01f));
        params.push_back(CParam("B_腔冷却时间", "", "", v * 0.01f));
        i += 2;
        // 5.A_烘烤温度设定
        v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8;
        parsms.push_back(CParam("A_烘烤温度设定", 0, "", v * 0.1f));
        params.push_back(CParam("A_烘烤温度设定", "", "", v * 0.1f));
        i += 2;
        // 6.B_烘烤温度设定
        v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8;
        parsms.push_back(CParam("B_烘烤温度设定", 0, "", v * 0.1f));
        params.push_back(CParam("B_烘烤温度设定", "", "", v * 0.1f));
        i += 2;
        return (int)parsms.size();
        return (int)params.size();
    }
}
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);
@@ -523,7 +524,7 @@
        return m_nIndex == 0 ? 15000 : 20000;
    }
    int CBonder::parsingParams(const char* pszData, size_t size, std::vector<CParam>& parsms)
    int CBonder::parsingParams(const char* pszData, size_t size, std::vector<CParam>& params)
    {
        ASSERT(pszData);
        if (size < 250) return 0;
@@ -532,113 +533,113 @@
        // 1.校正对位延时
        v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8;
        parsms.push_back(CParam("校正对位延时", 0, "", v * 0.01f));
        params.push_back(CParam("校正对位延时", "", "", v * 0.01f));
        i += 2;
        // 2.保压时间
        v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8;
        parsms.push_back(CParam("保压时间", 0, "", v * 0.01f));
        params.push_back(CParam("保压时间", "", "", v * 0.01f));
        i += 2;
        // 3.腔体破真空延时
        v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8;
        parsms.push_back(CParam("腔体破真空延时", 0, "", v * 0.01f));
        params.push_back(CParam("腔体破真空延时", "", "", v * 0.01f));
        i += 2;
        // 4.腔体分子泵启动延时
        v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8;
        parsms.push_back(CParam("腔体分子泵启动延时", 0, "", v * 0.1f));
        params.push_back(CParam("腔体分子泵启动延时", "", "", v * 0.1f));
        i += 2;
        // 5.腔体贴附抽真空延时
        v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8;
        parsms.push_back(CParam("腔体贴附抽真空延时", 0, "", v * 0.1f));
        params.push_back(CParam("腔体贴附抽真空延时", "", "", v * 0.1f));
        i += 2;
        // 6.加热等待延时
        v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8;
        parsms.push_back(CParam("加热等待延时", 0, "", v * 0.1f));
        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;
        parsms.push_back(CParam("气囊压力设定", 0, "", v * 0.1f));
        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;
        parsms.push_back(CParam("气囊加压速率", 0, "", v * 0.1f));
        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;
        parsms.push_back(CParam("气囊泄压速率", 0, "", v * 0.1f));
        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;
        parsms.push_back(CParam("贴附压力上限", 0, "", v * 0.1f));
        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;
        parsms.push_back(CParam("上腔Z轴转矩速度设定", 0, "", v * 0.001f));
        params.push_back(CParam("上腔Z轴转矩速度设定", "", "", v * 0.001f));
        i += 4;
        // 12.上腔温度设定
        v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8;
        parsms.push_back(CParam("上腔温度设定", 0, "", v * 0.1f));
        params.push_back(CParam("上腔温度设定", "", "", v * 0.1f));
        i += 2;
        // 13.下腔温度设定
        v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8;
        parsms.push_back(CParam("下腔温度设定", 0, "", v * 0.1f));
        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;
        parsms.push_back(CParam("上腔Z轴预贴合位速度", 0, "", v * 0.001f));
        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;
        parsms.push_back(CParam("上腔Z轴贴附位速度", 0, "", v * 0.001f));
        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;
        parsms.push_back(CParam("上腔Z上腔加热位间距", 0, "", v * 0.001f));
        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;
        parsms.push_back(CParam("上腔贴附位压入量", 0, "", v * 0.001f));
        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;
        parsms.push_back(CParam("上腔Z轴破真空距离", 0, "", v * 0.001f));
        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;
        parsms.push_back(CParam("下顶Pin破真空距离", 0, "", v * 0.001f));
        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;
        parsms.push_back(CParam("下顶Pin加热位间距", 0, "", v * 0.001f));
        params.push_back(CParam("下顶Pin加热位间距", "", "", v * 0.001f));
        i += 4;
        // 21.腔体真空泵真空规设定值
        parsms.push_back(CParam("腔体真空泵真空规设定值", 0, "", (double)toFloat(&pszData[i])));
        params.push_back(CParam("腔体真空泵真空规设定值", "", "", (double)toFloat(&pszData[i])));
        i += 4;
        // 22.腔体分子泵到达设定值
        parsms.push_back(CParam("腔体分子泵到达设定值", 0, "", (double)toFloat(&pszData[i])));
        params.push_back(CParam("腔体分子泵到达设定值", "", "", (double)toFloat(&pszData[i])));
        i += 4;
        return (int)parsms.size();
        return (int)params.size();
    }
}
SourceCode/Bond/Servo/CEquipment.cpp
@@ -496,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);
@@ -811,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)
@@ -2099,4 +2114,25 @@
        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
@@ -123,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);
@@ -169,7 +171,8 @@
        int recipeParameterRequest(short masterRecipeId, short localRecipeId, short unitNo, ONSYNCINGSTATECHANGED block);
        // è§£æžé…æ–¹å‚数列表
        virtual int parsingParams(const char* pszData, size_t size, std::vector<CParam>& parsms) { return 0;  };
        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);
SourceCode/Bond/Servo/CMeasurement.cpp
@@ -220,12 +220,13 @@
            // recipe parameter report
            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);
                        pStep->setReturnCode(ret);
                        pTmpStep->setReturnCode(ret);
                    }
                    pStep->setReturnCode(MRLRC_OK);
                    pTmpStep->setReturnCode(MRLRC_OK);
                    return -1;
                });
            pStep->setName(STEP_EQ_RECIPE_PARAMETER);
@@ -417,7 +418,7 @@
        return 35000;
    }
    int CMeasurement::parsingParams(const char* pszData, size_t size, std::vector<CParam>& parsms)
    int CMeasurement::parsingParams(const char* pszData, size_t size, std::vector<CParam>& params)
    {
        ASSERT(pszData);
        if (size < 250) return 0;
@@ -426,10 +427,14 @@
        // 1.检测功能启用/禁用
        v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8;
        parsms.push_back(CParam("检测功能启用/禁用", 0, "", v));
        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)parsms.size();
        return (int)params.size();
    }
}
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;
        }
@@ -90,17 +93,23 @@
        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) {
            reset();
            reset2();
            return MRLRC_GROUP_COUNT_NG;
        }
        if (currentGroup == 0) {
            reset();
            reset2();
        }
        if (m_nCurrentGroupCount + 1 > currentGroup) {
            return MRLRC_DUPLICATION_GROUP_COUNT_NG;
@@ -113,6 +122,8 @@
        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;
        }
@@ -120,4 +131,85 @@
        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>
@@ -17,12 +17,17 @@
        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;
SourceCode/Bond/Servo/CRecipesManager.cpp
@@ -232,7 +232,7 @@
        // æ‰¾åˆ°å¯¹åº”CRecipeList, æ‰¾ä¸åˆ°åˆ™è¿”回NG
        lock();
        CRecipeList* pRecipeList = getRecipeListFromTemp(unitNo);
        CRecipeList* pRecipeList = getRecipeList(unitNo);
        if (pRecipeList == nullptr) {
            unlock();
            return MRLRC_NG;
@@ -262,6 +262,11 @@
                lock();
                m_nSyncStatus = SS_PARAMS_COMPLETE;
                unlock();
                if (m_onSyncingStateChanged != nullptr) {
                    m_onSyncingStateChanged(m_nSyncStatus);
                }
                return MRLRC_OK;
            }
@@ -286,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
@@ -30,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/CVacuumBake.cpp
@@ -220,12 +220,13 @@
            // recipe parameter report
            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);
                        pStep->setReturnCode(ret);
                        pTmpStep->setReturnCode(ret);
                    }
                    pStep->setReturnCode(MRLRC_OK);
                    pTmpStep->setReturnCode(MRLRC_OK);
                    return -1;
                });
            pStep->setName(STEP_EQ_RECIPE_PARAMETER);
@@ -410,7 +411,7 @@
        return 30000;
    }
    int CVacuumBake::parsingParams(const char* pszData, size_t size, std::vector<CParam>& parsms)
    int CVacuumBake::parsingParams(const char* pszData, size_t size, std::vector<CParam>& params)
    {
        ASSERT(pszData);
        if (size < 250) return 0;
@@ -419,43 +420,43 @@
        // 1.A_腔加热时间
        v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8;
        parsms.push_back(CParam("A_腔加热时间", 0, "", v * 0.1f));
        params.push_back(CParam("A_腔加热时间", "", "", v * 0.1f));
        i += 2;
        // 2.B_腔加热时间
        v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8;
        parsms.push_back(CParam("B_腔加热时间", 0, "", v * 0.1f));
        params.push_back(CParam("B_腔加热时间", "", "", v * 0.1f));
        i += 2;
        // 3.A_腔破真空时间
        v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8;
        parsms.push_back(CParam("A_腔破真空时间", 0, "", v * 0.01f));
        params.push_back(CParam("A_腔破真空时间", "", "", v * 0.01f));
        i += 2;
        // 4.B_腔破真空时间
        v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8;
        parsms.push_back(CParam("B_腔破真空时间", 0, "", v * 0.01f));
        params.push_back(CParam("B_腔破真空时间", "", "", v * 0.01f));
        i += 2;
        // 5.A_腔真空到达值
        parsms.push_back(CParam("A_腔真空到达值", 0, "", (double)toFloat(&pszData[i])));
        params.push_back(CParam("A_腔真空到达值", "", "", (double)toFloat(&pszData[i])));
        i += 4;
        // 6.B_腔真空到达值
        parsms.push_back(CParam("B_腔真空到达值", 0, "", (double)toFloat(&pszData[i])));
        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;
        parsms.push_back(CParam("A_腔温控表主控温度设定", 0, "", v * 0.1f));
        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;
        parsms.push_back(CParam("B_腔温控表主控温度设定", 0, "", v * 0.1f));
        params.push_back(CParam("B_腔温控表主控温度设定", "", "", v * 0.1f));
        i += 4;
        return (int)parsms.size();
        return (int)params.size();
    }
}
SourceCode/Bond/Servo/PageRecipe.cpp
@@ -160,8 +160,9 @@
    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;
@@ -169,16 +170,23 @@
    // æ¸…空当前CListCtrl中的所有项
    pListCtrl->DeleteAllItems();
    if (pList == nullptr) {
    if (pRecipeList == nullptr) {
        return;
    }
    // éåŽ†æ•°æ®å¹¶æ’å…¥åˆ°CListCtrl中
    std::map<int, short>& ids = pList->getIds();
    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());
        auto iter = rawDatas.find(item.second);
        if (iter != rawDatas.end()) {
            std::string strDescription;
            pEq->parsingParams((const char*)iter->second.data(), iter->second.size(), strDescription);
        }
    }
    // èŽ·å–åˆ—æ•°
@@ -338,8 +346,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);
@@ -531,8 +543,7 @@
    }
    else {
        InitListCtrlHeaderForDevice();
        SERVO::CRecipeList* pRecipeList = pEq->getRecipeList(0);
        FillRecipeListToListCtrl(pRecipeList);
        FillRecipeListToListCtrl(pEq);
    }
}
@@ -548,6 +559,12 @@
    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) {
@@ -572,6 +589,7 @@
    });
    ::WaitForSingleObject(hEvent, INFINITE);
    if (nStep != 1) {
        pEq->saveRecipeList(0, strFilepath);
        pMsgDlg->SetIcon(MSG_BOX_SUCCEED);
        pMsgDlg->SetMarquee(FALSE, 0);
        pMsgDlg->SetCompleteCode(-1);
@@ -587,17 +605,18 @@
        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, item.second, 0, [&, pEq, pMsgDlg](int status) -> void {
            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 å‚数超时!"), item.second);
                    strMsg.Format(status == SS_FAILED ? _T("获取配方 %d å‚数失败!") : _T("获取配方 %d å‚数超时!"), recipeId);
                    pMsgDlg->SetMessage((LPTSTR)(LPCTSTR)strMsg);
                    Sleep(300);
                    Sleep(30);
                    SetEvent(hEvent);
                }
                else if (status == SS_PARAMS_COMPLETE) {
@@ -605,7 +624,7 @@
                    strMsg.Format(_T("获取配方 %d å‚数完成!"), item.second);
                    pMsgDlg->SetMessage((LPTSTR)(LPCTSTR)strMsg);
                    Sleep(300);
                    Sleep(30);
                    SetEvent(hEvent);
                }
                });
@@ -613,6 +632,8 @@
            ResetEvent(hEvent);
        }
        
        pEq->saveRecipeList(0, strFilepath);
        pMsgDlg->SetIcon(MSG_BOX_SUCCEED);
        pMsgDlg->SetTitle(_T("操作完成"));
        pMsgDlg->SetCompleteCode(0);
@@ -620,10 +641,33 @@
        pMsgDlg->DelayClose(3000);
    };
    SERVO::CRecipeList* pRecipeList = pEq->getRecipeList(0);
    FillRecipeListToListCtrl(pRecipeList);
    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
@@ -24,7 +24,7 @@
    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
@@ -15,6 +15,8 @@
    int nRecipeID;               // å­é…æ–¹ID
    std::string strRecipeName;   // å­é…æ–¹åç§°
    std::string strDeviceName;   // è®¾å¤‡åç§° 
    std::vector<uint8_t> paramsRawData;     // é…æ–¹åŽŸå§‹æ•°æ®
    std::vector<CParam*> m_params;            // å‡ºç«™æ—¶è®°å½•参数
};
// é…æ–¹ä¿¡æ¯
@@ -23,23 +25,6 @@
    std::string strDescription;  // é…æ–¹æè¿°
    std::string strCreateTime;   // åˆ›å»ºæ—¶é—´
    std::vector<DeviceRecipe> vecDeviceList;  // å…³è”的设备信息列表
    std::vector<CParam*> m_params;            // å‡ºç«™æ—¶è®°å½•参数
    void RecipeInfo::addIntParam(const char* pszName, const char* pszId, const char* pszUnit, int value)
    {
        CParam* pParam = new CParam(pszName, pszId, pszUnit, value);
        m_params.push_back(pParam);
    }
    void RecipeInfo::addDoubleParam(const char* pszName, const char* pszId, const char* pszUnit, double value)
    {
        CParam* pParam = new CParam(pszName, pszId, pszUnit, value);
        m_params.push_back(pParam);
    }
    std::vector<CParam*>& RecipeInfo::getParams()
    {
        return m_params;
    }
};
using RecipeMap = std::unordered_map<std::string, RecipeInfo>; // æŒ‰ PPID æ˜ å°„的配方表