18108a94f48b2cd6f9fce59aa5ed1d1ccc3f27b2..576e5fc2d2db7d106dc264c685d5a59849082d1f
2025-06-19 mrDarker
1. 添加JOB Data交互
576e5f 对比 | 目录
2025-06-19 mrDarker
Merge branch 'clh' into liuyang
4e5df2 对比 | 目录
2025-06-19 mrDarker
1. 补充发送信号读取PLC信号 2. 补充结束发送信号给PLC
29adbd 对比 | 目录
2025-06-19 LAPTOP-SNT8I5JK\Boounion
1.修复LoadPort生成GlassID序号偏移问题; 2.用于测试的代码;
c23460 对比 | 目录
2025-06-19 LAPTOP-SNT8I5JK\Boounion
1.对Panel Data Request的响应;
7a60f2 对比 | 目录
2025-06-19 LAPTOP-SNT8I5JK\Boounion
1.重新梳理JobDataS的传递和更新;
be0131 对比 | 目录
2025-06-19 LAPTOP-SNT8I5JK\Boounion
1.生成玻璃的JobDataS数据,采用新的JobNo等id
d24917 对比 | 目录
2025-06-19 LAPTOP-SNT8I5JK\Boounion
1.准备处理PanelDataRequest的响应; 2.删除掉Glass中的JobDataB
e43178 对比 | 目录
2025-06-19 mrDarker
Merge branch 'clh' into liuyang
8ffc83 对比 | 目录
2025-06-19 mrDarker
1. 添加设备配方绑定
02d1df 对比 | 目录
2025-06-19 LAPTOP-SNT8I5JK\Boounion
1.启动自动搬送时,先发送start到各机台
d7973a 对比 | 目录
2025-06-19 mrDarker
Merge branch 'clh' into liuyang
ae6ef5 对比 | 目录
2025-06-18 LAPTOP-SNT8I5JK\Boounion
1.更新文档 ;
3e369a 对比 | 目录
2025-06-18 LAPTOP-SNT8I5JK\Boounion
1.CEqWriteStep, 写数据时,有时还要读取对方的返回值,增加获取返回数据的功能;
96266d 对比 | 目录
2025-06-17 LAPTOP-SNT8I5JK\Boounion
Merge branch 'liuyang' into clh
3c387c 对比 | 目录
2025-06-17 LAPTOP-SNT8I5JK\Boounion
1.增加Send Able信号出现号的事件处理;
b4aa15 对比 | 目录
已添加3个文件
已删除6个文件
已修改34个文件
1180 ■■■■ 文件已修改
Document/ESWIN_EAS_Bonder_Inline_Mapping_Address_v1.1.1.xlsx 补丁 | 查看 | 原始文档 | blame | 历史
Document/ESWIN_EAS_Bonder_Inline_Mapping_Address_v1.1.2.xlsx 补丁 | 查看 | 原始文档 | blame | 历史
Document/ESWIN_EAS_Bonder_Inline_Mapping_Address_v1.1.4(1).xlsx 补丁 | 查看 | 原始文档 | blame | 历史
Document/ESWIN_EAS_Bonder_Inline_Mapping_Address_v1.1.5(4).xlsx 补丁 | 查看 | 原始文档 | blame | 历史
Document/ESWIN_EAS_Bonder_Inline_Mapping_Address_v1.1.5(5).xlsx 补丁 | 查看 | 原始文档 | blame | 历史
Document/ESWIN_EAS_Bonder_Inline_Mapping_Address_v1.1.5.xlsx 补丁 | 查看 | 原始文档 | blame | 历史
Document/ESWIN_EAS_Bonder_Inline_Mapping_Address_v1.1.7(3).xlsx 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CAttributeVector.cpp 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CBakeCooling.cpp 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CBonder.cpp 77 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CBonder.h 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CEFEM.cpp 111 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CEqWriteStep.cpp 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CEqWriteStep.h 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CEquipment.cpp 341 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CEquipment.h 26 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CGlass.cpp 19 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CGlass.h 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CJobDataS.cpp 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CJobDataS.h 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CLoadPort.cpp 117 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CLoadPort.h 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CMaster.cpp 185 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CMaster.h 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CMeasurement.cpp 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CPageGraph2.cpp 25 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CReadStep.cpp 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CReadStep.h 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CRobotCmdTestDlg.cpp 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CRobotTask.cpp 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CVacuumBake.cpp 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CWriteStep.cpp 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CWriteStep.h 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/Common.h 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/RecipeDeviceBindDlg.cpp 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/RecipeDeviceBindDlg.h 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/Servo.rc 补丁 | 查看 | 原始文档 | 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 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/ServoDlg.cpp 28 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/resource.h 补丁 | 查看 | 原始文档 | blame | 历史
Document/ESWIN_EAS_Bonder_Inline_Mapping_Address_v1.1.1.xlsx
Binary files differ
Document/ESWIN_EAS_Bonder_Inline_Mapping_Address_v1.1.2.xlsx
Binary files differ
Document/ESWIN_EAS_Bonder_Inline_Mapping_Address_v1.1.4(1).xlsx
Binary files differ
Document/ESWIN_EAS_Bonder_Inline_Mapping_Address_v1.1.5(4).xlsx
Binary files differ
Document/ESWIN_EAS_Bonder_Inline_Mapping_Address_v1.1.5(5).xlsx
Binary files differ
Document/ESWIN_EAS_Bonder_Inline_Mapping_Address_v1.1.5.xlsx
Binary files differ
Document/ESWIN_EAS_Bonder_Inline_Mapping_Address_v1.1.7(3).xlsx
Binary files differ
SourceCode/Bond/Servo/CAttributeVector.cpp
@@ -19,9 +19,18 @@
    void CAttributeVector::addAttribute(CAttribute* pAttribute, BOOL bReplace/* = FALSE*/)
    {
        if (!pAttribute) {
            return;
        }
        const std::string& name = pAttribute->getName();
        if (name.empty()) {
            return;
        }
        if (bReplace) {
            for (auto it = m_attributes.begin(); it != m_attributes.end(); ) {
                if ((*it)->getName().compare(pAttribute->getName()) == 0) {
                if (name.compare((*it)->getName()) == 0) {
                    delete (*it);
                    it = m_attributes.erase(it);
                }
SourceCode/Bond/Servo/CBakeCooling.cpp
@@ -239,7 +239,7 @@
        {
            // Received Job Report Upstream #1~9
            char szBuffer[256];
            for (int i = 0; i < 9; i++) {
            for (int i = 0; i < 1; i++) {
                CEqReadStep* pStep = new CEqReadStep(0x10c90 + 320 * i, 320 * 2,
                    [&](void* pFrom, int code, const char* pszData, size_t size) -> int {
                        if (code == ROK && pszData != nullptr && size > 0) {
@@ -263,7 +263,7 @@
        {
            // Sent Out Job Report Downstream #1~9
            char szBuffer[256];
            for (int i = 0; i < 9; i++) {
            for (int i = 0; i < 1; i++) {
                CEqReadStep* pStep = new CEqReadStep(0x10000 + 320 * i, 320 * 2,
                    [&](void* pFrom, int code, const char* pszData, size_t size) -> int {
                        if (code == ROK && pszData != nullptr && size > 0) {
@@ -287,7 +287,7 @@
        {
            // Fetched Out Job Report #1~15
            char szBuffer[256];
            for (int i = 0; i < 15; i++) {
            for (int i = 0; i < 1; i++) {
                CEqReadStep* pStep = new CEqReadStep(0x11c31 + 18 * i, 18 * 2,
                    [&](void* pFrom, int code, const char* pszData, size_t size) -> int {
                        if (code == ROK && pszData != nullptr && size > 0) {
@@ -311,7 +311,7 @@
        {
            // Stored Job Report #1~15
            char szBuffer[256];
            for (int i = 0; i < 15; i++) {
            for (int i = 0; i < 1; i++) {
                CEqReadStep* pStep = new CEqReadStep(0x11b23 + 18 * i, 18 * 2,
                    [&](void* pFrom, int code, const char* pszData, size_t size) -> int {
                        if (code == ROK && pszData != nullptr && size > 0) {
SourceCode/Bond/Servo/CBonder.cpp
@@ -244,7 +244,7 @@
        {
            // Received Job Report Upstream #1~9
            char szBuffer[256];
            for (int i = 0; i < 9; i++) {
            for (int i = 0; i < 1; i++) {
                CEqReadStep* pStep = new CEqReadStep((m_nIndex == 0 ? 0x8c90 : 0xcc90) + 320 * i, 320 * 2,
                    [&](void* pFrom, int code, const char* pszData, size_t size) -> int {
                        if (code == ROK && pszData != nullptr && size > 0) {
@@ -267,7 +267,7 @@
        {
            // Sent Out Job Report Downstream #1~9
            char szBuffer[256];
            for (int i = 0; i < 9; i++) {
            for (int i = 0; i < 1; i++) {
                CEqReadStep* pStep = new CEqReadStep((m_nIndex == 0 ? 0x8000 : 0xc000) + 320 * i, 320 * 2,
                    [&](void* pFrom, int code, const char* pszData, size_t size) -> int {
                        if (code == ROK && pszData != nullptr && size > 0) {
@@ -291,7 +291,7 @@
        {
            // Fetched Out Job Report #1~15
            char szBuffer[256];
            for (int i = 0; i < 15; i++) {
            for (int i = 0; i < 1; i++) {
                CEqReadStep* pStep = new CEqReadStep((m_nIndex == 0 ? 0x9c31 : 0xdc31) + 18 * i, 18 * 2,
                    [&](void* pFrom, int code, const char* pszData, size_t size) -> int {
                        if (code == ROK && pszData != nullptr && size > 0) {
@@ -315,7 +315,7 @@
        {
            // Stored Job Report #1~15
            char szBuffer[256];
            for (int i = 0; i < 15; i++) {
            for (int i = 0; i < 1; i++) {
                CEqReadStep* pStep = new CEqReadStep((m_nIndex == 0 ? 0x9b23 : 0xdb23) + 18 * i, 18 * 2,
                    [&](void* pFrom, int code, const char* pszData, size_t size) -> int {
                        if (code == ROK && pszData != nullptr && size > 0) {
@@ -333,6 +333,18 @@
                if (addStep(STEP_ID_STORE_JOB_REPORT1 + i, pStep) != 0) {
                    delete pStep;
                }
            }
        }
        {
            // Indexer Operation Mode Change
            CEqWriteStep* pStep = new CEqWriteStep();
            pStep->setName(STEP_EQ_IN_OP_MODE_CHANGE);
            pStep->setWriteSignalDev(0x370);
            pStep->setDataDev(0x923);
            pStep->setRetDataDev(0xa00e, 2);
            if (addStep(STEP_ID_IN_OP_CMD_REPLY, pStep) != 0) {
                delete pStep;
            }
        }
@@ -429,32 +441,41 @@
        CEquipment::onProcessData(pProcessData);
        // æ£€æŸ¥æ•°æ®ï¼Œå½“前两片玻璃,一片为G1, ä¸€ç‰‡ä¸ºG2, ä¸”pProcessData中的id能匹配G1或G2
        Lock();
        CGlass* pGlass2 = getGlassFromSlot(1);
        CGlass* pGlass1 = getGlassFromSlot(2);
        if (pGlass1 == nullptr || pGlass2 == nullptr) {
            LOGE("<CBonder-%s>onProcessData,错误!不满足两片玻璃且分别为G1与G2的条件,请检查数据是否正确!", m_strName.c_str());
            Unlock();
            return -1;
        }
        if (pGlass1->getBuddy() != nullptr) {
            LOGE("<CBonder-%s>onProcessData,错误!玻璃较早前已被绑定,请检查数据是否正确!", m_strName.c_str());
            Unlock();
            return -1;
        }
        return 0;
    }
        if (pGlass1->getType() != MaterialsType::G1 || pGlass2->getType() != MaterialsType::G2) {
            LOGE("<CBonder-%s>onProcessData,错误!两片玻璃未匹配,必须分别为G1和G2类型,请检查数据是否正确!", m_strName.c_str());
            Unlock();
            return -1;
        }
    int CBonder::onProcessStateChanged(PROCESS_STATE state)
    {
        CEquipment::onProcessStateChanged(state);
        pGlass1->setBuddy(pGlass2);
        getSlot(0)->setContext(nullptr);
        LOGE("<CBonder-%s>onProcessData,%s和%s已贴合!", m_strName.c_str(),
            pGlass1->getID().c_str(), pGlass2->getID().c_str());
        Unlock();
        if (state == PROCESS_STATE::Complete) {
            // æ£€æŸ¥æ•°æ®ï¼Œå½“前两片玻璃,一片为G1, ä¸€ç‰‡ä¸ºG2, ä¸”pProcessData中的id能匹配G1或G2
            Lock();
            CGlass* pGlass2 = getGlassFromSlot(1);
            CGlass* pGlass1 = getGlassFromSlot(2);
            if (pGlass1 == nullptr || pGlass2 == nullptr) {
                LOGE("<CBonder-%s>onProcessData,错误!不满足两片玻璃且分别为G1与G2的条件,请检查数据是否正确!", m_strName.c_str());
                Unlock();
                return -1;
            }
            if (pGlass1->getBuddy() != nullptr) {
                LOGE("<CBonder-%s>onProcessData,错误!玻璃较早前已被绑定,请检查数据是否正确!", m_strName.c_str());
                Unlock();
                return -1;
            }
            if (pGlass1->getType() != MaterialsType::G1 || pGlass2->getType() != MaterialsType::G2) {
                LOGE("<CBonder-%s>onProcessData,错误!两片玻璃未匹配,必须分别为G1和G2类型,请检查数据是否正确!", m_strName.c_str());
                Unlock();
                return -1;
            }
            pGlass1->setBuddy(pGlass2);
            getSlot(0)->setContext(nullptr);
            LOGE("<CBonder-%s>onProcessStateChanged,%s和%s已贴合!", m_strName.c_str(),
                pGlass1->getID().c_str(), pGlass2->getID().c_str());
            Unlock();
        }
        return 0;
    }
SourceCode/Bond/Servo/CBonder.h
@@ -22,6 +22,7 @@
        virtual void getAttributeVector(CAttributeVector& attrubutes);
        virtual int recvIntent(CPin* pPin, CIntent* pIntent);
        virtual int onProcessData(CProcessData* pProcessData);
        virtual int onProcessStateChanged(PROCESS_STATE state);
        virtual int getIndexerOperationModeBaseValue();
    public:
SourceCode/Bond/Servo/CEFEM.cpp
@@ -22,7 +22,7 @@
        m_pPort[3] = nullptr;
        m_pAligner = nullptr;
        m_pFliper = nullptr;
        m_robotData.status = ROBOT_STATUS::Idle;
        m_robotData.status = ROBOT_STATUS::Setup;
        m_robotData.position = ROBOT_POSITION::Port1;
        m_robotData.armState[0] = FALSE;
        m_robotData.armState[1] = FALSE;
@@ -531,25 +531,49 @@
            }
        }
        // ä½¿ç”¨CEqReadStep替换CEqJobEventStep
        {
            // Received Job Report Upstream#1~9
            // Received Job Report Upstream #1~9
            char szBuffer[256];
            for (int i = 0; i < 9; i++) {
            for (int i = 0; i < 8; i++) {
                CEqReadStep* pStep = new CEqReadStep(0x4c90 + 320 * i, 320 * 2,
                    [&](void* pFrom, int code, const char* pszData, size_t size) -> int {
                        if (code == ROK && pszData != nullptr && size > 0) {
                            int port = (int)(__int64)((CEqReadStep*)pFrom)->getProp("Port");
                            if (port > 0) {
                                decodeFetchedOutJobReport((CStep*)pFrom, port, pszData, size);
                                decodeReceivedJobReport((CStep*)pFrom, port, pszData, size);
                            }
                        }
                        return -1;
                    });
                sprintf_s(szBuffer, "%s%d", STEP_EQ_RECEIVED_JOBn, i + 1);
                sprintf_s(szBuffer, "%s%d", STEP_EQ_RECEIVED_JOB_UPSn, i + 1);
                pStep->setName(szBuffer);
                pStep->setProp("Upstream", (void*)(__int64)(i + 1));
                pStep->setProp("Port", (void*)(__int64)(i + 1));
                pStep->setWriteSignalDev(0x0 + i);
                if (addStep(STEP_ID_FETCHED_OUT_JOB_REPORT1 + i, pStep) != 0) {
                if (addStep(STEP_ID_RECIVE_JOB_UPS1 + i, pStep) != 0) {
                    delete pStep;
                }
            }
        }
        {
            // Sent Out Job Report Downstream #1~9
            char szBuffer[256];
            for (int i = 0; i < 8; i++) {
                CEqReadStep* pStep = new CEqReadStep(0x4000 + 320 * i, 320 * 2,
                    [&](void* pFrom, int code, const char* pszData, size_t size) -> int {
                        if (code == ROK && pszData != nullptr && size > 0) {
                            int port = (int)(__int64)((CEqReadStep*)pFrom)->getProp("Port");
                            if (port > 0) {
                                decodeSentOutJobReport((CStep*)pFrom, port, pszData, size);
                            }
                        }
                        return -1;
                    });
                sprintf_s(szBuffer, "%s%d", STEP_EQ_SENT_OUT_JOB_DOWNSn, i + 1);
                pStep->setName(szBuffer);
                pStep->setProp("Port", (void*)(__int64)(i + 1));
                pStep->setWriteSignalDev(0x00a + i);
                if (addStep(STEP_ID_SENT_OUT_JOB_DOWNS1 + i, pStep) != 0) {
                    delete pStep;
                }
            }
@@ -558,7 +582,7 @@
        {
            // Fetched Out Job Report #1~15
            char szBuffer[256];
            for (int i = 0; i < 15; i++) {
            for (int i = 0; i < 8; i++) {
                CEqReadStep* pStep = new CEqReadStep(0x5c31 + 18 * i, 18 * 2,
                    [&](void* pFrom, int code, const char* pszData, size_t size) -> int {
                        if (code == ROK && pszData != nullptr && size > 0) {
@@ -569,7 +593,7 @@
                        }
                        return -1;
                    });
                sprintf_s(szBuffer, "%s%d", STEP_EQ_FETCHED_OUT_JOBn, i+1);
                sprintf_s(szBuffer, "%s%d", STEP_EQ_FETCHED_OUT_JOBn, i + 1);
                pStep->setName(szBuffer);
                pStep->setProp("Port", (void*)(__int64)(i + 1));
                pStep->setWriteSignalDev(0x023 + i);
@@ -580,9 +604,9 @@
        }
        {
            // Store Job Report #1~15
            // Stored Job Report #1~15
            char szBuffer[256];
            for (int i = 0; i < 15; i++) {
            for (int i = 0; i < 8; i++) {
                CEqReadStep* pStep = new CEqReadStep(0x5b23 + 18 * i, 18 * 2,
                    [&](void* pFrom, int code, const char* pszData, size_t size) -> int {
                        if (code == ROK && pszData != nullptr && size > 0) {
@@ -602,6 +626,7 @@
                }
            }
        }
        {
            // Dispatching Mode Change Command
@@ -628,9 +653,10 @@
        {
            // Indexer Operation Mode Change
            CEqWriteStep* pStep = new CEqWriteStep();
            pStep->setName(STEP_EFEM_IN_OP_MODE_CHANGE);
            pStep->setName(STEP_EQ_IN_OP_MODE_CHANGE);
            pStep->setWriteSignalDev(0x070);
            pStep->setDataDev(0x023);
            pStep->setRetDataDev(0x600e, 2);
            if (addStep(STEP_ID_IN_OP_CMD_REPLY, pStep) != 0) {
                delete pStep;
            }
@@ -658,7 +684,7 @@
            CEqReadStep* pStep = new CEqReadStep(0x6301, 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;
                });
@@ -666,6 +692,35 @@
            pStep->setProp("Port", (void*)1);
            pStep->setWriteSignalDev(0x04d);
            if (addStep(STEP_ID_FAC_DATA_REPORT, pStep) != 0) {
                delete pStep;
            }
        }
        {
            // JOB Data Request
            CEqReadStep* pStep = new CEqReadStep(0x617d, 2 * 2,
                [&](void* pFrom, int code, const char* pszData, size_t size) -> int {
                    if (code == ROK && pszData != nullptr && size > 0) {
                        decodeJobDataRequest((CStep*)pFrom, pszData, size);
                        // efme, èŽ·å–æ•°æ®åŽè¿”å›ž
                        // Cassette Sequence No        1W
                        // Job Sequence No            1W
                        // Job DataS                256W
                        char szBuffer[1024] = { 0 };
                        CJobDataS* pJobDataS = m_pPort[3]->getJobDataSWithCassette(4001, 1);
                        if (pJobDataS != nullptr) {
                            int size = pJobDataS->serialize(szBuffer, 1024);
                            ((CEqReadStep*)pFrom)->setReturnData(szBuffer, size);
                        }
                    }
                    return -1;
                });
            pStep->setName(STEP_EFEM_PANEL_DATA_REQUEST);
            pStep->setProp("Port", (void*)1);
            pStep->setWriteSignalDev(0x35);
            pStep->setReturnDev(0x5EA);
            if (addStep(STEP_ID_JOB_DATA_REQUEST, pStep) != 0) {
                delete pStep;
            }
        }
@@ -742,28 +797,26 @@
    int CEFEM::onReceivedJob(int port, CJobDataS* pJobDataS)
    {
        m_pPort[0]->onReceivedJob(port, pJobDataS);
        m_pPort[1]->onReceivedJob(port, pJobDataS);
        m_pPort[2]->onReceivedJob(port, pJobDataS);
        m_pPort[3]->onReceivedJob(port, pJobDataS);
        m_pArmTray[0]->onReceivedJob(port, pJobDataS);
        m_pArmTray[1]->onReceivedJob(port, pJobDataS);
        m_pAligner->onReceivedJob(port, pJobDataS);
        m_pFliper->onReceivedJob(port, pJobDataS);
        // è½¬å‘到子单元设备
        CEquipment* pEqs[] = { m_pPort[0], m_pPort[1], m_pPort[2], m_pPort[3], m_pArmTray[0], m_pArmTray[1],
            m_pAligner, m_pFliper };
        if (1 <= port && port <= 8) {
            pEqs[port - 1]->onReceivedJob(port, pJobDataS);
        }
        return 0;
    }
    int CEFEM::onSentOutJob(int port, CJobDataS* pJobDataS)
    {
        m_pPort[0]->onSentOutJob(port, pJobDataS);
        m_pPort[1]->onSentOutJob(port, pJobDataS);
        m_pPort[2]->onSentOutJob(port, pJobDataS);
        m_pPort[3]->onSentOutJob(port, pJobDataS);
        m_pArmTray[0]->onSentOutJob(port, pJobDataS);
        m_pArmTray[1]->onSentOutJob(port, pJobDataS);
        m_pAligner->onSentOutJob(port, pJobDataS);
        m_pFliper->onSentOutJob(port, pJobDataS);
        // è½¬å‘到子单元设备
        CEquipment* pEqs[] = { m_pPort[0], m_pPort[1], m_pPort[2], m_pPort[3], m_pArmTray[0], m_pArmTray[1],
            m_pAligner, m_pFliper };
        if (1 <= port && port <= 8) {
            pEqs[port - 1]->onSentOutJob(port, pJobDataS);
        }
        return 0;
    }
SourceCode/Bond/Servo/CEqWriteStep.cpp
@@ -64,4 +64,13 @@
        return 0;
    }
    int CEqWriteStep::onReadRetDataError()
    {
        if (m_onWritedBlock != nullptr) {
            m_onWritedBlock(WREAD_RET_ERR);
        }
        return 0;
    }
}
SourceCode/Bond/Servo/CEqWriteStep.h
@@ -5,6 +5,7 @@
#define WOK                0
#define WTIMEOUT        -1
#define WREAD_RET_ERR    -2
namespace SERVO {
    typedef std::function<int(int code)> ONWRITED;
@@ -23,6 +24,7 @@
        int writeDataEx(const char* pszData, int size, ONWRITED onWritedBlock = nullptr);
        virtual int onComplete();
        virtual int onTimeout();
        virtual int onReadRetDataError();
    private:
        int m_nDataDev;
SourceCode/Bond/Servo/CEquipment.cpp
@@ -39,6 +39,7 @@
        m_pCclink = nullptr;
        m_nBaseAlarmId = 0;
        m_pArm = nullptr;
        m_processState = PROCESS_STATE::Ready;
        InitializeCriticalSection(&m_criticalSection);
    }
@@ -142,6 +143,16 @@
        pStep->setCcLink(m_pCclink);
        m_mapStep[addr] = pStep;
        return 0;
    }
    void CEquipment::setProcessState(PROCESS_STATE state)
    {
        m_processState = state;
        onProcessStateChanged(m_processState);
        if (m_listener.onProcessStateChanged != nullptr) {
            m_listener.onProcessStateChanged(this, m_processState);
        }
    }
    void CEquipment::init()
@@ -394,7 +405,9 @@
            m_bLinkSignal[i][SIGNAL_SEND_ABLE] = isBitOn(pszData, size, index + 3);
            index += 0x40;
        }         
        if(m_bLinkSignal[0][SIGNAL_SEND_ABLE]) {
            onSendAble();
        }
        // å…¶å®ƒä¿¡å·åŠå“åº”
        index = 0x540;
@@ -565,7 +578,18 @@
        // robot cmd reply
        CHECK_WRITE_STEP_SIGNAL(STEP_ID_ROBOT_CMD_REPLY, pszData, size);
        // Indexer Operation Mode Change
        CHECK_WRITE_STEP_SIGNAL(STEP_ID_IN_OP_CMD_REPLY, pszData, size);
        // Panel Data Report
        CHECK_WRITE_STEP_SIGNAL(STEP_ID_PANEL_DATA_REPORT, pszData, size);
        // Panel Data Request
        CHECK_WRITE_STEP_SIGNAL(STEP_ID_PANEL_DATA_REQUEST, pszData, size);
        // Job Data Request
        CHECK_READ_STEP_SIGNAL(STEP_ID_JOB_DATA_REQUEST, pszData, size);
    }
    BOOL CEquipment::isBitOn(const char* pszData, size_t size, int index)
@@ -778,7 +802,7 @@
        CGlass* pContext = nullptr;
        for (int i = 0; i < SLOT_MAX; i++) {
            CGlass* pGlass = (CGlass*)m_slot[i].getContext();
            if (pGlass != nullptr && compareJobDataB(pJobDataB, pGlass->getJobDataB())) {
            if (pGlass != nullptr && compareJobData(pJobDataB, pGlass->getJobDataS())) {
                pContext = pGlass;
                if (pGlass != nullptr) pGlass->addRef();
                m_slot[i].setContext(nullptr);
@@ -794,6 +818,11 @@
        ((CArm*)m_pArm)->tempStore(pContext);
        pContext->release();
        Unlock();
        if (m_processState != PROCESS_STATE::Ready) {
            setProcessState(PROCESS_STATE::Ready);
        }
        if (m_listener.onDataChanged != nullptr) {
            m_listener.onDataChanged(this, EDCC_FETCHOUT_JOB);
@@ -821,22 +850,9 @@
        pGlass->release();                // tempFetchOut需要调用一次release
        Unlock();
        // å¦‚果此玻璃已经贴合,贴合的玻璃也要从加入到列表中
        /*
        CGlass* pBuddy = pGlass->getBuddy();
        if (pBuddy != nullptr) {
            Lock();
            pBuddy->addPath(m_nID, 0);
            if (putSlot % 2 == 0) {
                m_slot[putSlot - 2].setContext(pBuddy);
            }
            else {
                m_slot[putSlot].setContext(pBuddy);
            }
            Unlock();
        if (m_processState != PROCESS_STATE::Processing) {
            setProcessState(PROCESS_STATE::Processing);
        }
        */
        if (m_listener.onDataChanged != nullptr) {
            m_listener.onDataChanged(this, EDCC_STORED_JOB);
@@ -866,6 +882,61 @@
                return pGlass;
            }
        }
        return nullptr;
    }
    CGlass* CEquipment::getGlassFromSlot(int slotNo)
    {
        CSlot* pSlot = nullptr;
        for (int i = 0; i < SLOT_MAX; i++) {
            if (!m_slot[i].isEnable()) continue;
            if (m_slot[i].getNo() != slotNo) continue;
            pSlot = &m_slot[i];
            break;
        }
        if (pSlot != nullptr) {
            return (CGlass*)pSlot->getContext();
        }
        return nullptr;
    }
    CGlass* CEquipment::getGlassWithCassette(int cassetteSequenceNo, int jobSequenceNo)
    {
        CSlot* pSlot = nullptr;
        for (int i = 0; i < SLOT_MAX; i++) {
            if (!m_slot[i].isEnable()) continue;
            CGlass* pGlass = (CGlass*)m_slot[i].getContext();
            if (pGlass == nullptr) continue;
            CJobDataS* pJobDataS = pGlass->getJobDataS();
            ASSERT(pJobDataS);
            if (pJobDataS->getCassetteSequenceNo() == cassetteSequenceNo
                && pJobDataS->getJobSequenceNo() == jobSequenceNo) {
                return pGlass;
            }
        }
        return nullptr;
    }
    CJobDataS* CEquipment::getJobDataSWithCassette(int cassetteSequenceNo, int jobSequenceNo)
    {
        CSlot* pSlot = nullptr;
        for (int i = 0; i < SLOT_MAX; i++) {
            if (!m_slot[i].isEnable()) continue;
            CGlass* pGlass = (CGlass*)m_slot[i].getContext();
            if (pGlass == nullptr) continue;
            CJobDataS* pJobDataS = pGlass->getJobDataS();
            ASSERT(pJobDataS);
            if (pJobDataS->getCassetteSequenceNo() == cassetteSequenceNo
                && pJobDataS->getJobSequenceNo() == jobSequenceNo) {
                return pJobDataS;
            }
        }
        return nullptr;
    }
@@ -1007,30 +1078,35 @@
        return 0;
    }
    int CEquipment::indexerOperationModeChange(IDNEXER_OPERATION_MODE mode, ONWRITED onWritedBlock/* = nullptr*/)
    int CEquipment::indexerOperationModeChange(IDNEXER_OPERATION_MODE mode, ONWRITEDRET onWritedRetBlock)
    {
        SERVO::CEqWriteStep* pStep = (SERVO::CEqWriteStep*)getStepWithName(STEP_EFEM_IN_OP_MODE_CHANGE);
        SERVO::CEqWriteStep* pStep = (SERVO::CEqWriteStep*)getStepWithName(STEP_EQ_IN_OP_MODE_CHANGE);
        if (pStep == nullptr) {
            return -1;
        }
        unsigned short operationMode = (unsigned short)((unsigned short)mode + getIndexerOperationModeBaseValue());
        LOGI("<CEquipment-%s>准备设置indexerOperationMode<%d>", m_strName.c_str(), (int)mode);
        if (onWritedBlock != nullptr) {
            pStep->writeShort(operationMode, onWritedBlock);
        }
        else {
            pStep->writeShort(operationMode, [&, mode](int code) -> int {
                if (code == WOK) {
                    LOGI("<CEquipment-%s>设置indexerOperationMode成功.", m_strName.c_str());
                }
                else {
                    LOGI("<CEquipment-%s>设置indexerOperationMode失败,code:%d", m_strName.c_str(), code);
                }
        pStep->writeShort(operationMode, [&, pStep, mode, onWritedRetBlock](int code) -> int {
            int retCode = 0;
            if (code == WOK) {
                LOGI("<CEquipment-%s>设置indexerOperationMode成功.", m_strName.c_str());
                const char* pszRetData = nullptr;
                pStep->getReturnData(pszRetData);
                ASSERT(pszRetData);
                retCode = (unsigned int)CToolUnits::toInt16(pszRetData);
                LOGI("<CEquipment-%s>返回值: %d", m_strName.c_str(), retCode);
            }
            else {
                LOGI("<CEquipment-%s>设置indexerOperationMode失败,code:%d", m_strName.c_str(), code);
            }
                return 0;
                });
        }
            if (onWritedRetBlock != nullptr) {
                onWritedRetBlock(code, retCode);
            }
            return 0;
        });
        return 0;
    }
@@ -1210,23 +1286,6 @@
        return &m_slot[index];
    }
    CGlass* CEquipment::getGlassFromSlot(int slotNo)
    {
        CSlot* pSlot = nullptr;
        for (int i = 0; i < SLOT_MAX; i++) {
            if (!m_slot[i].isEnable()) continue;
            if (m_slot[i].getNo() != slotNo) continue;
            pSlot = &m_slot[i];
            break;
        }
        if (pSlot != nullptr) {
            return (CGlass*)pSlot->getContext();
        }
        return nullptr;
    }
    CGlass* CEquipment::getAnyGlass()
    {
        CSlot* pSlot = nullptr;
@@ -1313,8 +1372,6 @@
    int CEquipment::onReceivedJob(int port, CJobDataS* pJobDataS)
    {
        LOGI("<CEquipment-%s>onReceivedJob.", m_strName.c_str());
        addJobDataS(pJobDataS);
        return 0;
    }
@@ -1331,7 +1388,7 @@
        pStep->addAttributeVector(attrubutes);
        onReceivedJob(port, &jobDataS);
        onSentOutJob(port, &jobDataS);
        return nRet;
    }
@@ -1340,13 +1397,16 @@
    {
        LOGI("<CEquipment-%s>onSentOutJob.", m_strName.c_str());
        int count = removeJobDataS(pJobDataS->getCassetteSequenceNo(), pJobDataS->getJobSequenceNo());
        if (count == 1) {
            LOGI("<CEquipment-%s>onSentOutJob,删除数据 %d æ¡", m_strName.c_str(), count);
        // å¯ä»¥åœ¨æ­¤æ›´æ–°JobDataS数据了
        CGlass* pGlass = getGlass(pJobDataS->getGlass1Id().c_str());
        if (pGlass == nullptr) {
            LOGE("<CEquipment-%s>onSentOutJob,没有找到对应的Glass(CassetteSequenceNo:%d, JobSequenceNo:%d, ID=%s),请检查数据,注意风险。",
                m_strName.c_str(), pJobDataS->getCassetteSequenceNo(), pJobDataS->getJobSequenceNo(),
                pJobDataS->getGlass1Id().c_str());
            return -1;
        }
        else {
            LOGE("<CEquipment-%s>onSentOutJob,删除数据 %d æ¡ï¼Œæ³¨æ„æŽ’查风险", m_strName.c_str(), count);
        }
        pGlass->updateJobDataS(pJobDataS);
        return 0;
    }
@@ -1534,15 +1594,49 @@
        return 0;
    }
    int CEquipment::decodeJobDataRequest(CStep* pStep, const char* pszData, size_t size)
    {
        int index = 0;
        short cassetteSequenceNo, jobSequenceNo;
        memcpy(&cassetteSequenceNo, &pszData[index], sizeof(short));
        index += sizeof(short);
        memcpy(&jobSequenceNo, &pszData[index], sizeof(short));
        index += sizeof(short);
        cassetteSequenceNo = 4000;
        jobSequenceNo = 1;
        // ç¼“å­˜Attribute,用于调试时显示信息
        unsigned int weight = 201;
        pStep->addAttribute(new CAttribute("CassetteSequenceNo",
            (std::to_string(cassetteSequenceNo)).c_str(), "", weight++));
        pStep->addAttribute(new CAttribute("JobSequenceNo",
            (std::to_string(jobSequenceNo)).c_str(), "", weight++));
        return 0;
    }
    int CEquipment::onPreStoredJob(int port, CJobDataB* pJobDataB, short& putSlot)
    {
        LOGI("<CEquipment-%s>onPreStoredJob:port:%d|GlassId:%s",
            m_strName.c_str(), port, pJobDataB->getGlassId().c_str());
        CJobDataS* pJobDataS = getJobDataS(pJobDataB->getCassetteSequenceNo(), pJobDataB->getJobSequenceNo());
        if (pJobDataS == nullptr) {
            LOGE("<CFliper-%s>onPreFetchedOutJob,找不到对应的JobDataS(CassetteSequenceNo:%d, JobSequenceNo:%d), æ³¨æ„æŽ’查风险!", m_strName.c_str(),
        // å½“前要存片,之前肯定有拔片,因此片子在Arm那里
        CGlass* pGlass = ((CArm*)m_pArm)->getGlassFromSlot(1);
        if (pGlass == nullptr) {
            LOGE("<CFliper-%s>onPreStoredJob,缓存中没有找到对应的Glass(CassetteSequenceNo:%d, JobSequenceNo:%d),请检查数据,注意风险。", m_strName.c_str(),
                pJobDataB->getCassetteSequenceNo(), pJobDataB->getJobSequenceNo());
            return FALSE;
        }
        CJobDataS* pJobDataS = pGlass->getJobDataS();
        ASSERT(pJobDataS);
        if (!compareJobData(pJobDataB, pJobDataS)) {
            LOGE("<CFliper-%s>onPreFetchedOutJob,JobData数据不匹配(JobDataB(%d, %d),JobDataS(%d, %d)), æ³¨æ„æŽ’查风险!", m_strName.c_str(),
                pJobDataB->getCassetteSequenceNo(), pJobDataB->getJobSequenceNo(),
                pJobDataS->getCassetteSequenceNo(), pJobDataS->getJobSequenceNo());
            return FALSE;
        }
@@ -1578,7 +1672,6 @@
        short putSlot = 0;
        BOOL bCheck = onPreStoredJob(port, pJobDataB, putSlot);
        if (bCheck) {
            addJobDataB(pJobDataB);
            return storedJob(pJobDataB, putSlot);
        }
@@ -1595,109 +1688,39 @@
        return 0;
    }
    /*
     * å½“从CC-Link检测到设备Send Able为On时调用此函数
     * å¯èƒ½ä¼šå¤šæ¬¡é‡å¤è°ƒç”¨(根据扫描频率), æ³¨æ„é˜²å‘†
     */
    int CEquipment::onSendAble()
    {
        LOGI("<CEquipment-%s>onSendAble.", m_strName.c_str());
        if (m_processState != PROCESS_STATE::Complete) {
            setProcessState(PROCESS_STATE::Complete);
        }
        return 0;
    }
    int CEquipment::onProcessStateChanged(PROCESS_STATE state)
    {
        return 0;
    }
    int CEquipment::getIndexerOperationModeBaseValue()
    {
        return 0;
    }
    int CEquipment::addJobDataB(CJobDataB* pJobDataB)
    BOOL CEquipment::compareJobData(CJobDataB* pJobDataB, CJobDataS* pJobDataS)
    {
        // æ·»åŠ ä¹‹å‰å…ˆåˆ é™¤æ—§çš„ï¼Œä»¥å…æ•°æ®é‡å¤
        Lock();
        int count = removeJobDataB(pJobDataB->getCassetteSequenceNo(), pJobDataB->getJobSequenceNo());
        if (count > 0) {
            LOGE("<CEquipment-%s>addJobDataB,删除重复数据 %d æ¡ï¼Œæ³¨æ„æŽ’查风险", m_strName.c_str(), count);
        }
        ASSERT(pJobDataB);
        ASSERT(pJobDataS);
        m_listJobDataB.push_back(std::move(*pJobDataB));
        Unlock();
        return (int)m_listJobDataB.size();
    }
    int CEquipment::removeJobDataB(int nCassetteSequenceNo, int nJobSequenceNo)
    {
        int count = 0;
        for (auto it = m_listJobDataB.begin(); it != m_listJobDataB.end(); ) {
            if ((*it).getCassetteSequenceNo() == nCassetteSequenceNo
                && (*it).getJobSequenceNo() == nJobSequenceNo) {
                it = m_listJobDataB.erase(it);
                count++;
            }
            else {
                ++it;
            }
        }
        return count;
    }
    CJobDataB* CEquipment::getJobDataB(int nCassetteSequenceNo, int nJobSequenceNo)
    {
        for (auto& item : m_listJobDataB) {
            if (item.getCassetteSequenceNo() == nCassetteSequenceNo
                && item.getJobSequenceNo() == nJobSequenceNo) {
                return &item;
            }
        }
        return nullptr;
    }
    int CEquipment::addJobDataS(CJobDataS* pJobDataS)
    {
        // æ·»åŠ ä¹‹å‰å…ˆåˆ é™¤æ—§çš„ï¼Œä»¥å…æ•°æ®é‡å¤
        Lock();
        int count = removeJobDataS(pJobDataS->getCassetteSequenceNo(), pJobDataS->getJobSequenceNo());
        if (count > 0) {
            LOGE("<CEquipment-%s>addJobDataS,删除重复数据 %d æ¡ï¼Œæ³¨æ„æŽ’查风险", m_strName.c_str(), count);
        }
        m_listJobDataS.push_back(std::move(*pJobDataS));
        Unlock();
        return (int)m_listJobDataB.size();
    }
    int CEquipment::removeJobDataS(int nCassetteSequenceNo, int nJobSequenceNo)
    {
        int count = 0;
        Lock();
        for (auto it = m_listJobDataS.begin(); it != m_listJobDataS.end(); ) {
            if ((*it).getCassetteSequenceNo() == nCassetteSequenceNo
                && (*it).getJobSequenceNo() == nJobSequenceNo) {
                it = m_listJobDataS.erase(it);
                count++;
            }
            else {
                ++it;
            }
        }
        Unlock();
        return count;
    }
    CJobDataS* CEquipment::getJobDataS(int nCassetteSequenceNo, int nJobSequenceNo)
    {
        for (auto& item : m_listJobDataS) {
            if (item.getCassetteSequenceNo() == nCassetteSequenceNo
                && item.getJobSequenceNo() == nJobSequenceNo) {
                return &item;
            }
        }
        return nullptr;
    }
    BOOL CEquipment::compareJobDataB(CJobDataB* pJobDataB1, CJobDataB* pJobDataB2)
    {
        ASSERT(pJobDataB1);
        ASSERT(pJobDataB2);
        if (pJobDataB1->getCassetteSequenceNo() != pJobDataB2->getCassetteSequenceNo())
        if (pJobDataB->getCassetteSequenceNo() != pJobDataS->getCassetteSequenceNo())
            return FALSE;
        if (pJobDataB1->getJobSequenceNo() != pJobDataB2->getJobSequenceNo())
        if (pJobDataB->getJobSequenceNo() != pJobDataS->getJobSequenceNo())
            return FALSE;
        return TRUE;
SourceCode/Bond/Servo/CEquipment.h
@@ -43,6 +43,7 @@
#define SIGNAL_UPSTREAM_TROUBLE    1
#define SIGNAL_INTERLOCK        2
#define SIGNAL_SEND_ABLE        3
    typedef std::function<void(int writeCode, int retCode)> ONWRITEDRET;
    typedef std::function<void(void* pEiuipment, BOOL bAlive)> ONALIVE;
    typedef std::function<void(void* pEiuipment, int code)> ONDATACHANGED;
@@ -50,6 +51,7 @@
    typedef std::function<void(void* pEiuipment, void* pReport)> ONVCREVENTREPORT;
    typedef std::function<BOOL(void* pEiuipment, CJobDataB* pJobDataB)> ONPREFETCHEDOUTJOB;
    typedef std::function<BOOL(void* pEiuipment, CJobDataB* pJobDataB, short& putSlot)> ONPRESTOREDJOB;
    typedef std::function<void(void* pEiuipment, PROCESS_STATE state)> ONPROCESSSTATE;
    typedef struct _EquipmentListener
    {
        ONALIVE                onAlive;
@@ -59,6 +61,7 @@
        ONVCREVENTREPORT    onVcrEventReport;
        ONPREFETCHEDOUTJOB    onPreFethedOutJob;
        ONPRESTOREDJOB        onPreStoredJob;
        ONPROCESSSTATE        onProcessStateChanged;
    } EquipmentListener;
@@ -119,6 +122,8 @@
        virtual BOOL onPreStoredJob(int port, CJobDataB* pJobDataB, short& putSlot);
        virtual int onStoredJob(int port, CJobDataB* pJobDataB);
        virtual int onProcessData(CProcessData* pProcessData);
        virtual int onSendAble();
        virtual int onProcessStateChanged(PROCESS_STATE state);
        virtual int getIndexerOperationModeBaseValue();
        bool isAlarmStep(SERVO::CStep* pStep);
        bool isVcrEventStep(SERVO::CStep* pStep);
@@ -136,7 +141,7 @@
        int clearCimMessage(short id, short nTouchPanelNo);
        int setDateTime(short year, short month, short day, short hour, short minute, short second);
        int setDispatchingMode(DISPATCHING_MODE mode, ONWRITED onWritedBlock = nullptr);
        int indexerOperationModeChange(IDNEXER_OPERATION_MODE mode, ONWRITED onWritedBlock = nullptr);
        int indexerOperationModeChange(IDNEXER_OPERATION_MODE mode, ONWRITEDRET onWritedRetBlock);
@@ -171,16 +176,16 @@
        // èŽ·å–çŽ»ç’ƒç‰©æ–™
        CGlass* getGlassFromSlot(int slotNo);
        CGlass* getGlassWithCassette(int cassetteSequenceNo, int jobSequenceNo);
        CGlass* getAnyGlass();
        CGlass* getGlass(const char* pszGlassId);
        CJobDataS* getJobDataSWithCassette(int cassetteSequenceNo, int jobSequenceNo);
        // éªŒè¯çŽ»ç’ƒå’Œæ§½æ˜¯å¦åŒ¹é…
        BOOL ValidateGlassSlotMatch();
        // æ˜¯å¦æœ‰çŽ»ç’ƒ
        BOOL hasGlass();
        // èŽ·å–æŒ‡å®šID的glass
        CGlass * getGlass(const char* pszGlassId);
        // æŒ‡å®šæ§½ä½æ˜¯å¦å¯ä»¥æ”¾ç½®çŽ»ç’ƒ
        BOOL canPlaceGlassInSlot(const short slotIndex);
@@ -218,13 +223,9 @@
        int decodeVCREventReport(CStep* pStep, const char* pszData, size_t size);
        int decodePanelDataReport(CStep* pStep, const char* pszData, size_t size);
        int decodeFacDataReport(CStep* pStep, const char* pszData, size_t size);
        int addJobDataB(CJobDataB* pJobDataB);
        int removeJobDataB(int nCassetteSequenceNo, int nJobSequenceNo);
        CJobDataB* getJobDataB(int nCassetteSequenceNo, int nJobSequenceNo);
        int addJobDataS(CJobDataS* pJobDataS);
        int removeJobDataS(int nCassetteSequenceNo, int nJobSequenceNo);
        CJobDataS* getJobDataS(int nCassetteSequenceNo, int nJobSequenceNo);
        BOOL compareJobDataB(CJobDataB* pJobDataB1, CJobDataB* pJobDataB2);
        int decodeJobDataRequest(CStep* pStep, const char* pszData, size_t size);
        BOOL compareJobData(CJobDataB* pJobDataB, CJobDataS* pJobDataS);
        void setProcessState(PROCESS_STATE state);
    protected:
        EquipmentListener m_listener;
@@ -256,11 +257,10 @@
        int m_nBaseAlarmId;
        CRecipesManager m_recipesManager;
        CSlot m_slot[SLOT_MAX];
        PROCESS_STATE m_processState;
    private:
        CEquipment* m_pArm;
        std::list<CJobDataS> m_listJobDataS;
        std::list<CJobDataB> m_listJobDataB;
    };
}
SourceCode/Bond/Servo/CGlass.cpp
@@ -108,8 +108,6 @@
                m_pPath->serialize(ar);
            }
            char temp[JOBDATAS_SIZE] = { 0 };
            m_jobDataB.serialize(temp, JOBDATAB_SIZE);
            ar.Write(temp, JOBDATAB_SIZE);
            m_jobDataS.serialize(temp, JOBDATAS_SIZE);
            ar.Write(temp, JOBDATAS_SIZE);
            ar << (ULONGLONG)m_pBuddy;
@@ -131,8 +129,6 @@
                m_pPath->serialize(ar);
            }
            char temp[JOBDATAS_SIZE];
            ar.Read(temp, JOBDATAB_SIZE);
            m_jobDataB.unserialize(temp, JOBDATAB_SIZE);
            ar.Read(temp, JOBDATAS_SIZE);
            m_jobDataS.unserialize(temp, JOBDATAS_SIZE);
            ar >> ullPath;    m_pBuddy = (CGlass*)ullPath;
@@ -141,21 +137,16 @@
        }
    }
    void CGlass::setJobDataB(CJobDataB* pJobDataB)
    {
        m_jobDataB.copy(pJobDataB);
    }
    CJobDataB* CGlass::getJobDataB()
    {
        return &m_jobDataB;
    }
    void CGlass::setJobDataS(CJobDataS* pJobDataS)
    {
        m_jobDataS.copy(pJobDataS);
    }
    void CGlass::updateJobDataS(CJobDataS* pJobDataS)
    {
        m_jobDataS.update(pJobDataS);
    }
    CJobDataS* CGlass::getJobDataS()
    {
        return &m_jobDataS;
SourceCode/Bond/Servo/CGlass.h
@@ -28,9 +28,8 @@
        CPath* getPath();
        void addPath(unsigned int nEqId, unsigned int nUnit);
        void serialize(CArchive& ar);
        void setJobDataB(CJobDataB* pJobDataB);
        CJobDataB* getJobDataB();
        void setJobDataS(CJobDataS* pJobDataS);
        void updateJobDataS(CJobDataS* pJobDataS);
        CJobDataS* getJobDataS();
        BOOL setBuddy(CGlass* pGlass);
        BOOL forceSetBuddy(CGlass* pGlass);
@@ -43,7 +42,6 @@
        MaterialsType m_type;
        std::string m_strID;
        CPath* m_pPath;
        CJobDataB m_jobDataB;
        CJobDataS m_jobDataS;
        CGlass* m_pBuddy;
        std::string m_strBuddyId;
SourceCode/Bond/Servo/CJobDataS.cpp
@@ -88,6 +88,51 @@
        m_pOwner = pScr->m_pOwner;
    }
    void CJobDataS::update(CJobDataS* pScr)
    {
        // m_nCassetteSequenceNo = pScr->m_nCassetteSequenceNo;
        // m_nJobSequenceNo = pScr->m_nJobSequenceNo;
        m_strLotId = pScr->m_strLotId;
        m_strProductId = pScr->m_strProductId;
        m_strOperationId = pScr->m_strOperationId;
        // m_strGlass1Id = pScr->m_strGlass1Id;
        m_strGlass2Id = pScr->m_strGlass2Id;
        m_nJobType = pScr->m_nJobType;
        m_nMaterialsType = pScr->m_nMaterialsType;
        m_nProductType = pScr->m_nProductType;
        m_nDummyType = pScr->m_nDummyType;
        m_nSkipFlag = pScr->m_nSkipFlag;
        m_nProcessFlag = pScr->m_nProcessFlag;
        m_nProcessResonCode = pScr->m_nProcessResonCode;
        m_nLastGlassFlag = pScr->m_nLastGlassFlag;
        m_nFirstGlassFlag = pScr->m_nFirstGlassFlag;
        m_nQTime[0] = pScr->m_nQTime[0];
        m_nQTime[1] = pScr->m_nQTime[1];
        m_nQTime[2] = pScr->m_nQTime[2];
        m_nQTimeOverFlag = pScr->m_nQTimeOverFlag;
        m_nMasterRecipe = pScr->m_nMasterRecipe;
        m_strProductRecipeId = pScr->m_strProductRecipeId;
        m_strPCode = pScr->m_strPCode;
        m_strUseType = pScr->m_strUseType;
        m_strPanelMeasure = pScr->m_strPanelMeasure;
        m_nMode = pScr->m_nMode;
        m_nSlotUnitSelectFlag = pScr->m_nSlotUnitSelectFlag;
        m_nSourcePortNo = pScr->m_nSourcePortNo;
        m_nSourceSlotNo = pScr->m_nSourceSlotNo;
        m_nTargetPortNo = pScr->m_nTargetPortNo;
        m_nTargetSlotNo = pScr->m_nTargetSlotNo;
        m_pOwner = pScr->m_pOwner;
    }
    CJobDataB& CJobDataS::getJobDataB(CJobDataB& jobDataB)
    {
        jobDataB.setCassetteSequenceNo(this->getCassetteSequenceNo());
        jobDataB.setJobSequenceNo(this->getJobSequenceNo());
        jobDataB.setGlassId(this->getGlass1Id().c_str());
        return jobDataB;
    }
    void* CJobDataS::getOwner()
    {
        return m_pOwner;
SourceCode/Bond/Servo/CJobDataS.h
@@ -1,5 +1,6 @@
#pragma once
#include "CAttributeVector.h"
#include "CJobDataB.h"
#define JOBDATAS_SIZE        (256 * 2)
@@ -15,6 +16,8 @@
        void* getOwner();
        void setOwner(void* pOwner);
        void copy(CJobDataS* pScr);
        void update(CJobDataS* pScr);
        CJobDataB& getJobDataB(CJobDataB& jobDataB);
        int getCassetteSequenceNo();
        void setCassetteSequenceNo(int no);
        int getJobSequenceNo();
SourceCode/Bond/Servo/CLoadPort.cpp
@@ -22,6 +22,7 @@
        m_transferMode = TransferMode::AGVMode;
        m_bEnable = FALSE;
        m_bAutoChangeEnable = FALSE;
        m_nNextCassetteSequenceNo = 0;
    }
    CLoadPort::~CLoadPort()
@@ -57,30 +58,12 @@
    // å¿…须要实现的虚函数,在此初始化Slot信息
    void CLoadPort::initSlots()
    {
        m_slot[0].enable();
        m_slot[0].setPosition(m_nID);
        m_slot[0].setNo(1);
        m_slot[0].setName("Slot 1");
        m_slot[1].enable();
        m_slot[1].setPosition(m_nID);
        m_slot[1].setNo(2);
        m_slot[1].setName("Slot 2");
        m_slot[2].setPosition(m_nID);
        m_slot[2].enable();
        m_slot[2].setNo(3);
        m_slot[2].setName("Slot 3");
        m_slot[3].setPosition(m_nID);
        m_slot[3].enable();
        m_slot[3].setNo(4);
        m_slot[3].setName("Slot 4");
        m_slot[4].setPosition(m_nID);
        m_slot[4].enable();
        m_slot[4].setNo(5);
        m_slot[4].setName("Slot 5");
        m_slot[5].setPosition(m_nID);
        m_slot[5].enable();
        m_slot[5].setNo(6);
        m_slot[5].setName("Slot 6");
        for (int i = 0; i < SLOT_MAX; i++) {
            m_slot[i].enable();
            m_slot[i].setPosition(m_nID);
            m_slot[i].setNo(i + 1);
            m_slot[i].setName((std::string("Slot") + std::to_string(i+1)).c_str());
        }
    }
    void CLoadPort::initSteps()
@@ -365,6 +348,50 @@
                }
            }
        }
        {
            // Fetched Out Job Report #1~15
            char szBuffer[256];
            CEqReadStep* pStep = new CEqReadStep(0x5c31 + 18 * m_nIndex, 18 * 2,
                [&](void* pFrom, int code, const char* pszData, size_t size) -> int {
                    if (code == ROK && pszData != nullptr && size > 0) {
                        int port = (int)(__int64)((CEqReadStep*)pFrom)->getProp("Port");
                        if (port > 0) {
                            decodeFetchedOutJobReport((CStep*)pFrom, port, pszData, size);
                        }
                    }
                    return -1;
                });
            sprintf_s(szBuffer, "%s%d", STEP_EQ_FETCHED_OUT_JOBn, m_nIndex + 1);
            pStep->setName(szBuffer);
            pStep->setProp("Port", (void*)(__int64)(m_nIndex + 1));
            pStep->setWriteSignalDev(0x023 + m_nIndex);
            if (addStep(STEP_ID_FETCHED_OUT_JOB_REPORT1 + m_nIndex, pStep) != 0) {
                delete pStep;
            }
        }
        {
            // Store Job Report #1~15
            char szBuffer[256];
            CEqReadStep* pStep = new CEqReadStep(0x5b23 + 18 * m_nIndex, 18 * 2,
                [&](void* pFrom, int code, const char* pszData, size_t size) -> int {
                    if (code == ROK && pszData != nullptr && size > 0) {
                        int port = (int)(__int64)((CEqReadStep*)pFrom)->getProp("Port");
                        if (port > 0) {
                            decodeStoredJobReport((CStep*)pFrom, port, pszData, size);
                        }
                    }
                    return -1;
                });
            sprintf_s(szBuffer, "%s%d", STEP_EQ_STORED_JOBn, m_nIndex + 1);
            pStep->setName(szBuffer);
            pStep->setProp("Port", (void*)(__int64)(m_nIndex + 1));
            pStep->setWriteSignalDev(0x014 + m_nIndex);
            if (addStep(STEP_ID_STORE_JOB_REPORT1 + m_nIndex, pStep) != 0) {
                delete pStep;
            }
        }
    }
    void CLoadPort::onTimer(UINT nTimerid)
@@ -459,6 +486,16 @@
        Unlock();
        return pStep;
    }
    short CLoadPort::getNextCassetteSequenceNo()
    {
        m_nNextCassetteSequenceNo++;
        if (m_nNextCassetteSequenceNo >= 1000) {
            m_nNextCassetteSequenceNo = 0;
        }
        return (m_nIndex + 1) * 1000 + m_nNextCassetteSequenceNo;
    }
    void CLoadPort::setIndex(unsigned int index)
@@ -838,6 +875,8 @@
    void CLoadPort::onReceiveLBData(const char* pszData, size_t size)
    {
        __super::onReceiveLBData(pszData, size);
        static int type[] = { STEP_ID_PORT1_TYPE_CHANGE, STEP_ID_PORT2_TYPE_CHANGE,
            STEP_ID_PORT3_TYPE_CHANGE, STEP_ID_PORT4_TYPE_CHANGE };
        static int mode[] = { STEP_ID_PORT1_MODE_CHANGE, STEP_ID_PORT2_MODE_CHANGE,
@@ -1110,13 +1149,8 @@
    /*
     * ç”Ÿæˆæµ‹è¯•用的玻璃列表
     */
    int CLoadPort::testGenerateGlassList(MaterialsType type, const char* pszPrefix, int startSuffix)
    int CLoadPort::testGenerateGlassList(MaterialsType type)
    {
        static unsigned short nJobSequenceNo = 0;
        static unsigned short nCassetteSequenceNo = 0;
        nCassetteSequenceNo++;
        // å¦‚果非空就不生成了
        Lock();
        if (hasGlass()) {
@@ -1127,32 +1161,21 @@
        char szBuffer[64];
        int suffix = startSuffix;
        for (int i = 0; i < SLOT_MAX; i++) {
        for (int i = 0; i < 1; i++) {
            if (!m_slot[i].isEnable()) continue;
            CJobDataB jb;
            CJobDataS js;
            sprintf_s(szBuffer, "%s%d", pszPrefix, suffix++);
            jb.setGlassId(szBuffer);
            jb.setCassetteSequenceNo(nCassetteSequenceNo);
            jb.setJobSequenceNo(++nJobSequenceNo);
            js.setCassetteSequenceNo(getNextCassetteSequenceNo());
            js.setJobSequenceNo(m_slot[i].getNo());
            sprintf_s(szBuffer, 64, "%05d%05d", js.getCassetteSequenceNo(), js.getJobSequenceNo());
            js.setGlass1Id(szBuffer);
            js.setJobType(1);
            js.setMaterialsType((int)type);
            js.setCassetteSequenceNo(nCassetteSequenceNo);
            js.setJobSequenceNo(nJobSequenceNo);
            if (type == MaterialsType::G1) {
                js.setGlass1Id(szBuffer);
            }
            else if (type == MaterialsType::G2) {
                js.setGlass2Id(szBuffer);
            }
            CGlass* pGlass = theApp.m_model.m_glassPool.allocaGlass();
            pGlass->addPath(m_nID, 0);
            pGlass->processEnd(m_nID, 0);
            pGlass->setID(szBuffer);
            pGlass->setJobDataB(&jb);
            pGlass->setType(type);
            pGlass->setJobDataS(&js);
            m_slot[i].setContext(pGlass);
SourceCode/Bond/Servo/CLoadPort.h
@@ -39,6 +39,7 @@
        void localAutoChangeEnable(BOOL bEnable);
    public:
        short getNextCassetteSequenceNo();
        void setIndex(unsigned int index);
        unsigned int getIndex();
        BOOL isEnable();
@@ -54,7 +55,7 @@
        int getQTimeFlag();
        int getCassetteMappingState();
        int getCassetteStatus();
        int testGenerateGlassList(MaterialsType type, const char* pszPrefix, int startSuffix);
        int testGenerateGlassList(MaterialsType type);
    public:
        static std::string& getPortTypeDescription(PortType portType, std::string& strDescription);
@@ -89,6 +90,7 @@
        BOOL m_bEnable;
        BOOL m_bAutoChangeEnable;
        CPortStatusReport m_portStatusReport;
        int m_nNextCassetteSequenceNo;
    };
}
SourceCode/Bond/Servo/CMaster.cpp
@@ -1,6 +1,8 @@
#include "stdafx.h"
#include "Common.h"
#include "CMaster.h"
#include <future>
#include <vector>
namespace SERVO {
@@ -48,6 +50,7 @@
        m_ullRunTime = 0;
        m_state = MASTERSTATE::READY;
        m_pActiveRobotTask = nullptr;
        m_nLastError = 0;
        InitializeCriticalSection(&m_criticalSection);
    }
@@ -264,6 +267,13 @@
        return 0;
    }
    void CMaster::clearError()
    {
        m_nLastError = 0;
        m_strLastError = "";
        setState(MASTERSTATE::READY);
    }
    ULONGLONG CMaster::getRunTime()
    {
        if (m_state == MASTERSTATE::RUNNING)
@@ -325,8 +335,114 @@
            // å¦‚果状态为STARTING,开始工作并切换到RUNNING状态
            lock();
            if (m_state == MASTERSTATE::STARTING) {
                // å‘送indexerOperationModeChange到各个机台,成功后切换到RUNNING状态
                // å¦åˆ™åˆ‡æ¢åˆ°MSERROR状态
                int nRet;
                CEquipment* pEq[6] = { pEFEM, pBonder1, pBonder2, pBakeCooling,
                    pVacuumBake, pMeasurement};
                BOOL bIomcOk[7] = {FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE};
                std::vector<std::promise<void>> promises(6);
                std::vector<std::future<void>> futures;
                nRet = pEq[0]->indexerOperationModeChange(IDNEXER_OPERATION_MODE::Start,
                    [&](int writeCode, int retCode) -> void {
                        bIomcOk[0] = retCode == (int)RET::OK;
                        promises[0].set_value();
                        TRACE("a0001\n", writeCode, retCode);
                    });
                if (nRet != 0) {
                    LOGI("<Master>EFEM切换Start状态失败");
                    m_strLastError = "EFEM切换Start状态失败.";
                    goto WAIT;
                }
                futures.push_back(promises[0].get_future());
                /*
                nRet = pEq[1]->indexerOperationModeChange(IDNEXER_OPERATION_MODE::Start,
                    [&](int writeCode, int retCode) -> void {
                        bIomcOk[1] = retCode == (int)RET::OK;
                        promises[1].set_value();
                        TRACE("a0002\n");
                    });
                if (nRet != 0) {
                    LOGI("<Master>Bonder1切换Start状态失败");
                    m_strLastError = "Bonder1切换Start状态失败.";
                    goto WAIT;
                }
                futures.push_back(promises[1].get_future());
                nRet = pEq[2]->indexerOperationModeChange(IDNEXER_OPERATION_MODE::Start,
                    [&](int writeCode, int retCode) -> void {
                        bIomcOk[2] = retCode == (int)RET::OK;
                        promises[2].set_value();
                        TRACE("a0003\n");
                    });
                if (nRet != 0) {
                    LOGI("<Master>Bonder2切换Start状态失败");
                    m_strLastError = "Bonder2切换Start状态失败.";
                    goto WAIT;
                }
                futures.push_back(promises[2].get_future());
                nRet = pEq[3]->indexerOperationModeChange(IDNEXER_OPERATION_MODE::Start,
                    [&](int writeCode, int retCode) -> void {
                        bIomcOk[3] = retCode == (int)RET::OK;
                        promises[3].set_value();
                        TRACE("a0004\n");
                    });
                if (nRet != 0) {
                    LOGI("<Master>BakeCooling切换Start状态失败");
                    m_strLastError = "BakeCooling切换Start状态失败.";
                    goto WAIT;
                }
                futures.push_back(promises[3].get_future());
                nRet = pEq[4]->indexerOperationModeChange(IDNEXER_OPERATION_MODE::Start,
                    [&](int writeCode, int retCode) -> void {
                        bIomcOk[4] = retCode == (int)RET::OK;
                        promises[4].set_value();
                        TRACE("a0005\n");
                    });
                if (nRet != 0) {
                    LOGI("<Master>VacuumBake切换Start状态失败");
                    m_strLastError = "VacuumBake切换Start状态失败.";
                    goto WAIT;
                }
                futures.push_back(promises[4].get_future());
                nRet = pEq[5]->indexerOperationModeChange(IDNEXER_OPERATION_MODE::Start,
                    [&](int writeCode, int retCode) -> void {
                        bIomcOk[5] = retCode == (int)RET::OK;
                        promises[5].set_value();
                        TRACE("a0006\n");
                    });
                if (nRet != 0) {
                    LOGI("<Master>Measurement切换Start状态失败");
                    m_strLastError = "Measurement切换Start状态失败.";
                    goto WAIT;
                }
                futures.push_back(promises[5].get_future());
                */
WAIT:
                for (auto& f : futures) {
                    f.wait();  // é˜»å¡žç­‰å¾…对应设备完成
                }
                for (int i = 0; i < 6; i++) {
                    if (!bIomcOk[i]) {
                        bIomcOk[6] = FALSE;
                        LOGI("<Master>%s切换Start状态失败", pEq[i]->getName().c_str());
                    }
                }
                // æ£€æŸ¥çœ‹æ˜¯å¦éƒ½å·²ç»åˆ‡æ¢åˆ°START状态
                if (!bIomcOk[6]) {
                    unlock();
                    setState(MASTERSTATE::MSERROR);
                    continue;
                }
                unlock();
                Sleep(1000);
                setState(MASTERSTATE::RUNNING);
                continue;
            }
@@ -335,7 +451,49 @@
            // å¤„理完成当前事务后,切换到停止或就绪状态
            else if (m_state == MASTERSTATE::STOPPING) {
                unlock();
                Sleep(1000);
                LOGI("<Master>开始切换各设备到 Stop æ¨¡å¼...");
                std::vector<std::promise<void>> promises(6);
                std::vector<std::future<void>> futures;
                BOOL bIomcOk[7] = { FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE };
                int nRet;
                CEquipment* pEq[6] = { pEFEM, pBonder1, pBonder2, pBakeCooling,
                    pVacuumBake, pMeasurement };
                for (int i = 0; i < 1; ++i) {
                    nRet = pEq[i]->indexerOperationModeChange(IDNEXER_OPERATION_MODE::Stop,
                        [i, &promises, &bIomcOk](int writeCode, int retCode) -> void {
                            bIomcOk[i] = retCode == (int)RET::OK;
                            promises[i].set_value();
                            TRACE("s000%d: ret=%d\n", i + 1, retCode);
                        });
                    if (nRet != 0) {
                        LOGI("<Master>%s切换Stop状态发送失败", pEq[i]->getName().c_str());
                        m_strLastError = pEq[i]->getName() + "切换Stop状态发送失败.";
                        bIomcOk[i] = FALSE;
                        promises[i].set_value(); // é¿å… wait é˜»å¡ž
                    }
                    futures.push_back(promises[i].get_future());
                }
                for (auto& f : futures) {
                    f.wait();  // ç­‰å¾…所有完成
                }
                for (int i = 0; i < 6; ++i) {
                    if (!bIomcOk[i]) {
                        bIomcOk[6] = FALSE;
                        LOGI("<Master>%s切换Stop状态失败", pEq[i]->getName().c_str());
                    }
                }
                if (!bIomcOk[6]) {
                    setState(MASTERSTATE::MSERROR);
                    continue;
                }
                LOGI("<Master>所有设备成功切换到 Stop æ¨¡å¼");
                setState(MASTERSTATE::READY);
                continue;
            }
@@ -613,17 +771,6 @@
            // è¯»æ ‡å¿—位
            for (auto item : m_listEquipment) {
                //if (item->getID() == EQ_ID_Bonder1 ||
                //    item->getID() == EQ_ID_Bonder2) {
                //    const StationIdentifier& station = item->getStation();
                //    MemoryBlock& block = item->getReadBitBlock();
                //    int nRet = m_cclink.ReadData2(station, (DeviceType)block.type,
                //        block.start, block.size, block.buffer);
                //    if (0 == nRet) {
                //        item->onReceiveLBData(block.buffer, block.size);
                //    }
                //}
                const StationIdentifier& station = item->getStation();
                MemoryBlock& block = item->getReadBitBlock();
@@ -682,10 +829,10 @@
                if (m_pActiveRobotTask->getSrcPosition() == p->getID()) {
                    CGlass* pGlass = p->getGlassFromSlot(m_pActiveRobotTask->getSrcSlot());
                    if (pGlass != nullptr) {
                        CJobDataB* pJobDataBSrc = pGlass->getJobDataB();
                        if (pJobDataBSrc != nullptr
                            && pJobDataBSrc->getCassetteSequenceNo() == pJobDataB->getCassetteSequenceNo()
                            && pJobDataBSrc->getJobSequenceNo() == pJobDataB->getJobSequenceNo()) {
                        CJobDataS* pJobDataS = pGlass->getJobDataS();
                        if (pJobDataS != nullptr
                            && pJobDataS->getCassetteSequenceNo() == pJobDataB->getCassetteSequenceNo()
                            && pJobDataS->getJobSequenceNo() == pJobDataB->getJobSequenceNo()) {
                            bOk = TRUE;
                            LOGI("<CMaster>onPreFethedOutJob, å·²æ ¡éªŒæ•°æ®ä¸€è‡´æ€§.");
                        }
@@ -788,7 +935,9 @@
                unlock();
            }
        };
        listener.onProcessStateChanged = [&](void* pEquipment, PROCESS_STATE state) -> void {
            LOGI("<Master>onProcessStateChanged<%d>", (int)state);
        };
        pEquipment->setListener(listener);
        pEquipment->setCcLink(&m_cclink);
        m_listEquipment.push_back(pEquipment);
SourceCode/Bond/Servo/CMaster.h
@@ -16,11 +16,12 @@
namespace SERVO {
    enum MASTERSTATE {
    enum class MASTERSTATE {
        READY = 0,
        STARTING,
        RUNNING,
        STOPPING
        STOPPING,
        MSERROR
    };
    typedef std::function<void(void* pMaster, MASTERSTATE state)> ONMASTERSTATECHANGED;
@@ -55,6 +56,7 @@
        int term();
        int start();
        int stop();
        void clearError();
        ULONGLONG getRunTime();
        MASTERSTATE getState();
        unsigned DispatchProc();
@@ -122,6 +124,10 @@
        // å½“前任务和已完成任务列表
        CRobotTask* m_pActiveRobotTask;
        std::list< CRobotTask* > m_listTask;
        // é”™è¯¯ä»£ç 
        int m_nLastError;
        std::string m_strLastError;
    };
}
SourceCode/Bond/Servo/CMeasurement.cpp
@@ -239,7 +239,7 @@
        {
            // Received Job Report Upstream #1~9
            char szBuffer[256];
            for (int i = 0; i < 9; i++) {
            for (int i = 0; i < 1; i++) {
                CEqReadStep* pStep = new CEqReadStep(0x18c90 + 320 * i, 320 * 2,
                    [&](void* pFrom, int code, const char* pszData, size_t size) -> int {
                        if (code == ROK && pszData != nullptr && size > 0) {
@@ -263,7 +263,7 @@
        {
            // Sent Out Job Report Downstream #1~9
            char szBuffer[256];
            for (int i = 0; i < 9; i++) {
            for (int i = 0; i < 1; i++) {
                CEqReadStep* pStep = new CEqReadStep(0x18000 + 320 * i, 320 * 2,
                    [&](void* pFrom, int code, const char* pszData, size_t size) -> int {
                        if (code == ROK && pszData != nullptr && size > 0) {
@@ -287,7 +287,7 @@
        {
            // Fetched Out Job Report #1~15
            char szBuffer[256];
            for (int i = 0; i < 15; i++) {
            for (int i = 0; i < 1; i++) {
                CEqReadStep* pStep = new CEqReadStep(0x19c31 + 18 * i, 18 * 2,
                    [&](void* pFrom, int code, const char* pszData, size_t size) -> int {
                        if (code == ROK && pszData != nullptr && size > 0) {
@@ -311,7 +311,7 @@
        {
            // Stored Job Report #1~15
            char szBuffer[256];
            for (int i = 0; i < 15; i++) {
            for (int i = 0; i < 1; i++) {
                CEqReadStep* pStep = new CEqReadStep(0x19b23 + 18 * i, 18 * 2,
                    [&](void* pFrom, int code, const char* pszData, size_t size) -> int {
                        if (code == ROK && pszData != nullptr && size > 0) {
SourceCode/Bond/Servo/CPageGraph2.cpp
@@ -212,25 +212,24 @@
        else if (nCmd == ID_EQSGRAPHITEM_TEST1) {
            BOOL bTestGenerate = FALSE;
            SERVO::CEquipment* pEquipment = (SERVO::CEquipment*)pItem->pData;
            if (pEquipment->getID() == EQ_ID_LOADPORT1 && !pEquipment->hasGlass()) {
                ((SERVO::CLoadPort*)pEquipment)->testGenerateGlassList(SERVO::MaterialsType::G1,
                    "P20250320G1X", 1);
            if (pEquipment->getID() == EQ_ID_LOADPORT4 && !pEquipment->hasGlass()) {
                ((SERVO::CLoadPort*)pEquipment)->testGenerateGlassList(SERVO::MaterialsType::G1);
                bTestGenerate = TRUE;
            }
            else if (pEquipment->getID() == EQ_ID_LOADPORT2 && !pEquipment->hasGlass()) {
                ((SERVO::CLoadPort*)pEquipment)->testGenerateGlassList(SERVO::MaterialsType::G2,
                    "P20250320G2X", 1);
            /*
            else if (pEquipment->getID() == EQ_ID_LOADPORT1 && !pEquipment->hasGlass()) {
                ((SERVO::CLoadPort*)pEquipment)->testGenerateGlassList(SERVO::MaterialsType::G2);
                bTestGenerate = TRUE;
            }
            */
            if (!bTestGenerate) {
                SERVO::CRobotTask* pTask = theApp.m_model.getMaster().getActiveRobotTask();
                if (pTask != nullptr) {
                    SERVO::CGlass* pGlass = (SERVO::CGlass*)pTask->getContext();
                    SERVO::CJobDataB* pJobDataB = pGlass->getJobDataB();
                    SERVO::CJobDataS* pJobDataS = pGlass->getJobDataS();
                    if (pJobDataB != nullptr && pJobDataS != nullptr) {
                        pEquipment->onFetchedOutJob(0, pJobDataB);
                    if (pJobDataS != nullptr) {
                        SERVO::CJobDataB jobDataB;
                        pEquipment->onFetchedOutJob(0, &pJobDataS->getJobDataB(jobDataB));
                        pEquipment->onSentOutJob(0, pJobDataS);
                    }
                }
@@ -242,12 +241,12 @@
            if (pArm != nullptr) {
                SERVO::CGlass* pGlass = pArm->getAnyGlass();
                if (pGlass != nullptr) {
                    SERVO::CJobDataB* pJobDataB = pGlass->getJobDataB();
                    SERVO::CJobDataS* pJobDataS = pGlass->getJobDataS();
                    if (pJobDataB != nullptr && pJobDataS != nullptr) {
                    if (pJobDataS != nullptr) {
                        pEquipment->onReceivedJob(0, pJobDataS);
                        Sleep(600);
                        pEquipment->onStoredJob(0, pJobDataB);
                        SERVO::CJobDataB jobDataB;
                        pEquipment->onStoredJob(0, &pJobDataS->getJobDataB(jobDataB));
                    }
                }
            }
SourceCode/Bond/Servo/CReadStep.cpp
@@ -218,4 +218,13 @@
        return 0;
    }
    int CReadStep::setReturnData(const char* pszData, unsigned int size)
    {
        ASSERT(size < 1024);
        memcpy(m_szReturnBuf, pszData, size);
        m_nReturnDataSize = size;
        return 0;
    }
}
SourceCode/Bond/Servo/CReadStep.h
@@ -23,6 +23,7 @@
        inline void nextStep();
        inline void resetStep();
        virtual int setReturnCode(short code);
        virtual int setReturnData(const char* pszData, unsigned int size);
    protected:
        HANDLE m_hWorkThreadHandle;
SourceCode/Bond/Servo/CRobotCmdTestDlg.cpp
@@ -270,6 +270,8 @@
void CRobotCmdTestDlg::AppendLogLineRichStyled(const CString& content, COLORREF color /*= RGB(0, 0, 0)*/)
{
    if (!::IsWindow(GetSafeHwnd())) return;
    // æ—¶é—´æˆ³
    CString timestamp;
    CTime now = CTime::GetCurrentTime();
SourceCode/Bond/Servo/CRobotTask.cpp
@@ -227,7 +227,7 @@
        ASSERT(m_pEFEM);
        m_state = ROBOT_TASK_STATE::Picking;
        m_pEFEM->robotSendMoveToGet(m_robotCmdParam->sequenceNo,
        m_pEFEM->robotSendGet(m_robotCmdParam->sequenceNo,
            m_robotCmdParam[ACTION_PICK].armNo,
            m_robotCmdParam[ACTION_PICK].getPosition,
            m_robotCmdParam[ACTION_PICK].getSlotNo,
SourceCode/Bond/Servo/CVacuumBake.cpp
@@ -239,7 +239,7 @@
        {
            // Received Job Report Upstream #1~9
            char szBuffer[256];
            for (int i = 0; i < 9; i++) {
            for (int i = 0; i < 1; i++) {
                CEqReadStep* pStep = new CEqReadStep(0x14c90 + 320 * i, 320 * 2,
                    [&](void* pFrom, int code, const char* pszData, size_t size) -> int {
                        if (code == ROK && pszData != nullptr && size > 0) {
@@ -263,7 +263,7 @@
        {
            // Sent Out Job Report Downstream #1~9
            char szBuffer[256];
            for (int i = 0; i < 9; i++) {
            for (int i = 0; i < 1; i++) {
                CEqReadStep* pStep = new CEqReadStep(0x14000 + 320 * i, 320 * 2,
                    [&](void* pFrom, int code, const char* pszData, size_t size) -> int {
                        if (code == ROK && pszData != nullptr && size > 0) {
@@ -287,7 +287,7 @@
        {
            // Fetched Out Job Report #1~15
            char szBuffer[256];
            for (int i = 0; i < 15; i++) {
            for (int i = 0; i < 1; i++) {
                CEqReadStep* pStep = new CEqReadStep(0x15c31 + 18 * i, 18 * 2,
                    [&](void* pFrom, int code, const char* pszData, size_t size) -> int {
                        if (code == ROK && pszData != nullptr && size > 0) {
@@ -311,7 +311,7 @@
        {
            // Stored Job Report #1~15
            char szBuffer[256];
            for (int i = 0; i < 15; i++) {
            for (int i = 0; i < 1; i++) {
                CEqReadStep* pStep = new CEqReadStep(0x15b23 + 18 * i, 18 * 2,
                    [&](void* pFrom, int code, const char* pszData, size_t size) -> int {
                        if (code == ROK && pszData != nullptr && size > 0) {
SourceCode/Bond/Servo/CWriteStep.cpp
@@ -55,6 +55,18 @@
        m_nWriteSignalDev = dev;
    }
    void CWriteStep::setRetDataDev(int dev, int size)
    {
        m_nReturnDevNo = dev;
        m_nReturnDataSize = size;
    }
    int CWriteStep::getReturnData(const char*& pszData)
    {
        pszData = m_szReturnBuf;
        return m_nReturnDataSize;
    }
    void CWriteStep::onRecvSignal(BOOL bSignal)
    {
        Lock();
@@ -111,6 +123,18 @@
                    goto RESET;
                }
                ResetEvent(m_hRecvSignalOn);
                // 3.9读数据,如果有
                if (m_nReturnDataSize > 0) {
                    int nRet = m_pCclink->ReadData2(m_station, DeviceType::W, m_nReturnDevNo,
                        (long)min(READ_BUFFER_MAX, m_nReturnDataSize), m_szReturnBuf);
                    if (0 != nRet) {
                        LOGI("<CEqReadStep>Read return data error.");
                        onReadRetDataError();
                        return -1;
                    }
                }
                // 4.дOFF
@@ -196,4 +220,9 @@
    {
        return 0;
    }
    int CWriteStep::onReadRetDataError()
    {
        return 0;
    }
}
SourceCode/Bond/Servo/CWriteStep.h
@@ -19,8 +19,14 @@
        virtual void getAttributeVector(CAttributeVector& attrubutes);
        virtual int onComplete();
        virtual int onTimeout();
        virtual int onReadRetDataError();
        inline void nextStep();
        inline void resetStep();
        virtual void setRetDataDev(int dev, int size);
    public:
        int getReturnData(const char*& pszData);
    protected:
        HANDLE m_hWorkThreadHandle;
@@ -33,6 +39,12 @@
        char m_szBuffer[1024];
        int m_nWriteDataSize;
        int m_nWriteDevNo;
    protected:
        // return code or data
        char m_szReturnBuf[1024];
        int m_nReturnDataSize;
        int m_nReturnDevNo;
    };
}
SourceCode/Bond/Servo/Common.h
@@ -41,6 +41,7 @@
#define CR_MSGBOX_MESSAGE                    RGB(200, 216, 246)
#define TOP_TOOLBAR_BACKGROUND                RGB(240, 240, 240)    
#define STATUSBAR_BK_NORMAL                    RGB(195, 195, 195)
#define STATUSBAR_BK_STARTING                RGB(58, 127, 78)
#define STATUSBAR_BK_RUNNING                RGB(34, 177, 76)
#define STATUSBAR_BK_ALARM                    RGB(255, 127, 39)
@@ -218,7 +219,7 @@
#define STEP_EQ_STORED_JOB15            _T("EQStoredJobReport15")
#define STEP_EQ_DISPATCHINT_MODE_CHANGE    _T("EQDispatchingModeChangeCommand")
#define STEP_EFEM_ROBOT_CMD                _T("EFEMRobotCmd")
#define STEP_EFEM_IN_OP_MODE_CHANGE        _T("EFEMIndexerOperationModeChangeCommand")
#define STEP_EQ_IN_OP_MODE_CHANGE        _T("EQIndexerOperationModeChangeCommand")
#define STEP_PORT1_TYPE_CHANGE            _T("Port1TypeChange")
#define STEP_PORT2_TYPE_CHANGE            _T("Port2TypeChange")
#define STEP_PORT3_TYPE_CHANGE            _T("Port3TypeChange")
@@ -245,7 +246,7 @@
#define STEP_PORT4_CASSETTE_TYPE_CHANGE    _T("Port4CassetteTypeChange")
#define STEP_EQ_PANEL_DATA_REPORT        _T("EQPanelDataReport")
#define STEP_EQ_FAC_DATA_REPORT            _T("EQFacDataReport")
#define STEP_EFEM_PANEL_DATA_REQUEST    _T("EFEMPanelDataRequest")
/* Step ID */
#define STEP_ID_CIMMODE_CHANGED_CMD_REPLY        0x550
@@ -318,6 +319,8 @@
#define STEP_ID_FETCHED_OUT_JOB_REPORT13        0x5BB
#define STEP_ID_FETCHED_OUT_JOB_REPORT14        0x5BC
#define STEP_ID_FETCHED_OUT_JOB_REPORT15        0x5BD
#define STEP_ID_JOB_DATA_REQUEST                0x5C1
#define STEP_ID_PANEL_DATA_REQUEST                0x5D0
#define STEP_ID_PANEL_DATA_REPORT                0x5D1
#define STEP_ID_IN_OP_CMD_REPLY                    0x5F0
#define STEP_ID_DISPATCHING_MODE_CHANGE_REPLY    0x5F1
SourceCode/Bond/Servo/RecipeDeviceBindDlg.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,34 @@
// RecipeDeviceBindDlg.cpp: å®žçŽ°æ–‡ä»¶
//
#include "stdafx.h"
#include "Servo.h"
#include "afxdialogex.h"
#include "RecipeDeviceBindDlg.h"
// CRecipeDeviceBindDlg å¯¹è¯æ¡†
IMPLEMENT_DYNAMIC(CRecipeDeviceBindDlg, CDialogEx)
CRecipeDeviceBindDlg::CRecipeDeviceBindDlg(CWnd* pParent /*=nullptr*/)
    : CDialogEx(IDD_DIALOG_RECIPE_DEVICE_BIND, pParent)
{
}
CRecipeDeviceBindDlg::~CRecipeDeviceBindDlg()
{
}
void CRecipeDeviceBindDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialogEx::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CRecipeDeviceBindDlg, CDialogEx)
END_MESSAGE_MAP()
// CRecipeDeviceBindDlg æ¶ˆæ¯å¤„理程序
SourceCode/Bond/Servo/RecipeDeviceBindDlg.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,24 @@
#pragma once
#include "afxdialogex.h"
// CRecipeDeviceBindDlg å¯¹è¯æ¡†
class CRecipeDeviceBindDlg : public CDialogEx
{
    DECLARE_DYNAMIC(CRecipeDeviceBindDlg)
public:
    CRecipeDeviceBindDlg(CWnd* pParent = nullptr);   // æ ‡å‡†æž„造函数
    virtual ~CRecipeDeviceBindDlg();
// å¯¹è¯æ¡†æ•°æ®
#ifdef AFX_DESIGN_TIME
    enum { IDD = IDD_DIALOG_RECIPE_DEVICE_BIND };
#endif
protected:
    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV æ”¯æŒ
    DECLARE_MESSAGE_MAP()
};
SourceCode/Bond/Servo/Servo.rc
Binary files differ
SourceCode/Bond/Servo/Servo.vcxproj
@@ -317,6 +317,7 @@
    <ClInclude Include="PageTransferLog.h" />
    <ClInclude Include="PortConfigurationDlg.h" />
    <ClInclude Include="ProductionLogManager.h" />
    <ClInclude Include="RecipeDeviceBindDlg.h" />
    <ClInclude Include="RecipeManager.h" />
    <ClInclude Include="Resource.h" />
    <ClInclude Include="SECSRuntimeManager.h" />
@@ -455,6 +456,7 @@
    <ClCompile Include="PageTransferLog.cpp" />
    <ClCompile Include="PortConfigurationDlg.cpp" />
    <ClCompile Include="ProductionLogManager.cpp" />
    <ClCompile Include="RecipeDeviceBindDlg.cpp" />
    <ClCompile Include="RecipeManager.cpp" />
    <ClCompile Include="SECSRuntimeManager.cpp" />
    <ClCompile Include="SecsTestDlg.cpp" />
SourceCode/Bond/Servo/Servo.vcxproj.filters
@@ -168,6 +168,7 @@
    <ClCompile Include="UserManager.cpp" />
    <ClCompile Include="InputDialog.cpp" />
    <ClCompile Include="RecipeManager.cpp" />
    <ClCompile Include="RecipeDeviceBindDlg.cpp" />
  </ItemGroup>
  <ItemGroup>
    <ClInclude Include="AlarmManager.h" />
@@ -341,6 +342,7 @@
    <ClInclude Include="SystemLogManager.h" />
    <ClInclude Include="InputDialog.h" />
    <ClInclude Include="RecipeManager.h" />
    <ClInclude Include="RecipeDeviceBindDlg.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
@@ -9,6 +9,11 @@
#define SIGNAL_MAX                    8
#define ARM_ALL                        99
    enum class RET {
        OK = 1,
        NG,
    };
    enum class PortType {
        Loading = 1,
        Unloading,
@@ -149,6 +154,13 @@
        BOOL armState[2];
    } ROBOT_MONITORING_DATA, RMDATA;
    /* å·¥è‰º(加工处理)状态 */
    enum class PROCESS_STATE {
        Ready = 0,
        Processing,
        Complete,
        Error
    };
    /* EQ Data changed code */
#define EDCC_FETCHOUT_JOB                1000    /* È¡Æ¬ */
SourceCode/Bond/Servo/ServoDlg.cpp
@@ -190,6 +190,18 @@
                    GetRuntimeFormatText(strText, "");
                    m_pMyStatusbar->setRunTimeText((LPTSTR)(LPCTSTR)strText);
                }
                else if (state == SERVO::MASTERSTATE::STARTING) {
                    m_pMyStatusbar->setBackgroundColor(STATUSBAR_BK_STARTING);
                    m_pMyStatusbar->setForegroundColor(RGB(0, 0, 0));
                    m_pMyStatusbar->setRunTimeText("正在启动...");
                }
                else if (state == SERVO::MASTERSTATE::MSERROR) {
                    m_pTopToolbar->GetBtn(IDC_BUTTON_RUN)->EnableWindow(TRUE);
                    m_pTopToolbar->GetBtn(IDC_BUTTON_STOP)->EnableWindow(FALSE);
                    m_pMyStatusbar->setBackgroundColor(STATUSBAR_BK_ALARM);
                    m_pMyStatusbar->setForegroundColor(RGB(0, 0, 0));
                    m_pMyStatusbar->setRunTimeText("启动失败.");
                }
                else if (state == SERVO::MASTERSTATE::RUNNING) {
                    m_pTopToolbar->GetBtn(IDC_BUTTON_RUN)->EnableWindow(FALSE);
                    m_pTopToolbar->GetBtn(IDC_BUTTON_STOP)->EnableWindow(TRUE);
@@ -856,14 +868,22 @@
{
    int id = (int)lParam;
    if (id == IDC_BUTTON_RUN) {
        theApp.m_model.getMaster().start();
        m_pTopToolbar->GetBtn(IDC_BUTTON_RUN)->EnableWindow(FALSE);
        if (theApp.m_model.getMaster().getState() == SERVO::MASTERSTATE::MSERROR) {
            AfxMessageBox("当前有机台发生错误,不能启动,请确认解决问题后再尝试重新启动!");
        }
        else {
            if (theApp.m_model.getMaster().start() == 0) {
                m_pTopToolbar->GetBtn(IDC_BUTTON_RUN)->EnableWindow(FALSE);
            }
        }
    }
    else if (id == IDC_BUTTON_STOP) {
        theApp.m_model.getMaster().stop();
        m_pTopToolbar->GetBtn(IDC_BUTTON_STOP)->EnableWindow(FALSE);
        if (theApp.m_model.getMaster().stop() == 0) {
            m_pTopToolbar->GetBtn(IDC_BUTTON_STOP)->EnableWindow(FALSE);
        }
    }
    else if (id == IDC_BUTTON_ROBOT) {
        theApp.m_model.getMaster().clearError();
        SERVO::CEFEM* pEFEM = (SERVO::CEFEM*)theApp.m_model.getMaster().getEquipment(EQ_ID_EFEM);
        CRobotCmdTestDlg dlg;
        dlg.SetEFEM(pEFEM);
SourceCode/Bond/Servo/resource.h
Binary files differ